はじめに
こんにちは、槇原です。前回はファームウェアの書き込みをできるようにしたので、今回からはマイコンのペリフェラルを使っていきます。初めにタイマの説明をしていきます。
利用可能なマイコンのピンについて
PWMを出力できるピンはあらかじめ決まっているマイコンが多いですが、RX631についても同様です。
今回はブザー用にP16ピンと、モータドライバ用にPB3, PB1からPWM出力をする必要があるのでそれに沿って説明をします。
RX631にはタイマとしてMTUとTPUがありますが、MTUの方を利用します。MTUのほうがいろいろな機能を持っています。ただ今回は複雑なことはせずに単純なPWM出力をします。
MTUにはMTU0~3の独立したタイマがあってそれぞれのタイマごとに設定を変えて利用することができます。ブザーにはMTU3、モータにはMTU0を用います。これはピンとタイマ出力の関係が決まっているのでこのようになっています。
ユーザーマニュアルの表.22.6ではP1ポートの機能で設定できる機能が乗っています。
例えばP16の場合MTIOC3CでMTU3のTGRC、TGRDが出力波形を決めるレジスタになります。
以下の説明ではMTU3でP16のPWM出力をした際の設定について説明します。
PWMの設定のためのレジスタについて
プリスケーラの設定 (TCR TPSC)
タイマのカウンタのクロックの設定をします。PWM周期はこれをもとに決まります。今回は内部クロックPCLKを利用しますが、これを分周して利用することができます。ここでは1/4分周して元のクロック(48 MHz)を12 MHzとします。
PWMモード (TMDR MD)
PWMモードにはモード1と2がありますが、今回は1を使います。モードは1,2の2種類があって出力端子からPWM波形を出力できます。モード1はMTIOCnAかMTIOCnCに対応させた端子から波形を出力します。一方PWMモード2では複数のMTUを同期させて利用しますが、今回はブザーとモータでPWM周期を変えたりする必要があるため利用しません。(詳細はユーザーマニュアル 23.3.5 PWMモードに記載があります)各モードでの出力端子とレジスタの対応関係は下の表のようになっています。
PWMモードの設定はTMDRレジスタのMDビットにて設定されます。PWMモード1の場合0b0010に設定する必要があります。
コンペアマッチ時の動作 (TIOR TIORH,TIORL)
今回のPWMの動作は下の図のようになっています。出力波形に関係するレジスタは3つでTCNTとTGRC、TGRDです。TCNTはタイマのカウンタでクロックに合わせて増加していきます。TCNTの値がTGRDと一致したとき0にクリアされるように設定します(設定方法は後述)。またTCNTとTGRCが一致した際にMTIOC3Cに対応させたピンがLOWになり、TGRDと一致した際にMTIOC3CがHIGHになるようにします。TGRDの値によってPWM周期が決まり、TGRCの値によってデューティ比が決まります。
コンペアマッチ時の挙動はTIORHまたはTIORL内のIOx(A~D)で指定できます。ここではMTU3のTGRCレジスタのコンペアマッチの挙動を決めるレジスタの説明を以下の表に示しています。
上の図のような挙動にするためには、TIORLのIOCは0b001,TIORLのIODは0b010とすればよいです。
PWM周期は次の計算式で表されます。
f_PWM=(f_CLK/4)/(TGRD+1)
ここで1/4となっているのはプリスケーラの設定で1/4としたものが出ていて、TGRD+1と1を足しているのはTCNTを0からカウントしてTGDRになった際コンペアマッチが発生するためです。
カウンタのクリア動作の設定 (TCR CCLR)
カウンタをクリアする動作の設定はTCRレジスタのCCLRによって行います。下の表のとおり、CCLRを0b110とすることでTGRDのコンペアマッチでカウンタをクリアできるようになります。
GPIOの設定 (PMR)
GPIOはデフォルトではIOポートとして利用する設定になっています。PWMやそのほかの周辺機器として利用するためにはPMRレジスタの利用する端子のポートモードを1にする必要があります(リファレンスマニュアル21.3.4 下図を参照)。P16の場合であれば
PORT1.PMR.BIT.B6=1;
とします。
タイマスタート (TSTR CST3)
タイマスタートしない限りカウンタは変化しません。TSTRレジスタのCSTnを1にセットすることでカウンタがの動作が始まります。MTU3の場合
MTU.TSTR.BIT.CST3 = 1;
とします。
ブザー駆動用のコード
PWMに関する主要なレジスタの説明は以上となります。実際のコードは以下のようになっています。
コメント内でプロテクト~と書かれている箇所は、デフォルトでは書き換えが許可されていないレジスタの書き換えをするためにプロテクトの解除をして、設定後再度プロテクトをかけています。
#include "portdef.h" #include "iodefine.h" void init_buzzer(){ PORT1.PDR.BIT.B6 = 1; //P16を出力ピンに設定 PORT1.PODR.BIT.B6 = 0; SYSTEM.PRCR.WORD = 0xA502;//プロテクト解除 MSTP(MTU) = 0; //MTUモジュールON SYSTEM.PRCR.WORD = 0xA500;//プロテクト MTU.TSTR.BYTE=0; //タイマ動作ストップ MTU3.TCR.BIT.CCLR=6; //PWM TGRDのコンペアマッチでTCNTクリア MTU3.TCR.BIT.TPSC=1; //PCLK/4 12MHz MTU3.TMDR.BIT.MD=2; //PWMモード1に設定 MTU3.TIORL.BIT.IOC=1; //コンベアマッチてlow初期はlow MTU3.TIORL.BIT.IOD=2; //コンベアマッチでhigh MTU3.TGRC = 6000; //Duty 50% MTU3.TGRD = (12000-1); //1 kHz=12MHz/120000 12000カウントでカウンタをクリア MTU.TSTR.BIT.CST3 = 0; //タイマストップ MPC.PWPR.BIT.B0WI=0; //プロテクト解除 MPC.PWPR.BIT.PFSWE=1; MPC.P16PFS.BIT.PSEL=1; //機能の選択 ここではMTU MPC.PWPR.BYTE=0x80; //プロテクト PORT1.PMR.BIT.B6=1; //GPIO -> Buzzer PWM MTU.TSTR.BIT.CST3 = 0; //タイマストップ } void set_frequency(int f){ MTU3.TGRD=(unsigned short)(12000000/(f))-1; //ブザーの発振周波数を算出して、設定 MTU3.TGRC=(unsigned short)(6000000/(f))-1; //Duty 50% } void buzzer_on(){ MTU3.TCNT =0; //カウンタのリセット PORT1.PMR.BIT.B6=1; //周辺機器(PWMポート)として設定 MTU.TSTR.BIT.CST3=1; //タイマスタート } void buzzer_off(){ PORT1.PMR.BIT.B6=0; //汎用ポートに設定 MTU.TSTR.BIT.CST3=0; //タイマストップ }
次回はまたMTUを利用したエンコーダの読み取りについて説明します。