AVRのPWM波形生成機能を使う
タイマカウンタによるPWM波形生成
ATmega168にはタイマカウンタを使ったPWM波形生成機能がある。
通常のデジタルIOでPWM波形を生成する場合、オンオフを切り替えるタイミングを
delayを使って指定する方法があるが、これでは波形生成している間に
ほかの処理を行うことができない。
PWM波形生成機能を使えばオンオフの切り替えのタイミングが自動的に処理され
設定を変えない限り同じ波形を出し続けることが可能。
プログラムではデューティ比を指定するだけでよい。
この機能では波形の生成の方法がいくつかあるが、この記事では高速PWMという
波形生成モードを使うことにする。
高速PWM動作
タイマカウンタのCTC動作を設定したときと同じようにTCCRに数値を入れることで高速
PWM動作を設定する。
下の設定では、高速PWM動作、クロックを8分周、OC0A端子から波形生成となる。
(詳しくはATmega168データシート)
TCCR0A = 0b10000011; TCCR0B = 0b00000010;この設定における、生成される波形とタイマカウンタの値の関係を図に示す。 タイマカウンタはクロックの立ち上がりのたびに1増える。 MAX値255になるとリセットして0にもどる。ここまではタイマの標準動作と同じである。
PWM波形はOCR0Aというピンに出力される。OCR0Aは12番のピンでPD6と兼用である。
タイマカウンタが0にもどったとき、OC0Aの出力が5Vになる。 タイマカウンタがOCR0Aと一致した時にOC0Aの出力を0Vにする。 OCR0Aはプログラムで設定する。OCR0Aの値を指定することで任意のデューティ比の 波形を生成することができる。
タイマカウンタと出力波形
高速PWMのプログラム
//pwm.c //winavr //ATmega168 //1MHz #include#include #include int main(void) { DDRD = 0xff; //タイマ0,高速PWM、PWM周期2048us TCCR0A = 0b10000011; TCCR0B = 0b00000010; OCR0A = 100; while(1){ ; } return 0; }
上のプログラムを実行しOC0A(PD6と兼用)を測定
PWM周期2048us,デューティ比0.39
上のプログラムのOCR0Aを200として実行しOC0A(PD6と兼用)を測定
PWM周期2048us,デューティ比0.78
タイマ割り込みでデューティ比を変化せるプログラム
//pwm2.c //winavr //ATmega168 //1MHz #include<avr/io.h> #include<util/delay.h> #include <avr/interrupt.h> unsigned char i; ISR(TIMER2_COMPA_vect) //タイマ割り込み { i++; if(i%2==0)OCR0A = 10; else OCR0A = 200; } int main(void) { //タイマ2,高速PWM、PWM周期2048us TCCR0A = 0b10100011; TCCR0B = 0b00000010; //タイマ0,CTC,割り込み用、比較A一致で割り込み TCCR2A = 0b00000010; TCCR2B = 0b00000101; // N=1024 OCR2A = 97; // 500msごとに割り込み TIMSK2 = 0b0000010; //比較A一致割り込み有効 //方向レジスタの設定 DDRB = 0xff; //B2を出力 DDRD = 0xff; //D5を出力 //割り込み許可 sei(); while(1){ ; } }
上のプログラムを実行しOC0A(PD6と兼用)
PWM周期2048us,500msごとに割り込みを発生し、デューティ比を0.78と0.04を切り替える