Aruduinoの「MsTimer2」での100uS割込の実装方法についてメモとしてまとめました。
Arduino標準のMstimr2は簡単に動作するが、一番早い設定でも1ms以下での割込の設定が出来ないのが悩みどころ。
ネット調べるとFlextimerはマイクロ秒の設定が出来るらしいが、調べて見るとMstimer2流用して作ったらしく、1ms以上の設定が出来なかったり、今ひと使いずらい。
今回実装の対象にしたのは、オリジナルのArduinoボードでクロックは内部CR発振器動作の8MHzなので、ちょっとイレギュラーなボードですけど50usから5ms以上でMstimer2を使って良巧く動いた。
Mistimer2はAtmega328の8ビットタイマカウンタ2を使っていて、オーバーフロー割込発生でタイマー割込が起動する仕掛けになっている。
このライブラリのソースの詳しい解説があって実装にとても役立った。
いっそこのと全て自分でレジスタアクセスすれば良いかとも思ったけど、割込の記述とかはArduinoのほうが楽なので、小細工しながら100uS割込を実現する。
今回はMstimer2で指定できる“unsigned long ms”は1固定で動作させる。時間の設定は前置分周器(TCCR2B)の設定と計数値レジスタ(TCNT2)を操作しながら実現する。
今回使ったボードはクロック8MHzなので、100uSの時間計測のためには以下のTCCR2BとTCNT2は以下の組み合わせになる。
クロック:8.0MHz
周期:125ns
分周器の設定:1/32
分周後の周期:4us(TCCR2B=0x03)
100uSまでのカウント回数:25(TCNT2に割込の都度書込・・・調整必要)
具体的実装方法は以下
まずはタイマー初期化
MsTimer2::set(int_time, Tint); // 割込み間隔(timeは‘1’固定、Tintは割恋処理の関数)
タイマースタートは
MsTimer2::start()は使わなくてもうごくがおまじないだとおもって残した
TCCR2B = 0x03;(前置分周器を1/32でタイマースタートに変更)
割込毎の処理
void Tint() {
//---------------------------------
// カウンター初期値を毎回設定
//(カウンタソースは250KHzでT=4us、256-231=25で100uS)
TCNT2 = (TCNT2_val); //(TCNT2_valは下表のようにすると色々変えられる)
//-------------------------
(ほかの処理)
}
//prescaller:1/256(T=32us) 5ms --> 100
//prescaller:1/128(T=16us) 2ms --> 131
//prescaller:1/32(T=4us) 100us --> 231(12us調整で234)
//prescaller:1/32(T=4us) 200us --> 206(12us調整で209)
//prescaller:1/32(T=4us) 500us --> 131(12us調整で134)
//prescaller:1/32(T=4us) 1000us --> 6(12us調整で9)
//prescaller:1/8(T=1uS) 50us --> 206(15u調整で221)
//prescaller:1/8(T=1uS) 20us --> 236(割込処理の関係で動作?NG)
調整値が必要になったのは、割込発生後もカウントされ時間が経過していて割込処理の先頭行でカウンター値を変更するときには時間経過したカウント値を考慮して調整する必要があることがわかり実測で調整。