Electronic – Atmega32 PWM on all four PWM pins

atmegaavrpwm

I am trying to control LEDs brightness using PWM on the Atmega32. I have one LED connected to each of the 4 PWM pins (OC0, OC1A, OC1B, and OC2). Using the code below, all of the LEDs are functioning as expected except the LED connected to OC1A which is remaining dark. Why is this the case? Thank you for your assistance.

#define  F_CPU 100000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>



void InitPWM()
{

   TCCR0  |= (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00);
   TCCR1A |= (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00); 
   TCCR1B |= (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00);
   TCCR2  |= (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00);


}



int main(void)
{

    //Configure the ADC
    ADCSRA |= 1<<ADPS2;         //Enable a prescaler
    ADMUX |= 1<<ADLAR;          //8-bit or 10-bit results
    ADMUX |= 1<<REFS0;
    ADCSRA |= 1<<ADIE;          //Enable interrupts function in ADC
    ADCSRA |= 1<<ADEN;          //Turn on the ADC feature
    sei();                      //Enable global interrupts
    ADCSRA |= 1<<ADSC;          //Start the first conversion

    DDRB = 0xFF;                // initialize port B
    DDRD = 0xFF;                // initialize port D


    InitPWM();                  //initialize PWM mode

    while(1)
    {
        OCR0 = 100;
        OCR1A = 100;
        OCR1B = 100;
        OCR2 = 100;



        _delay_ms(500);        

        OCR0 = 255;
        OCR1A =255;
        OCR1B = 255;
        OCR2 = 255;



        _delay_ms(500);       
    }

}




ISR(ADC_vect) // interrupt routine and display the results
{
char adcResult[4];
itoa(ADCH, adcResult, 10);

ADCSRA |= 1<<ADSC; //Start the next conversion 
}

Best Answer

While it may not be your only problem (for example, your code is very light on configuration and seems to rely a lot on defaults, which may not be what you assumed) one serious issue that jumps out is in improperly using the TCCR0-specific bitmasks for all of the timer configuration registers:

TCCR0  |= (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00);
TCCR1A |= (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00); 
TCCR1B |= (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00);
TCCR2  |= (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00);

In fact, these are not all the same, and those for TCCR1A are among the most unique.

If you examine <avr/iom32.h> or presumably the data sheet, you will see for example that the available WGM bits in TCCR1A are called WGM11 and WGM10, not WGM01 and WGM00 which are not present in this register and have different values where they do occur for TCCR0 than the funcitonally comparable bits in TCCR1A do.

So at minimum, you need to correct the quoted block of configuration code to use the proper bit pattern names or at least values applicable to each of the registers you are attempting to configure.

But more generally, you should double check all involved registers, both timer and higher level, which are involved in making this work, and be sure that the values you explicitly set or rely on from power-on defaults are in fact those suitable to your goal.