akira.keiのアイコン画像
akira.kei 2025年01月26日作成 (2025年01月26日更新) © GPL-3.0+
セットアップや使用方法 セットアップや使用方法 Lチカ Lチカ 閲覧数 105
akira.kei 2025年01月26日作成 (2025年01月26日更新) © GPL-3.0+ セットアップや使用方法 セットアップや使用方法 Lチカ Lチカ 閲覧数 105

8ピンPICのPIC16F18313を使う(その4)Timer0でLチカ

<前の記事 : 次の記事>

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サイクルとなった!

akira.keiのアイコン画像
機械系エンジニアだが電子工作を趣味としている。週末はひとりバーベキュー。
ログインしてコメントを投稿する