RX220でPWMを発生させる(MTU0使用)
PWMを発生させる.基本なので頑張る.
環境
- マイコン:R5F52206BDFM(AKI-RX220ボード)
- 開発環境:e2studio
- 書き込みソフト:RenesasFlashProgrammer(RFP)
参考LINK
今回全体的に多数のサイトを少しずつ参考したので個別にリンクを張れない(どこを参考にしたか忘れたともいう)ので,参考率の高いのは以下のサイトです.ピンポイントな奴はその部分にリンクを張っています.
GitHub - radioshack16/rx220_sample: Small sample C program as a HEW project for Akizuki AE-RX220 development board
RX220 CubeSuite+ 用ルネサススタータキットのサンプルコード
ユーザーズマニュアル ハードウェア編)
タイマの設定
今回はPWMを発生させたいので,MTU0を用いる.
成果物は長いので一番下.
ピンの確認
タイマの機能としてのPWMを発生させるので出せるピンが決められている.事前に調べないと2度手間.
表21.3 MTUの入出力端子を見たところ,MTU0のTGRA0の端子名はMTIOC0A.
この機能は表1.6 機能別端子一覧(64ピンLQFP) (1 / 2)いわくピン番号36,ポート名PB3,秋月ボードだとCH2-3であることがわかった.
MPCの設定
汎用I/O以外の機能にするのでこいつを設定しなくてはならない.めんどくさいが仕方がない.
まず20.3.2 MPC レジスタ設定する場合の注意事項を読むと変更前に保護するものの保護を解除して保護を解除する必要があるらしい,わけがわからん.ひとまず解除しておく.
次に周辺機能がどんなのかを20.2.9 PBn 端子機能制御レジスタ ( PBnPFS )( n=0 ~ 7 )をみて決める.
最後に周辺機能モードにするべくPMRを変更しておく(PSELを決めてから設定しなくてはならないらしい).
一応表20.26 レジスタの設定に設定するべき一覧表がある(気が付かない).
void init_MPU()
{
MPC.PWPR.BIT.B0WI = 0; //PFSレジスタの保護解除をするPFSWEレジスタの保護解除
MPC.PWPR.BIT.PFSWE = 1; //PFSレジスタの保護解除
MPC.PB3PFS.BIT.PSEL = 0x1; //PB0~7を一括してPWM用のピンにしてしまう
PORTB.PMR.BIT.B3 = 1; //PB3だけ周辺機能ポートにする
PORTB.PDR.BIT.B3 = 0x1; //一応出力設定にしておく
MPC.PWPR.BIT.PFSWE = 0; //PFSレジスタの保護
MPC.PWPR.BIT.B0WI = 1; //PFSレジスタの保護をするPFSWEレジスタの保護
}
MTU0の有効化
準備が終わったのでMTUの設定に入る.
まずMTUを起動させる.起動させないとそもそもレジスタに書き込むことすらできないらしい.
次にMTU0の割り込みを禁止する.設定が終わるまでは静かにしてもらう.
なお表21.57 MTU割り込み要因 (1)を見ないと割り込み名がわからない模様.
/* ==== MTU module ON ==== */
SYSTEM.PRCR.WORD = 0x0A50b; //クロックソース選択の保護解除
MSTP(MTU) = 0; //MTU0~5まで有効にする
SYSTEM.PRCR.WORD = 0x0A500; //クロックソース選択の保護
/* ==== Disable Interrupt ==== */
IEN(MTU0,TGIA0) = 0; //TGIA0の割り込みを無効化
IEN(MTU0,TGIB0) = 0; //TGIB0の割り込みを無効化
MTU0.TIER.BYTE &= ~0x03; //TGIA0~B0の割り込みを無効化
MTU0の設定
はじめにMTU全体の設定の中のMTU0の部分を設定し,その後のMTU0の設定は適当に眺めていたら以下の手順例があったのでこれに準じて設定することにする.
CST0を0にしてカウントを止めておく.設定中に動かれると困りそう.
あとSYNC0を0にしてMTU0を独立して動作させる(PWMモード1を使うので←表21.4等参照).
/* ==== MTU Setting ==== */
//TSTR,TSYRの設定
MTU.TSTR.BIT.CST0 = 0; //MTU0のカウントを止める
MTU.TSYR.BIT.SYNC0 = 0; //MTU0を独立してカウントさせる
続いて[1],[2]のTCRを設定する.
分周はひとまずほっとく.エッジもほっとく.
クリアビットは表21.4 CCLR[2:0](MTU0、MTU3、MTU4)を見てTGRAでクリアさせることにする.
//MTU0 TCR設定
MTU0.TCR.BIT.TPSC = 0; //分周無し
MTU0.TCR.BIT.CKEG = 0; //立ち上がりエッジでカウントする
MTU0.TCR.BIT.CCLR = 0x1; //カウントのクリアをコンペアマッチTGRAで行う
次に[3]のTMDRを設定する.
ここではMTU0のモードを選択する.今回はPWMを発生させるので表21.11 MD[3:0]ビットによる動作モードの設定を見ると2を打てと書いてある.
このPWMモード1とPWMモード2の違いはPWMの出力可能本数が8本か12本かの違い.
SHでの話だがたいした差はないと思うので214.モード2による12相PWM(SH2-7045F)によると,モード1ではカウンタクリアをするのは各タイマ内のコンペアマッチでなくてはならないのだが,モード2だとどこでもいい.そんな違いらしい.
今後12本どころか8本も使う予定は全くないのでひとまず普通そうなPWMモード1でやってみる.(本当はピンとの兼ね合いを考えるべき?)
最後にバッファ動作の有無だが,そんなことはしない.
バッファ動作とは何ぞやと思い調べたところ,またSHでの話だがSH7125FのMTU2(3)曰くタイマがクリアされるときに別のコンペアマッチに代入しておいた値から周期を変更させるようにする機能らしい.面倒なのでそんなことはしない.
//MTU0 TMDR設定
MTU0.TMDR.BIT.MD = 0x2; //PWMモード1を選択
MTU0.TMDR.BIT.BFA = 0; //TGRAとTGRCを通常動作させる
MTU0.TMDR.BIT.BFB = 0; //TGRBとTGRDを通常動作させる
続きまして[4],[5]のTIORとTGRの設定.
TIORはどうやらMTIOC0Aの出力の仕方を設定するらしいと表21.20 TIORH(MTU0)に書いてある.コンペアマッチでLow→Highにでもしておく.
TGRではコンペアマッチの周期を設定する.適当に決めとく(制御しないのでどうでもいい).
//MTU0 TIORH/TIORL設定
MTU0.TIORH.BIT.IOA = 1; //Lowにする
MTU0.TIORH.BIT.IOB = 2; //Highにする
MTU0.TIORL.BYTE = 0; //全部出力しない
//MTU0 TGRA,TGRB設定
MTU0.TGRA = 1000 - 1;
MTU0.TGRB = 300 - 1;
最後に[6]のカウント動作を開始させる.一応TCNTをクリアしておく.
//MTU0 CST,TCNT設定
MTU0.TCNT = 0x0000; //カウント値の初期化
MTU.TSTR.BIT.CST0 = 1; //MTU0のカウントを開始する
MTU0の割り込み開始
次に割り込みレベルを設定して割り込みフラグを削除する.
/* ==== ICU Setting ==== */
IPR(MTU0,TGIA0) = 7; //TGIA0の割り込み優先度を7に設定
IPR(MTU0,TGIB0) = 7; //TGIB0の割り込み優先度を7に設定
IR(MTU0,TGIA0) = 0; //TGIA0の割り込みフラグを設定
IR(MTU0,TGIB0) = 0; //TGIB0の割り込みフラグを設定
/* ==== Enable Interrupt ==== */
// MTU0.TIER.BYTE |= 0x03; //TGIA0~B0の割り込みを有効化
// IEN(MTU0,TGIA0) = 1; //TGIA0の割り込みを有効化
// IEN(MTU0,TGIB0) = 1; //TGIB0の割り込みを有効化
このときルネサスのサンプル(初めて使った!) ではTGIA0,TGIB0を有効化しているが,今回は割り込みは使わないので有効化しない.というかすると遅くなる(謎).負荷が大きいとか?(全くわかりません)
この辺はおいおい調べる,気がしなくもない.ひとまず目的は達成したことにします.
成果物
ms_waitはn[ms]待つ関数.詳細は以前の投稿を参照されたし(普通の関数です).
徐々に暗くなっていきなり明るくなります.折り返すのは面倒でした.
void init_mtu0()
{
/* ==== MTU module ON ==== */
SYSTEM.PRCR.WORD = 0x0A50b; //クロックソース選択の保護解除
MSTP(MTU) = 0; //MTU0~5まで有効にする
SYSTEM.PRCR.WORD = 0x0A500; //クロックソース選択の保護
/* ==== Disable Interrupt ==== */
IEN(MTU0,TGIA0) = 0; //TGIA0の割り込みを無効化
IEN(MTU0,TGIB0) = 0; //TGIB0の割り込みを無効化
MTU0.TIER.BYTE &= ~0x03; //TGIA0~B0の割り込みを無効化
/* ==== MTU Setting ==== */
//TSTR,TSYRの設定
MTU.TSTR.BIT.CST0 = 0; //MTU0のカウントを止める
MTU.TSYR.BIT.SYNC0 = 0; //MTU0を独立してカウントさせる
/* ==== MTU0 Setting ==== */
//MTU0 TCR設定
MTU0.TCR.BIT.TPSC = 0; //分周無し
MTU0.TCR.BIT.CKEG = 0; //立ち上がりエッジでカウントする
MTU0.TCR.BIT.CCLR = 0x1; //カウントのクリアをコンペアマッチTGRAで行う
//MTU0 TMDR設定
MTU0.TMDR.BIT.MD = 0x2; //PWMモード1を選択
MTU0.TMDR.BIT.BFA = 0; //TGRAとTGRCを通常動作させる
MTU0.TMDR.BIT.BFB = 0; //TGRBとTGRDを通常動作させる
//MTU0 TIORH/TIORL設定
MTU0.TIORH.BIT.IOA = 1; //Lowにする
MTU0.TIORH.BIT.IOB = 2; //Highにする
MTU0.TIORL.BYTE = 0; //全部出力しない
//MTU0 TGRA,TGRB設定
MTU0.TGRA = 20000 - 1;
MTU0.TGRB = 2000 - 1;
//MTU0 CST,TCNT設定
MTU0.TCNT = 0x0000; //カウント値の初期化
MTU.TSTR.BIT.CST0 = 1; //MTU0のカウントを開始する
/* ==== ICU Setting ==== */
IPR(MTU0,TGIA0) = 7; //TGIA0の割り込み優先度を7に設定
IPR(MTU0,TGIB0) = 7; //TGIB0の割り込み優先度を7に設定
IR(MTU0,TGIA0) = 0; //TGIA0の割り込みフラグを設定
IR(MTU0,TGIB0) = 0; //TGIB0の割り込みフラグを設定
/* ==== Enable Interrupt ==== */
// MTU0.TIER.BYTE |= 0x03; //TGIA0~B0の割り込みを有効化
// IEN(MTU0,TGIA0) = 1; //TGIA0の割り込みを有効化
// IEN(MTU0,TGIB0) = 1; //TGIB0の割り込みを有効化
}
void init_MPU()
{
MPC.PWPR.BIT.B0WI = 0; //PFSレジスタの保護解除をするPFSWEレジスタの保護解除
MPC.PWPR.BIT.PFSWE = 1; //PFSレジスタの保護解除
MPC.PB3PFS.BIT.PSEL = 0x1; //PB0~7を一括してPWM用のピンにしてしまう
PORTB.PMR.BIT.B3 = 1; //PB3だけ周辺機能ポートにする
PORTB.PDR.BIT.B3 = 0x1; //一応出力設定にしておく
MPC.PWPR.BIT.PFSWE = 0; //PFSレジスタの保護
MPC.PWPR.BIT.B0WI = 1; //PFSレジスタの保護をするPFSWEレジスタの保護
}
void main(void)
{
PORT0.PDR.BIT.B3 = 1;
init_cmt0();
init_MPU();
init_mtu0();
int i=300;
while(1){
PORT0.PODR.BIT.B3 = 1;
ms_wait(1000);
i+=50;
if(i > 940){i=300;}
MTU0.TGRB = i;
PORT0.PODR.BIT.B3 = 0;
ms_wait(1000);
}
}