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でカウントスタートさせる。

私のプログラムを載せておきます。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#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();
}