Electronic – Fast PWM and Atmega1280 problem

avrcledpwmtimer

Hello I have some problems to understand how to bind a Timer to a Pin and because of that my code isn't running…

#include <avr/io.h>

void init_PWM(void)
{
    TCCR0A|=(1<<WGM00)|(1<<WGM01)|(1<<COM0A1)|(1<<CS00);

    //Set OC0 PIN as output. It is  PB3 on ATmega16 ATmega32

    DDRB|=(1<<PB7);
}

void setPWM(uint8_t duty)
{
   OCR0A = duty;
}

void main (void)
{
   uint8_t brightness = 0;
   init_PWM();

   for (brightness=0; brightness<=255; brightness++)
   {
      setPWM(brightness);
      _delay_ms(100);
   }
}

My problem is how to assign the timer to PB7?

My goal is blinking LED on PB7 with FastPWM Mode.

Best Answer

Ok I can see a few problems with this code (Im assuming this is your datasheet):

  • First of all, if you want smooth fading use the 16-bit Timer instead of 8-bit (TCCR1A)
  • You want Fast PWM however you have it set to Phase Correct (pg 148, you want Mode 14)
  • You are not indicating the Frequency you want, in Fast PWM mode, according to the datasheet you need to set the TOP value, to do this you need to perform some calculation (formula on page 152 at the top).
  • Once you computed your TOP, the ICR1 needs to be set to that value (use a prescaler if your number is greater than 65535, table on pg 161)
  • To enable PWM on OC0A (PINB7) you need to set both COM0A1 & COM0A0

Refer to this example, its for the Atmega128 and uses a 16 bit timer. The frequency is 120Hz and my CPU clock speed is 16MHz. Therefore by using the formula I ended up with a TOP (16665) and my prescaler was 8 I believe.

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

int main(void) {

    //Fast PWM, using inverted mode (default low)
    TCCR1A |= 1<<WGM11 | 1<<COM1A1 | 1<<COM1A0;
    TCCR1B |= 1<<WGM12 | 1<<WGM13 | 1<<CS11;

    //Top
    ICR1 = 16665;

    //Set pins to input/output

    DDRB |= 1<<PINB5;

    OCR1A = 0;

    while(1) {
        //continuous loop where everything happens
        int i;

        for(i=0; OCR1A<ICR1; i+=166) {
            OCR1A = i;
            _delay_ms(6);
        }

        for(i=0; i<ICR1; i+=166) {
            OCR1A = ICR1 - i;
            _delay_ms(6);
        }

        OCR1A = 0;
        _delay_ms(500);

    }

}