SH7125のCMTとMTUを使ってサーボモーターを動かす方法を解説します。
概要
SH7125のMTUにはPWMモードというのがあります。これはその名の通りPWM信号生成に特化されたモードで、MTUに必要な設定をしてやれば割り込みを使わなくても任意の周期、デューティーのPWM信号を作ってくれるというモードです。
でも、今回はこのモードには設定しません。なぜなら、MTUの5チャネルの全部を使っても12本しかPWMを作れないからです(PWMモード2)。
では、どうするのか。CMTに周期、MTUにデューティーを担当させてPWMを作ればいいのです。これなら12本のPWMを作るにしてもMTU3チャネルで実現出来ます。
CMT(コンペアマッチタイマ)
SH7125には2チャネルのCMTがあります。どちらを使ってもいいので、今回はチャネル0を使いましょう。
力尽きた。続きはいつか。
2010/01/09追記
全部書ききる自信がないので、私がPWM信号を16本生成した方法を大雑把に書き殴っておきます。
周期にCMT、デューティーにはMTUを使う。
CMTで周期ごとに割り込みを発生させる。このとき設定するのが、
INTC.IPRJ、CMCSR、CMCOR
また、割り込み発生後は、CMCSRのCMFというフラグをクリアする必要がある。
CMTの割り込みでMTUを立ち上げる。
CMT割り込みがなされる度にMTUの設定をしなくてはならない。
このとき設定するのが、
TRWER、TOER、TCR、TMDR、TIOR
まず最初にTSTRでMTUを停止し、TCNTをゼロクリアして、上記項目を設定し、TGRにデューティーに対応する数値を書き込んでから、TSTRでカウントスタートさせる。
私のプログラムを載せておきます。
#include "iodefine.h"
//プロトタイプ宣言
void main(void);
void initIo(void);
void pwm(void);
void initCMT0(void);
//サーボの初期値 (1125-1)~(3487.5-1)
#define RL0 2305.25f
#define RL1 2305.25f
#define RL2 2305.25f
#define RL3 2305.25f
#define RL4 2305.25f
#define RL5 2305.25f
#define LL0 2305.25f
#define LL1 2305.25f
#define LL2 2305.25f
#define LL3 2305.25f
#define LL4 2305.25f
#define LL5 2305.25f
//大域変数の設定
int rl[]={RL0,RL1,RL2,RL3,RL4,RL5};
int ll[]={LL0,LL1,LL2,LL3,LL4,LL5};
//関数
void main(void){
//provide clock to cmt
STB.CR4.BIT._CMT=0;
//provide clock to mtu
STB.CR4.BIT._MTU2=0;
initIo();
initCMT0();
while(1){
}
}
//端子の初期化
void initIo(void){
PFC.PECRL1.WORD=0x1111;
PFC.PECRL2.WORD=0x1111;
PFC.PECRL3.WORD=0x1111;
PFC.PECRL4.WORD=0x1111;
PFC.PEIORL.WORD=0xFFFF;
}
//デューティー設定
void pwm(void){
//MTU stop
MTU2.TSTR.BYTE=0;
//MTU3,4のための設定(必須)
MTU2.TRWER.BYTE=0;
MTU2.TOER.BYTE=0xff;
//Counter reset
MTU20.TCNT=0;
MTU21.TCNT=0;
MTU22.TCNT=0;
MTU23.TCNT=0;
MTU24.TCNT=0;
//MTU20
MTU20.TCR.BYTE=0x02;//通常モードφ/16
MTU20.TMDR.BYTE=0;//通常モード
MTU20.TIOR.WORD=0x5555;//初期出力1コンペアマッチで0出力
//MTU21
MTU21.TCR.BYTE=0x02;//通常モードφ/16
MTU21.TMDR.BYTE=0;//通常モード
MTU21.TIOR.BYTE=0x55;//初期出力1コンペアマッチで0出力
//MTU22
MTU22.TCR.BYTE=0x02;//通常モードφ/16
MTU22.TMDR.BYTE=0;//通常モード
MTU22.TIOR.BYTE=0x55;//初期出力1コンペアマッチで0出力
//MTU23
MTU23.TCR.BYTE=0x02;//通常モードφ/16
MTU23.TMDR.BYTE=0;//通常モード
MTU23.TIOR.WORD=0x5555;//初期出力1コンペアマッチで0出力
//MTU24
MTU24.TCR.BYTE=0x02;//通常モードφ/16
MTU24.TMDR.BYTE=0;//通常モード
MTU24.TIOR.WORD=0x5555;//初期出力1コンペアマッチで0出力
//MTU20 set
MTU20.TGRA=rl[0];
MTU20.TGRB=rl[1];
MTU20.TGRC=rl[2];
MTU20.TGRD=rl[3];
//MTU21 set
MTU21.TGRA=rl[4];
MTU21.TGRB=rl[5];
//MTU22 set
MTU22.TGRA=ll[0];
MTU22.TGRB=ll[1];
//MTU23 set
MTU23.TGRA=ll[2];
MTU23.TGRB=ll[3];
MTU23.TGRC=ll[4];
MTU23.TGRD=ll[5];
//MTU24 set
MTU24.TGRA=rl[0];
MTU24.TGRB=rl[0];
MTU24.TGRC=rl[0];
MTU24.TGRD=rl[0];
//MTU start
MTU2.TSTR.BYTE=0xc7;
}
//CMTの設定
void initCMT0(void){
//優先度15
INTC.IPRJ.BIT._CMT0=15;
//CMT stop
//CMT.CMSTR.BIT.STR0=0x00;
//CMT0
CMT0.CMCSR.BIT.CMIE=1;//enable interrupt
CMT0.CMCSR.BIT.CKS=0;//1/8
//counter reset
//CMT0.CMCNT=0;
//30000-1,10ms interval
CMT0.CMCOR=29999;
//CMT0 start
CMT.CMSTR.BIT.STR0=1;
}
//CMT0割り込み関数
void CMT0_interrupt(void){
//割り込みフラグクリア
CMT0.CMCSR.BIT.CMF=0;
pwm();
}