さて、上記の関数で構造体に記憶させた内容を実際にH8/3048F-ONEに反映させる処理はリスト4〜7の関数で行います。
#define TRUE 1 #define FALSE 0 //---------------------------------------------------------------------- // DcmOn //---------------------------------------------------------------------- // [説明] // DCモータのON/OFFを設定します // [入力] // ch :DCモータを0,1で指定します // on :TRUE DCモータON // :FALSE DCモータOFF // [出力] // なし // [戻り値] // なし //---------------------------------------------------------------------- void DcmOn(int ch, int on) { if(ch == 0) { DcmSet[0].on = on; if(on) { ITU3.GRA = DcmSet[ch].trig; ITU3.GRB = DcmSet[ch].cycle; ITU3.TCNT = 0; ITU.TMDR.BIT.PWM3 = 1; ITU.TSTR.BIT.STR3 = 1; } else { ITU.TSTR.BIT.STR3 = 0; ITU.TMDR.BIT.PWM3 = 0; } } else if(ch == 1) { DcmSet[1].on = on; if(on) { ITU4.GRA = DcmSet[ch].trig; ITU4.GRB = DcmSet[ch].cycle; ITU4.TCNT = 0; ITU.TMDR.BIT.PWM4 = 1; ITU.TSTR.BIT.STR4 = 1; } else { ITU.TSTR.BIT.STR4 = 0; ITU.TMDR.BIT.PWM4 = 0; } } }
リスト4の関数の引数chが0であればDCモータ0への設定ということで、H8/3048F-ONEのITUチャネル3に関係したレジスタが更新されます。1であればチャネル4に関係したレジスタが更新されます。また、引数onがTRUEであれば、PWM波を出力するために必要な処理(GRA、GRBレジスタの更新、ITUのモードをPWMモードにする、ITUのカウントスタート)を行います。
リスト5〜7の3つの関数は、DCモータの動作許可/禁止を設定する関数(DcmSetEn())、DCモータにブレーキを掛ける関数(DcmSetBrake())、そしてDCモータの回転方向を決定する関数(DcmSetCw())です。DcmSetEn()はDC_EN0、1信号の、DcmSetBrake()はDC_BRK0、1信号の、そしてDcmSetCw()はDC_CW0、1信号のHigh/Lowを切り替える処理を行います。ここはいままでの連載で行ってきたポートを操作する処理なので特に問題はないと思います。ただしDcmSetCw()だけはターゲットボードを壊さないために、モータがすでにONのときは一度止めるという処理を加えています。
//---------------------------------------------------------------------- // DcmSetEn //---------------------------------------------------------------------- // [説明] // DCモータのEnableビットを設定します // [入力] // ch :設定するDCモータを0,1で指定します // enable :TRUEを指定するとDC_ENビットをLowにします // :DCモータは動作状態となります // :FALSEを指定するとDC_ENビットをHighします // :DCモータは停止状態となります //---------------------------------------------------------------------- void DcmSetEn(int ch, int enable) { if(ch == 0) { if(enable) PB.DR.BIT.B4 = 0; // DC Motor 0 EN bit ON else PB.DR.BIT.B4 = 1; // DC Motor 0 EN bit OFF } else { if(enable) PB.DR.BIT.B5 = 0; // DC Motor 1 EN bit ON else PB.DR.BIT.B5 = 1; // DC Motor 1 EN bit OFF } }
//---------------------------------------------------------------------- // DcmSetBrake //---------------------------------------------------------------------- // [説明] // DCモータのブレーキビットを設定します // [入力] // ch :設定するDCモータを0,1で指定します // brake :TRUEを指定するとDC_BRKビットをONします // :DCモータはブレーキONとなります // :FALSEを指定するとDC_BRKビットをOFFします // :DCモータはブレーキOFFとなります //---------------------------------------------------------------------- void DcmSetBrake(int ch, int brake) { if(ch == 0) { if(brake) PB.DR.BIT.B1 = 1; // DC Motor 0 BRK bit ON else PB.DR.BIT.B1 = 0; // DC Motor 0 BRK bit OFF } else { if(brake) PB.DR.BIT.B3 = 1; // DC Motor 1 BRK bit ON else PB.DR.BIT.B3 = 0; // DC Motor 1 BRK bit OFF } }
//---------------------------------------------------------------------- // DcmSetCw //---------------------------------------------------------------------- // [説明] // DCモータのCWビットを設定します // CWビットの設定によりDCモータの回転方向が変わります // 回転方向の変更は、DCモータがストップもしくはブレーキONの // 状態のときに行ってください // 動作中に回転方向を変えると、モータドライバに貫通電流が流れ、 // ICが破壊される可能性があります // [入力] // ch :設定するDCモータを0,1で指定します // cw :TRUEを指定するとDC_CWビットをHighにします // :FALSEを指定するとDC_CWビットをLowにします //---------------------------------------------------------------------- void DcmSetCw(int ch, int cw) { int on; if((ch!=0) && (ch!=1)) return; // モータ動作中の変更時はいったんモータを停止する on = DcmSet[ch].on; if(on) DcmOn(ch, FALSE); // CWビット設定 if(ch == 0) { if(cw) PB.DR.BIT.B6 = 1; // DC Motor 0 CW bit ON else PB.DR.BIT.B6 = 0; // DC Motor 0 CW bit OFF } else { if(cw) PB.DR.BIT.B7 = 1; // DC Motor 1 CW bit ON else PB.DR.BIT.B7 = 0; // DC Motor 1 CW bit OFF } // モータ再起動 if(on) DcmOn(ch, TRUE); }
以上の関数を組み合わせることで、DCモータの制御ができるようになっているはずです。例えばリスト8ではターゲットボードの電源を入れるとDCモータが延々と回るようになります。
void main(void) { // DCモータ初期化 DcmInit(); // 初期設定 DcmSetCycle(0, 10000, 50); // モータ0の周期=10ms、デューティ比=50% DcmSetCycle(1, 10000, 50); // モータ1の周期=10ms、デューティ比=50% DcmSetEn(0, TRUE); // DC_EN0をLowにする(Enable) DcmSetEn(1, TRUE); // DC_EN1をLowにする(Enable) DcmSetBrake(0, FALSE); // DC_BRK0をLowにする(ブレーキOFF) DcmSetBrake(1, FALSE); // DC_BRK1をLowにする(ブレーキOFF) DcmSetCw(0, FALSE); // DC_CW0をLowにする DcmSetCw(1, FALSE); // DC_CW1をLowにする DcmOn(0, TRUE); // DCモータ0を回転開始 DcmOn(1, TRUE); // DCモータ1を回転開始 while(1); // 無限ループ }
これだけでは少々物足りないかもしれません。もう少しモータに動きを与えようと思ったら、例えばwhileの無限ループの中でDcmSetCycle()関数を呼び出しデューティ比をいろいろと変えてみるということもできるでしょう。また、本連載ではまだ触れていませんが、ターゲットボードにはトグルスイッチなどのH8マイコンにHigh/Low信号を入力するための装置も載っています。それらを組み合わせればもう少し工夫が凝らせるようになるのですが、それはまた別の機会にお話ししたいと思います。
最後に、ITU3、4レジスタのプログラム上の構造とH8/3048F-ONE上のアドレスを以下に紹介します。第5回でもITUの構造の一部を紹介していますので、そちらと併せてご覧いただくと今回のプログラムがより分かると思います。
struct st_itu3 { /* struct ITU3 */ union { /* TCR */ unsigned char BYTE; /* Byte Access */ struct { /* Bit Access */ unsigned char NOV :1; /* */ unsigned char CCLR:2; /* CCLR */ unsigned char CKEG:2; /* CKEG */ unsigned char TPSC:3; /* TPSC */ } BIT; /* */ } TCR; /* */ union { /* TIOR */ unsigned char BYTE; /* Byte Access */ struct { /* Bit Access */ unsigned char NOV1:1; /* */ unsigned char IOB:3; /* IOB */ unsigned char NOV2:1; /* */ unsigned char IOA:3; /* IOA */ } BIT; /* */ } TIOR; /* */ union { /* TIER */ unsigned char BYTE; /* Byte Access */ struct { /* Bit Access */ unsigned char NOV :5; /* */ unsigned char OVIE :1; /* OVIE */ unsigned char IMIEB:1; /* IMIEB */ unsigned char IMIEA:1; /* IMIEA */ } BIT; /* */ } TIER; /* */ union { /* TSR */ unsigned char BYTE; /* Byte Access */ struct { /* Bit Access */ unsigned char NOV :5; /* */ unsigned char OVF :1; /* OVF */ unsigned char IMFB:1; /* IMFB */ unsigned char IMFA:1; /* IMFA */ } BIT; /* */ } TSR; /* */ unsigned int TCNT; /* TCNT */ unsigned int GRA; /* GRA */ unsigned int GRB; /* GRB */ unsigned int BRA; /* BRA */ unsigned int BRB; /* BRB */ }; /* */ #define ITU3 (*(volatile struct st_itu3 *)0xFFFF82) /* ITU3 Address*/ #define ITU4 (*(volatile struct st_itu3 *)0xFFFF92) /* ITU4 Address*/
また、前回と今回ではH8/3048F-ONEの各ビットについて最低限の内容にしか触れていませんので、一度H8マイコンの開発元であるルネサステクノロジ社のWebページからハードウェアマニュアルをダウンロードして目を通すことを強くお勧めします。今後組み込みプログラミングを行ううえで、マイコンのハードウェアマニュアルを読むということは必須となりますので、損はないと思います。
次回はPWM制御の締めくくりとして、サーボモータ制御について説明します。(次回に続く)
Copyright © ITmedia, Inc. All Rights Reserved.