今回は、下の動画にあるような正確な時間を刻む時計を作っていきます。こんな記事もあります!割り込みPICなどのマイコンには、割り込みと呼ばれる機能が付いています。これは、その名の通り他のプログラムが動いている途中に違う処理を割り込ませるという処理をしてくれます。while文の中で常にLEDの点滅をする処理をしていたとしましょう。ここで、ボタンを押したらブザーを鳴らすという処理を追加したい場合、while文の中にif文を入れますね。これを実行してみると、非常に使い勝手が悪いことが分かります。LEDが点灯した時にボタンを押したとしましょう。すると、if文に到達するまで__delay_ms(1000)が2回ありますから、2秒は待っていないとブザーはなってくれません。できれば押した瞬間にブザーが鳴ってほしいですよね(それはそう)。これを実現するのが、割り込みです。具体的には、別の割り込み関数を用意しておいて、割り込み条件が満たされた場合即座にその関数に飛ぶという動作をします。割り込み条件は複数用意されています。先程示したピンの入力による割り込み。他にはTimerカウンタのオーバーフロー時の割り込みなどはよく使われます。今回は、正確なタイマーを作るので、Timer割り込みを使っていきます。Timer1PIC16F1938には、Timer1割り込み機能が付いています。Timer割り込みとは、もとから用意されているTMR1レジスタがオーバーフローしたときに割り込み関数に飛ぶ機能です。割り込み機能がオンになった瞬間から、自動的にTMR1レジスタがカウントアップしていきます。このカウントアップはクロック周波数数回に1回行われるので、逆算すれば正確な時間が数えられます。カウントアップは、他のプログラムが動いていようが関係なく確実に行われます。Timer割り込みと、なんだか難しい言葉が出てきましたが、動けばいいんです。プログラムの例を見てみましょう。}これが、割り込み処理の初期化関数です。T1CONは何秒に1回カウントアップするかを設定するレジスタです。Foscはクロック周波数です。クロックが32MHzの場合を考えてみます。11と設定しましょう。1クロックにかかる時間は1/32MHzです。aaは00,つまりFosc/4で、これは4クロックで1回カウントアップを表します。bbは11で8倍,つまりカウントアップする周期を8倍することになります。32クロックを要する設定です。1μs経つごとにカウントアップされます!「さっきからカウントアップって、いったい何がカウントアップされるんだよ...」とお思いでしょう。これが、TMR1レジスタです。長いのでTMR1HとTMR1Lに分かれています。TMR1は16bit,つまり0~65535までの値をとります。これが65535を超えた、つまりオーバーフローした時に割り込みがかかります。上のプログラムでは65536から10000を引いた数をデフォルト値としてTMR1レジスタに代入しています。10ms経ったところで割り込みがかかります。その後ろのTMR1IF等は、ほぼ呪文です。そのままコピペで問題ありません。TMR1IFに関しては後で少し説明があります。}これは、割り込みがかかった時に強制的に飛ばされる関数です。関数名の先頭にinterruptと付けることで割り込み関数になります。今回は、秒数を数えるintr_counterという定数を定義しました。割り込みがかかったら、まずしなければいけないのは割り込みの禁止です。しないと割り込み中に割り込まれてしまいます。0;とすればOKです。次に、割り込みがTimer1割り込みかどうかを調べます。TMR1IFレジスタに1が勝手に代入されています。これを、フラグが立つといいます。if文で確認したら、まずTMR1レジスタを巻き戻しましょう。同じように55536を入れればいいだけですね。次に、intr_counterをカウントアップします。この割り込み関数は10msごとに呼ばれるので、intr_counterは10ms刻みの時間を記録していきます。これが100,つまり1秒になった時、timerという変数をカウントアップします(timerは関数の前に定義されている必要あり)。これで、開始からの正確な時間をtimerという変数で取得できるようになりました!最後に、TMR1IFを0にしましょう(フラグを落とす、といいます)。これをしないと、この関数が終わってすぐにまた割り込み関数が呼び出されてしまいます。完成プログラム今回は、I2CLEDをPICで使うを参考にtimerの値をLCDに表示させてみました。下記のプログラムをコピペして書き込めば、正確な秒数がLCDに表示されるでしょう。いっても、実はクロックの製品誤差があるので、本当に正確にするにはTMR1から引く数を10000より少し増減させる必要があったりします。スマホのストップウォッチなどを横に置き、1時間計測→3600よりどれだけ外れているかを調べ、校正する等の方法もあります。}今回はある程度正確な時間を作りました。これを使えば、普段は電子蛍プログラムが常に動いているけれど、ある秒数経ったらブザーが鳴る目覚まし時計なんかも作れそうです。7時間寝ると決めているんだ!でも夜は少しLEDの点滅が欲しいなんて場合には、while文の中でLEDを点滅させておいて、中にif(timer==3600*7)という文を入れておきましょう。このif文の中にスピーカーを鳴らす命令を書いておけば、いい感じの目覚まし時計ができます。コメントをキャンセルメールアドレスが公開されることはありません。*サイト次回のコメントで使用するためブラウザーに自分の名前、メールアドレス、サイトを保存する。支援のお願いサイト維持のため、ご支援をお願いします。Wellington.。