編集履歴一覧に戻る
akira.keiのアイコン画像

akira.kei が 2025年01月26日11時23分11秒 に編集

コメント無し

本文の変更

[<前の記事](https://elchika.com/article/dfdfb8fa-d432-4bcf-91ff-82bf3ab0bb46/) : [次の記事>](url) ## Timer0を使う PIC16F18313のTimer0は従来の8bitから16bitに拡張された。また8bitモードでも使えて、コンペアで割り込みできるようになった。 ![](https://camo.elchika.com/fccd6dbdb43ba04da462fa5b5f50fb5984384b07/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33363031626666382d633530632d343762382d613765362d3531663731393163323336642f64623534616335312d346534322d343163312d383564362d366364356333643263333330/) ## 割り込み周期 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でも安定して割り込みルーチンが呼ばれるようになった。ただしサイクル数は262080であり、12080サイクルだけ遅い

+

サイクル数が1サイクルずれるのはアセンブラではジャンプ命令のせいなので、「while(1) {}」のところを「while(1) {__nop()}」としたところ、Simulatorでも安定して割り込みルーチンが呼ばれるようになった。ただしLEDのONサイクル数は262080であり、12080サイクルだけ遅いままだ割り込みサイクルも5040サイクルであり、ここを解消する必要がある…