人様の丸写しでなく、なるべくデータ・シートだけでいろいろやってみようとするコーナーの2回目はTimer2、使うPICはPIC16F1827だ。
早速データ・シートで「Timer2」を検索すると以下のように書いてある。
Period Register, Prescaler そして Postscaler があると。
そして、後ではまったので赤線を引いておいたのだが、Timer2は「Peripheral」な機能だ。
設定の必要なレジスターを調べていく。
このPICにはTimer2,4,6があるらしく、TMRxに対してPeriod RegisterならPRxと表記されているらしい。
クロックを4分の1にしたものがタイマーに入り、プリスケーラー(T2CKPS)は1, 4, 16のいずれかを設定できて、Peropd register(PR2)の値とTMR2が等しくなると次への出力が生じる。
それがPostscalerへ送られるわけだが、1から16までの値をT2OUTPSで設定する。
割り込みが発生するとTMR2IFが設定されるが、その割り込みはTMR2IEを設定することで使用可能になる。
ここまで、出てきた順に並べると
TMR2, PR2, T2CKPS, TMR2IF, TMR2IE, T2OUTPS
の設定が必要だ。
前回の経験から、GIEの設定も必要なことは知っているので、それを含めてここまでをコードしてPICに書き込んでみたら、実は思った通りには動かなかった。
さらにInterruptの項目にもちゃんと目を通しておかなければいけない。
GIE, TMR2IE, PEIE の3つの設定が必要なことがわかる。
PEIEは上では登場していないが、実は動かなかった原因はPEIEを設定しなかったことにある。
if the Interrupt Enable bit of the interrupt event is contained in the PIEx registers
PIE2レジスターに含まれている割り込みを使う際にはPEIEの設定が必要だよ。
ということが書かれている。
確認したら、Timer0はPIExに含まれないためにPEIEの設定は不要だったので、Timer2も同じTimerだからというんで確認もせずにごっちゃにしていたようだ。
それで、一番最初の図にあえて線を引いた「Peripheral」な機能なんだよというのが効いてくる。
PEIEは何を隠そうその名も「Peripheral Interrupt Enable bit」なのだから。
という訳で、都合以下のような設定が必要になる。
INTCONbits.GIE = 1;//Global Interrupt Enable bit
INTCONbits.PEIE = 1;//Peripheral Interrupt Enable bit
PIE1bits.TMR2IE = 1;//TMR2 to PR2 match interrupt
T2CONbits.T2OUTPS = 0b1001;//Timer2 Postscaler Select bits (1:10)
T2CONbits.TMR2ON = 0b1;//Timer2 On bit
T2CONbits.T2CKPS = 0b10;//Timer2-type Clock Prescale Select bits (16)
TMR2 = 0x00;//Timer2 Module register
PR2 = 250;//Timer2 Period register
で、割り込みが発生すると、
PIR1bit.TMR2IF = 1;//Timer2 to PR2 Interrupt Flag bit
となるわけだ。
ちなみにこの例ではクロックが8MHzの想定で1秒を測るのに、
4 × 16 × 250 × 10 × 50 = 8000000
という計算、最後の50は通常のプログラムで繰り返す回数だ。
参考
「PIC12F1822 Timer0」