前回、スイッチを正確に制御するために「CMT(コンペアマッチタイマー)」を使ってチャタリング防止の割り込み処理を追加しました。今回は、CMTよりも高機能な「MTU(マルチファンクションタイマーパルスユニット)」を使います。
Pi:Co Classicに搭載されているマイコン、「SH7125」に備わっている3つのタイマーの特徴を、SH7125のデータシートから抜き出して比べてみましょう(画像4)。いかがでしょうか。この表を見ると、機能の充実度合いから、MTUがSH7125で使用するタイマーの主力であることがよく分かります。
MTUは、名前に“パルス”が入っていることでも分かるように、タイマーとパルス発生機能が密接に結び付いています。このおかげで、周期と電圧を保つ時間を設定すれば、CPUに負荷を掛けずに制御波形を出し続けてくれます。この機能を「PWMモード」といいます。
SH7125のMTUには、「PWMモード1」と「PWMモード2」の2種類があります。今回は、周期を決めるレジスタとパルス幅を決めるレジスタを1組として、1つのPWMを生成するPWMモード1を使用します。これは、画像5のような動きをします。
画像5のようなパルスをブザーに出力することで音が鳴ります。周期を制御するのに、PWMモードを使えば音階が調整できるのです。
MTUが優れているのは、PWMのON/OFFの出力を直接ポートに出せる点です。ブザーが接続されている「PE6」をMTU出力に設定すれば、ON/OFFのパルスが出るので簡単にブザーの制御ができます。
参考記事: | |
---|---|
⇒ | モータ制御などに使われるパルス信号って何? |
⇒ | モータ制御に欠かせない技術“PWM”って何? |
MTUって、多機能なんですねぇ。ブザーを鳴らす以外に何ができるのか、ワタシはまだ見当もつかないんですけど……。
あのさ、「SH7125」のマニュアルは全部で690ページもあるって知ってるかな?
え〜っ。そんなにあるんですか!
そのうちの約200ページがMTUの解説なんだよ。つまり、それだけ重要な機能ってことだよね。
ワタシ、全部覚える自信ないかも……。センパイ、すごいー。
いや……。「えみちゃんと一緒に勉強する」って言ったじゃない。ボクもえみちゃんが来る前に、必死で予習しているんだよね。
いろんな機能があるから、実際にプログラミングしてハードウェアを動かしてみて……、必要なことから順番に覚えていけばいいと思うんだ。
(そうだったんだぁ……。)よーし、ワタシも頑張ろう!
うん。じゃあ、プログラムを組んでみよう!!
それでは、いつものようにプログラムを作成していきましょう。まずは、ブザーを鳴らすために必要な準備をしていきます。「init.h」にMTU設定を追加します(ソースコード1)。
void init_mtu(void); //MTU設定
次に「init.c」のI/Oポートの初期化部分に、ブザーのポート出力設定(ソースコード2)を追加し、MTUの初期化(ソースコード3)を新たに記述します。
void init_io(void) { ……(中略)…… //ブザー PFC.PEIORL.BIT.B6 = 1; //PE6を出力に設定 //ブザーMTU PFC.PECRL2.BIT.PE6MD = 1; //PE6をMTU端子に設定 }
MTUは、設定項目が多く少し複雑になります。画像6とソースコード3を照らし合わせて、理解を深めてください。
void init_mtu(void) { //MTU2スタンバイモード解除 STB.CR4.BIT._MTU2 = 0; // MTU2.TSTR.BYTE=0; //タイマー動作ストップ //ブザー用MTU MTU22.TCR.BIT.TPSC = 0; //MTU22の動作クロックは24MHz MTU22.TCR.BIT.CCLR = 2; //TGRBコンペアマッチでカウンタクリア MTU22.TIOR.BIT.IOB = 1; //初期出力0コンペアマッチ0出力 MTU22.TIOR.BIT.IOA = 2; //初期出力0コンペアマッチ1出力 MTU22.TGRA = 6000; MTU22.TGRB = 12000; //発振周波数2kHz MTU22.TMDR.BIT.MD = 2; //PWMモード1に設定 // MTU2.TOER.BYTE=0xff; //MTU出力端子を出力許可する // MTU2.TSTR.BIT.CST2 = 0; //タイマーストップ }
この設定で、以下のパルスが出力されます(画像7)。
全てのハードウェアの初期化を行うinit_all関数に、MTUの初期化を追加します(ソースコード4)。
void init_all(void) { ……(中略)…… init_mtu(); //MTUの初期化 }
そして、ブザーのON/OFFと音階の周波数をどこからでも呼び出せるように「common.h」へ定義しておきます(ソースコード5)。
//ブザー ON/OFF #define BZ_ON 1 //ブザー ON #define BZ_OFF 0 //ブザー OFF //音階の周波数 #define BZ_FREQ_REST 0 //休符 #define BZ_FREQ_LA0 440 //ラ(A)の周波数 #define BZ_FREQ_SI0 494 //シ(B)の周波数 #define BZ_FREQ_DO 523 //ド(C)の周波数 #define BZ_FREQ_RE 587 //レ(D)の周波数 #define BZ_FREQ_MI 659 //ミ(E)の周波数 #define BZ_FREQ_FA 698 //ファ(F)の周波数 #define BZ_FREQ_SO 784 //ソ(G)の周波数 #define BZ_FREQ_LA 880 //ラ(A)の周波数 #define BZ_FREQ_SI 988 //シ(B)の周波数 #define BZ_FREQ_DO2 1047 //ド(C)の周波数 #define BZ_FREQ_RE2 1174 //レ(D)の周波数 #define BZ_FREQ_MI2 1318 //ミ(E)の周波数 #define BZ_FREQ_FA2 1396 //ファ(F)の周波数 #define BZ_FREQ_SO2 1568 //ソ(G)の周波数 #define BZ_FREQ_LA2 1760 //ラ(A)の周波数 #define BZ_FREQ_SI2 1976 //シ(B)の周波数 #define BZ_FREQ_DO3 2094 //ド(C)の周波数
これで、MTUでブザーを鳴らす初期設定が完了しました。
Copyright © ITmedia, Inc. All Rights Reserved.