akira.kei が 2025年01月26日13時28分27秒 に編集
コメント無し
本文の変更
[<前の記事](https://elchika.com/article/dfdfb8fa-d432-4bcf-91ff-82bf3ab0bb46/) : [次の記事>](url)
[<前の記事](https://elchika.com/article/dfdfb8fa-d432-4bcf-91ff-82bf3ab0bb46/) : [次の記事>](https://elchika.com/article/6d8c83f9-8d83-4b0d-b7b1-069ef78248df/)
## Timer0を使う PIC16F18313のTimer0は従来の8bitから16bitに拡張された。また8bitモードでも使えて、コンペアで割り込みできるようになった。  ## 割り込み周期 1Hz周期でLEDを点滅させるなら、2Hz周期で割り込めば良い。Fosc/4が250kHzだとすると、プリスケーラで1/8(→31250Hz)、ポストスケーラで1/5(→6250Hz)、TMR0H=125でコンペアすると50Hz割り込みになり、割り込みルーチンの中で25カウントすると2HzでLEDのアクセスができる。 この割り込みルーチンは以下のようになる。 ``` unsigned char flg=0; unsigned char cnt=0; void __interrupt() isr(void) { if(TMR0IF) { TMR0IF=0; cnt++; if(cnt>25) { cnt=0; if(flg) { LATAbits.LATA2=1; LATAbits.LATA5=0; } else { LATAbits.LATA2=0; LATAbits.LATA5=1; } flg=1-flg; } } } ``` ## mainルーチン mainルーチンは以下のようになる。LEDピンの出力設定、TMR0の設定、割り込み許可を順に設定してあとはループするだけだ。 ``` #include <xc.h> #include "pragma_config.h" void main(void) { TRISAbits.TRISA2=0; TRISAbits.TRISA5=0; T0CON1bits.T0CS=0b010; // Fosc/4 T0CON1bits.T0CKPS=0b0011; // Prescaler 1/8 TMR0H=125; T0CON0bits.T0OUTPS=0b0100; // Postscaler 1/5 T0CON0bits.T0EN=1; PIR0bits.TMR0IF=0; PIE0bits.TMR0IE=1; INTCONbits.PEIE=1; INTCONbits.GIE=1; while(1) ; } ``` ## 不安定割り込み このようにTMR0のコンペア割り込み機能を使ったが、割り込みルーチンの呼び出し周期が安定しない。SimulatorのStopwatch機能を用いてサイクル数を確認してみると5039と5041サイクルを交互に繰り返している。つまり5000サイクル(20ms)で正確に割り込めていない。同じようにLEDのON周期を調べても262079と262081サイクルを繰り返し、本来の250000サイクルとは差異がある。 素直にdelay関数で調整した方が正確だ。 ## もしかしてnop サイクル数が1サイクルずれるのはアセンブラではジャンプ命令のせいなので、「while(1) {}」のところを「while(1) {__nop()}」としたところ、Simulatorでも安定して割り込みルーチンが呼ばれるようになった。ただしLEDのONサイクル数は262080であり、12080サイクルだけ遅いままだ。割り込みサイクルも5040サイクルであり、ここを解消する必要がある… 結局、TMR0H(コンペアレジスタ)をひとつ減らしてみたら(125→124)あっさりと本来の250000サイクルとなった!