Search code examples
microcontrolleravravr-gccpwmattiny

How do I output a compare match to OC1B in Fast PWM mode on the ATtiny84?


My goal is to output a PWM signal from my ATtiny84 with 1ms high at 50hz. The clock is operating at 1mhz, so I've set the compare output mode such that the output pin should be cleared for 19000 clock ticks and be set for 1000.

The device is powered at 5V and I have an oscilloscope reading a flat 5V output from pin A5 (OC1B), no modulation. My code is here:

#include <avr\io.h>

void init_pwm_generator()
{
    PORTA &= ~(1 << (PORTA5));

    ICR1  = 20000;

    TCCR1A = (1<<COM1B1) | (1<COM1B0) | (1<<WGM11);
    TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10); 
}

int main(void)
{
    DDRA |=  (1 << (DDA5));

    init_pwm_generator();

    while(1)
    {   
        OCR1B = ICR1 - 1000;
    }
}

I can't figure out why this isn't working!


Solution

  • See the datasheet chapter 12.5 Input Capture Unit at page 91

    The ICR1 Register can only be written when using a Waveform Generation mode that utilizesthe ICR1 Register for defining the counter’s TOP value. In these cases the Waveform Genera-tion mode (WGM13:0) bits must be set before the TOP value can be written to the ICR1Register.

    So, correct initialization sequence will be as follows:

        // Init the timer
        TCCR1A = (1<<COM1B1) | (1<COM1B0) | (1<<WGM11);
        TCCR1B = (1<<WGM13) | (1<<WGM12);
    
        ICR1  = 19999; // set the top value
        OCR1B = 19000; // set compare match value
    
        TCCR1B |= (1<<CS10); // start the timer
    

    Please note, for the timer period to be 20000 ticks you have to set TOP value to 19999 (since the timer counts from zero)