PWM(パルス幅変調)というAVRに内蔵されている機能を使って、LEDを明滅させてみる。
要は、細かいON/OFFを繰り返して、そのON時間を調整することにより、時間あたりの流れる電流量を調整する技術なのかな。
基本の回路から増えているのは、PB3から出ている、抵抗とLEDのみ。
8bitタイマ0を使ってPWMの出力をする場合には、OC0AかOC0Bのピンを使用し、これはそれぞれPD6とPD5の兼用機能になるんだけど、PDには前回やったLCDがついてて、はずすのも面倒。
なので、8bitタイマ2を使ってOC2AからPWM出力するようにし、これは空いてるPB3の兼用機能なので、PB3に繋いだ。
上の回路図には、ちゃんと書かれてないけど、データシートには、PD3は(MOSI/OC2A/PCINT3)と書いてある。
後で直しておくか……。
実際の動作はこのムービーのような感じ。
#include <avr/io.h> #include <util/delay.h> void delay_ms( int time ) { // 指定ms分ループ while( time-- ){ _delay_ms( 1 ); } } int main( void ) { uint8_t duty = 0; // Duty比 duty/256 int8_t dir = 1; // 増減量 DDRB = 0x08; // PB3を出力に設定 PORTB = 0x00; // ポートBをLowに初期化 OCR2A = duty; // Duty比初期化 TCCR2A = 0b10000011; // 8bit高速PWM動作 比較A出力選択でOC2Aへの非反転動作 TCCR2B = 0b00000001; // タイマ/カウンタ2入力クロック前置分周なし while(1){ // 0〜255〜0で、512msを1周期とした明滅を繰り返す delay_ms(1); if( 0x00 == duty ) dir = 1; // 正方向に増やす(明るくする) if( 0xFF == duty ) dir = -1; // 負方向に増やす(暗くする) duty += dir; OCR2A = duty; // Duty比更新 } return 0; }