日記

PWM信号

モータドライバを制御するPWM信号の出力には、タイマCのアウトプット・コンペア・モードを使います。
タイマCは16ビットのアップカウンタ(tc)と、コンペアマッチ用のコンパレータ(tm0,tm1)からなり、
特にtm1とのコンペアマッチでtcを0クリアできますので、tm1で周期を設定&"H"出力とし、
tm0とのコンペアマッチで"L"出力とすれば、tm0を変更することで任意のデューティを指定できます。
基本的には、最初に設定すれば、後は自動的にPWM信号を出力し続けてくれます。
(参考:トランジスタ技術2005年2月号の「R8C/Tinyマイコン入門 第4回」)
また、タイマCは1chしかありませんが、そのままの信号を3箇所から出力&反転した信号を3箇所から出力といった面白機能があります。

R8C/15のハードウェアマニュアルは慢性的な説明不足なのですが、殊にタイマCについては顕著です。
タイマCに関連する割り込みは、int_3,cmp_0,cmp_1,timer_cの4つですが、
int_3については、インプットキャプチャモードで使いますので、ここでは説明を省略します。
cmp_0,cmp_1は、それぞれtm0,tm1のコンペアマッチ時に割り込みが発生し、
timer_cは、tcのオーバーフロー時に発生します。
今回は、とりあえずtm1のコンペアマッチ時の割り込みのみを使用します。



.glb _cmp_1
.lword _cmp_1 ; vector 16 CMP1



では、実際にコードを記述します。
プログラムは、cmp0_0とcmp1_0(反転)からPWM信号を出力し、デューティ(tm0)をキーボードから変更できます("u"でアップ、"l"でダウン)。
なお、ベースとしたサンハヤトのサンプルプログラムでは、p1全体を設定している箇所がありますので、注意して下さい。
あと、CMP信号は、出力データも"H"にしないと出力されませんので、要注意です。



/* timerC初期化 */

timer_c_init();

/* I/Oポート初期化*/

pd1_0 = 1; // p1_0/CMP0_0を出力モードに設定
pd3_3 = 1; // p3_3/CMP1_0を出力モードに設定
p1_0 = 1; // CMP信号は、出力データも"H"にしないと出力されません(要注意)。
p3_3 = 1; //

p1_1 = 1; // LEDの初期状態(赤→消灯、青→点灯)をポートレジスタに設定する この時点ではまだ入力ポートの設定になっている
p1_3 = 0;



任意の箇所で・・・



/* デューティ変更 */

uart_put_short_dec((unsigned short)tm0); /* 値送信 */
uart_putc((unsigned char)0x0d); /* CR */

data = uart_getc(); /* 1文字受信 */
if ( 0 <= data ) {
uart_put_char_hex((unsigned char)data); /* 数値送信 */
uart_putc((unsigned char)0x0d); /* CR */
uart_putc((unsigned char)0x0a); /* LF */
if ( data == 0x75 ) {
tm0 += 10;
} else if ( data == 0x6c ) {
tm0 -= 10;
}
}



/****************************************/
/* タイマC 初期化 */
/****************************************/

timer_c_init(void)
{

tcc00 = 0; // カウント停止
tcc02 = 0; // カウントソース 00:f1
tcc01 = 0; //

// INT3割り込みは、インプットキャプチャモード時に使用します。

// tcc04 = 0; // INT3割り込み 00:立ち上りエッジ
// tcc03 = 0; //
// tcc06 = 0; // INT3割り込みタイミング 0:タイマCのカウントソースと同期
// tcc07 = 0; // 0:INT3割り込みに切り替え

// tcc11 = 0; // INT3フィルタ選択 00:フィルタなし
// tcc10 = 0; //

tcc13 = 1; // 1:アウトプットコンペアモード
tcc12 = 1; // 1:コンペア1一致時にカウンタ0セット
tcc15 = 1; // コンペア0出力設定 10:コンペア0の一致で"L"出力
tcc14 = 0; //
tcc17 = 1; // コンペア1出力設定 11:コンペア1の一致で"H"出力
tcc16 = 1; //

tcout0 = 1; // cmp0_0の出力許可
tcout1 = 0; // cmp0_1の出力禁止
tcout2 = 0; // cmp0_2の出力禁止
tcout3 = 1; // cmp1_0の出力許可
tcout4 = 0; // cmp1_1の出力禁止
tcout5 = 0; // cmp1_2の出力禁止
tcout6 = 0; // cmp0_0~cmp0_2からの出力を反転しない
tcout7 = 1; // cmp1_0~cmp1_2からの出力を反転する

// tc = 0; // カウントを停止させると自動的に0セットされる(tcレジスタは書き込みできない)

tm0 = 199; // デューティ D=(TM0+1/TM1+1)=50(先にtcc13=1:コンペア0出力に設定してから書き込む(p129))
tm1 = 399; // 周期設定 f=fCLK/(TM1+1)=8MHz/(399+1)=20kHz

cmp1ic = 0x06; // コンペア1割り込み許可(レベル6)

tcc00 = 1; // カウント開始
}

/****************************************/
/* コンペア1割り込み */
/****************************************/

#pragma interrupt cmp_1 // 割り込み処理関数指定
void cmp_1(void)
{

}


Copyright (c) 1997-2018 Rakuten, Inc. All Rights Reserved.