[Solved] 2313 PWM not working

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Folks,

I'm trying to learn about hardware PWM. I've read Dean's tutorial and it makes sense so I thought I'd try to test it out with an LED.

The code I have so for should basically set a 100% duty cycle and leave the led constantly on. This is not the case as the LED doesn't light at all. Can you see where I am going wrong? I am using an ATtiny2313 with the fuses set to factory settings.

void init_timers(void)  {
  TCCR0A = (1<<WGM01) | (1<<WGM00) | (1<<CS00); //Fast PWM, no prescaler
  TCCR0A |= (1<<COM0A1); //Clear OC0A on Compare Match, set OC0A at TOP
  OCR0A = 255;
}

void init_io(void) {
  DDRB |= (1<<PB2);
}

int main(void) {
  init_io();
  init_timers();
  while(1)
  {  }
}

I have PB2 (OC0A) connected to a 150ohm resistor and then the positive leg of an LED. The negative leg is attached to ground. I have tried setting PB2 high with other code (PORTB |= 1<<PB2) and the led turns on so I think the hardware is setup ok.

Thanks for any help!

Last Edited: Sun. Oct 26, 2008 - 03:52 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Answering my own posts here:

I am trying to set the pre-scaler with the wrong register. CS00 is located on register TCCR0B. Here is code that works. Changes duty cycle between 0%, 50%, and 100% pausing 1 second at each level.

#define F_CPU 1000000UL
#include 
#include 

void init_timers(void)  {
  TCCR0A = (1<<WGM01) | (1<<WGM00);
  TCCR0A |= (1<<COM0A1);
  OCR0A = 255;
  TCCR0B |= (1<<CS00);
}

void init_io(void) {
  DDRB |= (1<<PB2);
}

int main(void) {
  init_io();
  init_timers();
  while(1)
  {
  _delay_ms(1000);
  OCR0A = 127;
  _delay_ms(1000);
  OCR0A = 0;
  _delay_ms(1000);
  OCR0A = 255;
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I thought I'd add this in case anyone found it useful. Here is code to use an ATtiny2313 with an RGB led (I'm using three separate LEDs but it would be the same if they were all in one package) to produce 12 different colors. This is accomplished by using the hardware pulse width modulation of this uC to change the duty cycle for the appropriate color mix.

#define F_CPU 1000000UL
#include 
#include 

/*
Color codes from:
http://simple.wikipedia.org/wiki/Color_wheel
*/

unsigned char const RGB_Colors[] = {
  0, 0, 0,	//Black
  255, 0, 0,	//Red
  255, 127, 0,	//Orange
  255, 255, 0,	//Yellow
  127, 255, 0,	//Chartreuse Green
  0, 255, 0,	//Green
  0, 255, 127,	//Spring Green
  0, 255, 255,	//Cyan
  0, 127, 255,	//Azure
  0, 0, 255,	//Blue
  127, 0, 255,	//Violet
  255, 0, 255,	//Magenta
  255, 0, 127	//Rose
};

void init_timers(void)  {
  TCCR0A |= (1<<WGM01) | (1<<WGM00);
  TCCR0A |= (1<<COM0A1);
  TCCR1A |= (1<<WGM10);
  TCCR1B |= (1<<WGM12) | (1<<CS10);
  TCCR1A |= (1<<COM1A1) | (1<<COM1B1);
  TCCR0B |= (1<<CS00);
  TCCR1B |= (1<<CS10);
  OCR0A = 255;
  OCR1A = 255;
  OCR1B = 255;
}

void pwm_color(char red, char green, char blue)
{
  DDRB |= (1<<PB2) | (1<<PB3) | (1<<PB4); //PB2-red PB3-green PB4-blue
  if (red == 0) { DDRB &= ~(1<<PB2); }
  if (blue == 0) { DDRB &= ~(1<<PB3); }
  if (green == 0) { DDRB &= ~(1<<PB4); }
  OCR0A = red;
  OCR1A = blue;
  OCR1B = green;
}

int main(void) {
  init_timers();
  while(1)
  {
    for (char i=0;i<13;i++)
    {
      pwm_color(RGB_Colors[i*3],RGB_Colors[i*3+1],RGB_Colors[i*3+2]);
      _delay_ms(1000);
    }
  }
}