黙々と仕事をしている最中に自分のデスクの電話が鳴ったとします。たいていの人は電話にでます。これが割り込みです。ある要因(電話着信)で現在実行中のプログラム(仕事)を一時中断して違うプログラム(電話の相手と話す)を実行することを割り込み処理といいます。
例えば、図1のように押しボタンがあって押された回数を表示するような装置のプログラムを考えてみましょう。
図1
最も簡単な方法は押しボタンスイッチを接続する端子を汎用入力端子に設定して、対応するポートデータレジスタの値を常に監視するプログラムが思いつくと思います。しかしながらいつ押されるともわからないスイッチの状態を監視し続けるのはいささか効率が悪いですね。
今回の演習では押しボタンを押したことを割り込み要因としてそのときだけカウントアップの処理をするようなプログラムを作成してみます。PUPPYには押しボタンはないのですが、ロータリエンコーダのカウント数を数えるのに割り込み処理が適しているのでそちらでやってみましょう。
PUPPYのロータリエンコーダの出力はP14,P15に接続されています。このP14,P15は汎用入出力端子として使用できるだけでなく、IRQ0,IRQ1という端子も兼ねています。IRQ端子は[ハードウェアマニュアル-概要-端子機能]を見ると外部割込み要求端子になっていて立ち上がり、立下がりのどちらかで割り込みをかけることができる端子ということになっています。このIRQ端子を割り込み要求端子として設定すればロータリエンコーダがどのくらい回ったかを割り込み処理で知ることができます。
ロータリエンコーダの出力パルスは本体基板の図2の穴からとることができます。オシロスコープがある方はその穴にプローブを当てると出力波形を見ることができます。波形がLOWのところはエンコーダディスクの穴のところがフォトインタラプタのスリットを通過しているときで穴が通り過ぎると波形はHIになりなります。図3のように車輪をゆっくりとまわすと波形の周期が長くなり、車輪を早く回すと周期が早くなります。
図2
図3
とりあえずこの波形の立ち下がりで割り込みをかけ、この割り込みの回数をカウントし、LEDに表示するプログラムを作成してみましょう。
まずINT_sample.lzhをダウンロードしていつものところに入れます。
図4
INT_sampleには以下のファイルが含まれます。(表1)
main.c | LED点灯プログラム |
start.src | マイコンのスタートアップルーチン |
make.bat | ビルド実行ファイル |
int_sample.sub | ビルド用SUBファイル |
3687s.h | H8/3687F用レジスタ定義ファイル |
36057s.h | H8/36057F用レジスタ定義ファイル |
36064s.h | H8/36064F用レジスタ定義ファイル |
36077.h | H8/36077F用レジスタ定義ファイル |
sci.h | シリアル通信用ヘッダ |
sci.c | シリアル通信用プログラム |
int.c | 割り込み関数 |
表1
まず表1のmain.cから説明していきます。(リスト1)
リスト1
14行目 :P14をIRQ0に設定します。これを設定しないとP14は単なる汎用入出力端子として機能します。
15行目 :IRQ0の割り込み要求を受け付けます。これを設定しないとIRQの割り込み要因になっても割り込みは発生しません。
16行目 :マイコンの初期設定では、NMI(ノンマスカブル割り込み)という割り込み以外はすべて受け付けない設定になっています。set_imask_ccrは
set_imask_ccr(0) CPUはすべての割り込み要求を受け付ける
set_imask_ccr(1) NMIを除く割り込み要求を受け付けない
となっていますので割り込み要求を受け付けるように設定します。
注:set_imask_ccrはmachine.hをインクルードしないと使えません。
int.cは今回の演習から新たに加わったものです。H8/tinyマイコンにはIRQ割り込みのような外部端子からの割り込みの他にタイマなどの内部モジュールからの割り込みなどがあり、int.cはそれらの割り込みが入ったときに実行される関数をまとめたものです。(リスト2)
リスト2
8行目〜20行目:
#pragma interrupt(xxx)
はxxxが割り込み関数であることを示します。
33行目:今回の割り込みの種類はIRQ0なのでここに割り込み時にしたい処理を書きます。
41行目:IRQ0の割り込み要求をクリアします。割り込み要求をクリアしないと割り込み要求が取り下げられずまたINT_IRQ0関数の中に戻ってきてしまい無限ループに陥ります。
このサンプルプログラムは電源を入れて車輪を回すと回した分だけLEDをカウントアップさせる単純なプログラムです。ビルドして確かめてみましょう。
このプログラムは車輪をどちらに回してもLEDはカウントアップします。これを改良して正回転のときにLEDをカウントアップ,逆回転の時にLEDをカウントダウンするプログラムを作成してみましょう。
車輪正回転時,逆回転時のロータリエンコーダA相,B相の出力は図5のとおりです。
図5
A相立ち下がりのときにB相がHIだったら正転
A相立ち下がりのときにB相がLOWだったら逆転