連載第10回で、センサー値を取得するプログラムを作成しました。今回は、それをベースに走行中に壁の有無を判断するプログラムを作成します。
走行中に常に壁をチェックするので、割り込み処理を使います。これまで「CMT0」で1msの割り込み処理をしてきました。この1ms間に4つのセンサー値を取得します。「LEDをONにし、センサー値をA/D変換して、LEDをOFFにする」を行うのに90μsかかります。4つのセンサー値を次々に取得すると、トータルで360μs間は他の処理が何もできなくなってしまいます。4つのセンサーで値を1度に取得すると、その間は他の処理が何もできなくなってしまいます。そこで、新たな割り込み処理「CMT1」を作成し、4つのセンサー値を0.25msごとに順次取得します。
それでは、センサー用の割り込み処理プログラムを作成しましょう。
まず、CMT1を使う準備です。連載第8回でCMT0を扱ったときと同様に、「intprg.c」の中のCMT1を追記し、使用できるようにします(ソースコード2)。これで「CMT1」のコンペアマッチ割り込みが発生した際に、「int_cmt1」関数が実行されます。
// 188 CMT1 CMI1 //void INT_CMT1_CMI1(void){/* sleep(); */} //CMT1割り込み(センサー) extern void int_cmt1(void); void INT_CMT1_CMI1(void){ int_cmt1(); }
続いて、「init.c」内の「init_cmd」関数に、CMT1の初期化処理記述を追加します(ソースコード3)。
void init_cmt(void) { (……中略……) //CMT1はセンサーチェック用タイマー CMT1.CMCSR.BIT.CMIE = 1; //割り込みを許可 CMT1.CMCSR.BIT.CKS = 0; //カウントクロックPφ/8=3MHz CMT1.CMCSR.BIT.CMF = 0; //フラグクリア CMT1.CMCOR = (3000/4)-1; //0.25msごとに割り込み // INTC.IPRJ.BIT._CMT1 = 0x0e; //割り込み優先度を次点に設定 (……中略……) // CMT.CMSTR.BIT.STR1 = 1; //CMT1カウント開始 // }
これでCMT1を使う準備ができました。次に画像1のフローチャートを参照して、「intrpt.c」にCMT1割り込み処理のint_cmt1関数を作成します(ソースコード4)。ここで使用するG_SensorRや他のグローバル変数は、「Mouse2012.h」で宣言したものを、「intrpt.h」で外部参照します。このとき、volatileを付けて宣言することに注意してください。「intrpt.h」には、タイマー1割り込みフラグ「CMT1_INT_F」の宣言も必要です。
/************************************************/ /* CMT1割り込み処理 (int_cmt1) */ /************************************************/ /* センサーチェック用タイマー割り込み(0.25ms)*/ /* 0:右壁チェック */ /* 1:左壁チェック */ /* 2:前右壁チェック */ /* 3:前左壁チェック */ /************************************************/ void int_cmt1(void) { //センサー用タイマー割り込み(0.25ms) static int state = 0; //読み込むセンサーのローテーション管理用変数 // CMT1_INT_F = 0; //フラグクリア // switch(state) { case 0: //右壁チェック G_SensorR = ctrl_adc_r(); //右センサー値取得 break; case 1: //左壁チェック G_SensorL = ctrl_adc_l(); //左センサー値取得 break; case 2: //前右壁チェック G_SensorFR = ctrl_adc_fr(); //前右センサー値取得 break; case 3: //前左壁チェック G_SensorFL = ctrl_adc_fl(); //前左センサー値取得 break; } // state++; //4回ごとに繰り返す if(state >= 4) { state = 0; } }
よし! これでセンサー用の割り込み処理はOKだ。
「CMT0」と「CMT1」。2つの割り込み処理を使うのがポイントなんですね。
そうなんだよ。4つのセンサー値を読み込む間も、マイクロマウスは走り続けているし、その間に他の処理を止めるわけにはいかないからね。
1度に4つの値を読まずに分割することで、待ち時間を分散しているんですね。
うん。そういうことだよ。
360μsって、ほんの一瞬って思っちゃうけど……。
そうだよね。でも、マイコンの処理スピードは速いからね〜。
“マイコンの世界”の時間感覚を意識してプログラミングするのが大事なんですね!
うん。それじゃあ、迷路走行のプログラムを作ろうか!
はーい。
Copyright © ITmedia, Inc. All Rights Reserved.