PWM / OCnA[B]ピン以外からもPWM波を出力する

PWM / タイマー1を使ってOC1Aピン(PB1)、OC1Bピン(PB2)からPWM波を出力する -
PWM / タイマー2を使ってOC2Aピン(PB3)、OC2Bピン(PD3)からPWM波を出力する -
PWM / タイマー0を使ってOC0Aピン(PD6)、OC0Bピン(PD5)からPWM波を出力する -ではタイマーをFast PWMモードにしてPWMを実現したが、この方法では、決まっている6端子からしかPWM波が出力できない。

ここでは割り込みを利用してどのGPIO端子からもPWM波が出力できるようにしてみる。

// LEDをぼわーんと光らせる

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

volatile uint8_t duty;

ISR(TIMER0_OVF_vect){    // タイマー0がオーバーフローしたら、
    PORTB |= (1 << PB5); // PB5からHを出力して、
    OCR0A = duty;        // コンペア値を更新する。
}
ISR(TIMER0_COMPA_vect){   // タイマー0がコンペア値Aにマッチしたら、
    PORTB &= ~(1 << PB5); // PB5からLを出力する。
}
void initTimer0(){
    TCCR0B |= (1 <<CS01) | (1 << CS00);     // タイマー0のクロック源の分周比を設定する。ここでは64分周にした。
    TIMSK0 |= (1 << OCIE0A) | (1 << TOIE0); // コンペア値Aマッチ時およびオーバーフロー時に割り込む。
    sei();
}

int main(){
  
    DDRB |= (1 << PB5);
    initTimer0();
    
    uint8_t incre = 1;
    while(1){
        duty += incre;
        if(duty <= 0 || 255 <= duty){incre = -incre;};
        _delay_ms(5);
    }

    return 0;
}

これでChapter 10: Pulse-Width Modulationがだいたい終わり。