Atmega328 fast PWM (mode 15) on timer 1 not working

atmegaavrmicrocontrollerpwm

I cannot get PWM to work using mode 15 (a fast PWM) of timer 1. It's always giving me a high value of around 4.5V on PORTB2.

#include <avr/interrupt.h>
#define TIMER_OVERFLOW_COUNT  1

volatile int timerCount = 0;
ISR(TIMER1_COMPA_vect)
{
        ++timerCount;
}

int main(void)
{
        DDRB = DDRB | 1 << DDB2;
        TCCR1A = TCCR1A | 1 << COM1B1;
        TIMSK1 = TIMSK1 | 1 << OCIE1A;
        TCCR1A = TCCR1A | 1 << WGM10;
        TCCR1B = ((TCCR1B | 1 << WGM13) | 1 << WGM12) | 1 << WGM11;
        OCR1A = 62499;
        sei();
        TCCR1B = TCCR1B | 1 << CS12;
        while(1)
        {
        if( timerCount > TIMER_OVERFLOW_COUNT)
                {
                        OCR1B = 25000;
                        timerCount = 0;
                }
        }
        return 0;
}

However, I could get the similar mode (mode 7) of timer 0 to work fine.

#include <avr/interrupt.h>
#define TIMER_OVERFLOW_COUNT  125

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

int main(void)
{
        DDRD = DDRD | 1 << DDD5;
        TCCR0A = TCCR0A | 1 << COM0B1;
        TIMSK0 = TIMSK0 | 1 << OCIE0A;
        TCCR0A = (TCCR0A | 1 << WGM00) | 1 << WGM01;
        TCCR0B = TCCR0B | 1 << WGM02;
        OCR0A = 124;
        sei();
        TCCR0B = (TCCR0B | 1 << CS02) | 1 << CS00;
        while(1)
        {
        if(timerCount > TIMER_OVERFLOW_COUNT)
                {
                        OCR0B = 50;
                        timerCount = 0;
                }
        }
        return 0;
}

I cannot figure out what I am doing wrong in the earlier code.

Best Answer

I see one problem, but without a setup to test on: I can't say for sure if it's your only problem.

You're trying to set the WGM11 bit in TCCR1B to one when it really is in TCCR1A. Because of this, the WGM bits are 0x1101, and not 0x1111 that you want.

See below the TCCR1A register:

enter image description here

So this is the Waveform Generation Mode (WGM) that you are setting at.

enter image description here

It's "Reserved", so nothing.

You need to set WGM11 in TCCR1A:

TCCR1A |= (1 << WGM11) | (1 << WGM10);
TCCR1B |= (1 << WGM12) | (1 << WGM13);
Related Topic