PWMを利用したDCモータ制御プログラミングH8で学ぶマイコン開発入門(10)(3/3 ページ)

» 2007年07月11日 00時00分 公開
前のページへ 1|2|3       

DCモータを実際に制御するプログラム

 さて、上記の関数で構造体に記憶させた内容を実際に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 DCモータのON/OFFを設定

 リスト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
  }
}
リスト5 DCモータのEnableビットを設定する

//----------------------------------------------------------------------
// 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
  }
}
リスト6 DCモータのブレーキビットを設定する

//----------------------------------------------------------------------
// 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);
}
リスト7 DCモータのCWビットを設定する

 以上の関数を組み合わせることで、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);                   // 無限ループ
}
リスト8 DCモータを回転させるmainプログラム

 これだけでは少々物足りないかもしれません。もう少しモータに動きを与えようと思ったら、例えば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*/  
リスト9 ITU3、4の構造

 また、前回と今回ではH8/3048F-ONEの各ビットについて最低限の内容にしか触れていませんので、一度H8マイコンの開発元であるルネサステクノロジ社のWebページからハードウェアマニュアルをダウンロードして目を通すことを強くお勧めします。今後組み込みプログラミングを行ううえで、マイコンのハードウェアマニュアルを読むということは必須となりますので、損はないと思います。



 次回はPWM制御の締めくくりとして、サーボモータ制御について説明します。(次回に続く)

⇒ 連載バックナンバーはこちら

前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.