Skip to main content
Source Link
Suba Thomas
  • 1.4k
  • 13
  • 20

Atmega328 fast PWM (mode 7) of timer 0 not working as expected

I am blinking an LED on PORTB5 using timer 0 in mode 7. The time between blinks is computed as $$ \frac{(\text{OCROA}+1) \times \text{prescaler} \times \text{timerCount}}{\text{FCPU}} $$ \$FCPU=16MHz\$. With \$OCROA=124\$, \$prescaler=1024\$, and \$timerCount=125\$, the time turns out to be \$1 \space second\$ and this works as expected. But with \$OCROA=16\$, \$prescaler=1\$, and \$timerCount=2956793\$, I would expect the time to be \$~3.14 \space seconds\$, but I am getting something around \$12 \space seconds\$.

Code that works as expected:

#include <avr/interrupt.h>
#include <stdint.h>

volatile uint32_t timerCount = 0;
ISR(TIMER0_COMPA_vect)
{
        ++timerCount;
}

int main(void)
{
        DDRB |= 1 << DDB5;
        TIMSK0 |= 1 << OCIE0A;
        TCCR0A |= 1 << WGM00 | 1 << WGM01;
        TCCR0B |= 1 << WGM02;
        OCR0A = 124;
        sei();
        TCCR0B |= 1 << CS02 | 1 << CS00;
        while(1)
        {
        if(timerCount >= 125)
                {
                        PORTB ^= 1 << PORTB5;
                        timerCount = 0;
                }
        }
        return 0;
}

Code that does not work as expected:

#include <avr/interrupt.h>
#include <stdint.h>

volatile uint32_t timerCount = 0;
ISR(TIMER0_COMPA_vect)
{
        ++timerCount;
}

int main(void)
{
        DDRB |= 1 << DDB5;
        TIMSK0 |= 1 << OCIE0A;
        TCCR0A |= 1 << WGM00 | 1 << WGM01;
        TCCR0B |= 1 << WGM02;
        OCR0A = 16;
        sei();
        TCCR0B |= 1 << CS00;
        while(1)
        {
        if(timerCount >= 2956793)
                {
                        PORTB ^= 1 << PORTB5;
                        timerCount = 0;
                }
        }
        return 0;
}

What could be the issue with the latter?