ここでは「発光ダイオードを光らせる」で作成した物を使用して、1秒ごとに点灯・消灯を繰り返すプログラムを作成します。回路図などは「発光ダイオードを光らせる」を参照してください。
1.メインプログラム
Timer0を使用して、割り込みを発生させ、1秒ごとに点灯・消灯を繰り返すようにします。「発光ダイオードを光らせる」と同様に初期設定を行います。
OSCCON = 0b01110000 ; // 内部クロック8MHz ANSELA = 0b00000000 ; // すべてデジタルI/Oに割当てる TRISA = 0b00001000 ; // RA3を入力とする PORTA = 0b00000000 ; // ピン状態初期化
続いて割り込みの設定を行います。詳しくは「PIC12F1822の割り込み処理について」を参照してください。
Timer0を有効にし、タイマの動作を1:8で使用する設定にします。
OPTION_REG = 0b00000010 ;// 0-2bitでタイマ0のクロックを1/8に設定
Timer0の初期値を156に設定します。
TMR0 = 156; // 初期カウンタ設定
Timer0の割り込みフラグを初期化します。
TMR0IF = 0; // タイマ割り込みフラグ初期化
Timer0を有効にします。
TMR0IE = 1; // タイマ割り込み有効
割り込みを有効にします。
GIE = 1; // 全割り込み有効
発光ダイオードはRA2に接続しているので、RA2を0にすると消灯、1にすると点灯します。今回は「g_led_flg」が真のとき点灯し、偽のとき消灯させます。割り込み処理で「g_led_flg」を変化させることで点灯・消灯を切り替えます。
for(;;) { if( g_led_flg ) { RA2 = 1; } else { RA2 = 0; } }
2.割り込み時のプログラム
割り込みが発生した際、呼び出される関数です。
- 割り込み関数宣言
「interrupt」を付けると割り込み発生時に呼び出される関数になります。 - Timer0による割り込みか判定
「TMR0IF 」が真のときがTimer0割り込み発生時です。 - 1秒経過したかの判定
Timer0割り込みが呼び出される度に「time_cnt」をカウントアップしていき、「time_cnt」が10000回を超えたときが約1秒になります。 - 1秒経過した時の処理
「g_led_flg」を反転させます(真であれば偽に、偽であれば真に変更)
「time_cnt」をゼロにする - Timer0の設定を初期化する
このまま何もしないで処理を抜けてしまうと、Timer0割り込みが発生しなくなります。なので初期値の設定と割り込みが発生するように設定します。
TMR0 = 156
TMR0IF = 0
void interrupt time0( void ) { if( TMR0IF ) { time_cnt++; if( time_cnt >= 10000 ) { g_led_flg = ~g_led_flg; // 反転 time_cnt = 0; } TMR0 = 156; // 初期カウンタ再設定 TMR0IF = 0; // タイマ割り込みフラグをクリアする } }
ソースコード
プログラムの全文を掲載します。
<注意>
本サイトの注意事項を確認してください。
ソースコードや回路図などを使用する場合、上記注意とともに、自己責任でお願いします。
3.動作確認
PICへ書き込んで動かしてみてください。問題がなければ約1秒で点灯・消灯を繰り返します。
<更新履歴>
新規作成:2015年4月4日
第2版:2016年9月30日:フォーマット変更(内容の変更はなし)
プログラムソースを参考にさせてもらいました。
ありがとうございます。
CONFIG2の設定
PLLENがONになっていたので、クロックが8MHzでなく32MHzではないかと思いました。
まだ自分は、初心者でして理解力がないので
教えてほしいのですが
1秒を出す計算が32/8で4MHzになるから1MHzにならないのではないだろうかと思ってしまったのですが、考え方が分からなくご教授いただけないでしょうか?
すみません。
まずこのプログラムは32MHzで動いています。
(3行目のコメント部分)
クロックが8MHzで4逓倍で動くので32MHzです。
計算方法ですが、Timer0のカウンタは強制的に1/4になります。
詳しくはページ内のリンクもありますが、
「PIC12F1822の割り込み処理について」を確認してください。
さらに詳しくはデータシートの「Timer0モジュール」の説明を確認してください。
ありがとうございます。
納得できました。