こんにちは。koraです。
今回はタイマ割り込みを実装します。割り込みとは、マイコンで実行中のプログラムに一時的に割り込んで、別の処理を実行する機能です。タイマ割り込みを使うことで、一定周期でセンサを読み取ったりモータに指示を出したりして、マイクロマウスをリアルタイムで制御することが可能になります。
タイマ割り込みの準備
init.c
Step7のinit.cからinit_cmt()関数をコピーして、自作プロジェクトのinit.cに貼り付けます。また、init_all()関数内にinit_cmt();を追加して、init_all()からタイマ割り込みの初期化を呼び出せるようにします。
CMTはコンペアマッチタイマと言い、一定周期で割り込み処理を行うことができる機能です。init_cmt()関数内ではCMT0~2の、3つのタイマを初期化しています。この初期化で、CMT0は1kHz、CMT1は4kHz、CMT2は2kHzで割り込みが発生する設定になります。モータの制御に使うのはCMT0です。CMT1とCMT2は今後センサーの処理に使用します。
intprg.c
init_cmt()の設定で、intprg.cファイル内のExcep_CMT0_CMI0()関数が1kHzで呼び出されるようになります。今後、多様な処理を割り込みの中で実行したいので、Excep_CMT0_CMI0()関数から、別の関数を呼び出して実際の処理を行います。
#pragma section IntPRGの下に、次の行を追加します。
extern int_cmt0();
そして、void Excep_CMT0_CMI0(void){ } を次のように書き換えます。
void Excep_CMT0_CMI0(void){ int_cmt0(); }
interrupt.c
「新しいファイルを追加」から、interrupt.cというファイルを作ります。今回はテストのため、下のような簡単な処理のみにします。(本番用のプログラムでは、速度と旋回速度を制御するコードに書き換えます。)
#include "iodefine.h" #include "glob_var.h" #include "portdef.h" void int_cmt0(void) { MOT_OUT_R =(short)(240.0 * Duty_r); MOT_OUT_L =(short)(240.0 * Duty_l); }
glob_var.hとglob_var.c
グローバル変数を複数のファイル間で共有する場合、ヘッダファイルでextern付きの宣言をして各ソースファイルにインクルードし、実態を持たせる1つのソースファイルでextern無しの定義します。
しかし、このサンプルプログラム(Step7)では何十個もグローバル変数を使います。ヘッダファイルとソースファイルに同じ変数名を何十個も書くのは面倒です。
そこで、マクロでexternの有り無しを制御し、実態を持たせるソースファイルにインクルードされたときのみexternが外れるようにします。
glob_var.hに、
#ifdef _GLOB_VAR #define GLOBAL #else #define GLOBAL extern #endif GLOBAL float Duty_r; // 出力のデューティ比 [%] GLOBAL float Duty_l; // 出力のデューティ比 [%]
と書きます。そして、glob_var.cの方に、
#define _GLOB_VAR #include "glob_var.h"
と書きます。
テスト
my_hm_starterkit.cファイルに、
#include "glob_var.h"
を追加して、main関数を次のように書き換えます。
init_all(); // 初期化 MOT_POWER_ON; // モータドライバの電源ON MOT_CWCCW_R = MOT_R_FORWARD; // モータの回転方向を指定 MOT_CWCCW_L = MOT_L_FORWARD; // モータの回転方向を指定 Duty_r = 0.5; // PWMのDuty設定 Duty_l = 0.5; // PWMのDuty設定
グローバル関数Duty_rとDuty_lに値が代入されることで、タイマ割り込みで呼び出されるint_cmt0関数に値が渡され、PWMとして出力されます。Duty_rとDuty_lの値を0.0~1.0の値に設定することによって、モータの回転速度が変化します。
次回
タイマ割り込みでモータが動かせるようになりました。エンコーダ、ジャイロ、光センサの情報を反映できるようにしたいところですが、その前に、センサの情報をPCに表示するため、シリアル通信を使えるようにしたいと思います。