PIC16F1823-I/P を用いたLED点滅テスト(TMR0編)

前回「PIC16F1823-I/P を用いたLED点滅テスト」ではソフトウェアタイマーを使用してLEDを点滅するプログラムを作成しました。

このプログラムはあくまで動作確認用であり、現実のプログラムでこのような記述するのはナンセンスです。

PICマイコンには割り込み機能を持ったタイマーが搭載されているのですから、この機能を用いてLEDを点滅したいと思います。

 

回路図とブレットボードは前回と同じものです。

 

ただし、今回はPORT-C0をタイマーが割り込み発生した場合に確認できるよう、割り込みの都度信号を反転するよう割り込みプログラムに仕込んでいます。

 

まずは、タイマー割り込みプログラムを組み組んで動作確認します。

解説

108-109行目で、メイン/割り込みプログラムで使用する変数を宣言しています。

static unsigned char IOP_C = 0;
static unsigned int CNT_TMR0 = 0;

IOP_CはPORT Cをメインプログラムと割り込みプログラムとでシェアしますので、PORT Cの出力はどのようなものを出しているのかを共有するための変数です。

CNT_TMR0はタイマー割り込みが発生する都度単純にインクリメントする変数です。 時間カウントに使用できます。

 

タイマーの定数を設定しているのはメイン関数の238行目で設定しています。

タイマーの定数を考える場合、極力分解能を維持することが重要。

そのためにはTMR0レジスタが極力沢山カウントするようにプリスケーラーを設定するのが定石です。

タイマーのクロックは1ステートサイクルをクロックとしているので、源発信(ここでは32MHz)の4クロックがタイマークロックです。

TMR0はタイマーカウンターで、初期設定値からプリスケーラークロックでカウントアップして、255から0にオーバーフローとなったときにタイマー割り込みが発生します。

今回のタイマー割り込みは1msなので、32,000クロック(8000ステート)を必要とします。

この条件でより沢山のTMR0のカウンターをカウントするようにプリスケーラーを選択すると1:32、つまり32分周が適正値となりました。

OPTION_REG = 0b10000100;
TMR0 = 0x6;

計算してみると、プリスケーラーで32分周していますので、8,000ステート÷32分周=250 がタイマーカウンタでカウントする値です。

TMRはインクリメントして、オーバーフローしたときに割り込みが発生するので、256-250=6が設定値となります。

 

この内容でコンパイルして、PICKit3に接続したPIC16F1823にプログラムを焼きこんで実行し、オシロスロープでRC0端子を観測してみます。

 

ちゃんと1ms毎に端子がH/Lを繰り返しているのがわかります。

 

次に、LEDを点滅するようメインプログラム側にタイマー変数(CNT_TMR0)を観測して状態を変更するプログラムを記述します。

 

2016.08.08 追記  / HN なおさんよりメールにて指摘があり、割り込みプログラムでTMR0をリロードしていないバグがありました。

謹んでお詫び申します。

 

248行目からがそのプログラムとなります。

点滅周期はCNT_TMR0を50まで待っていますので、50msでLEDの点滅を実行しています。

 

ここで注意事項…

CNT_TMR0変数とIOP_C変数を操作、そしてPORTCにデータを書き込んでいるときは全体割り込みを制御するGIEレジスタを割り込み禁止にしています。 これはとても重要なことで、C言語では一行がマイコンの1命令ではなく複数命令に置き換えられます。 複数命令に置き換えられるということはそのどこかで割り込みが入ってくるということがあるということです。

そうすると、たとえばCNT_TMR0変数はINT型つまり16bitですから、8bitづつデータを読み書きしているときにタイマー割り込みが入ってきてCNT_TMR0変数を更新するという事態もありえます。 そのような不整合を発生させないためにも、割り込みプログラムで扱っている変数やレジスタを書換える場合は必ず割り込みプログラムが途中で割り込んでこない状態(つまり割り込み禁止状態)で実施する必要があります。

意外にこれに気がつかず割り込みプログラムの不具合を出すことは良くあることなので、より注意が必要です。

 

この内容でコンパイルして、PICKit3に接続したPIC16F1823にプログラムを焼きこんで実行し、オシロスロープでRC0/RC2端子を観測してみます。

CH1(青)はRC0で1msでH/Lしています。 CH2がRC2でLEDの点滅を読み取っています。

50ms毎にLEDがON/OFFしています。

 

今回のタイマーTMR0を用いたLED点滅はこれで終了です。

タイマー割り込みはマイコン割り込みプログラムの中で最も多用しますし応用範囲も広いです。

また割り込みプログラムの基本をしっかり学べるものなので是非マスターしたいですね。

では。

TOP/電子工作の部屋にもどる