Saturday, February 23, 2013

PWM on the Atmega328P




OK, this was kind of confusing, but not too bad really. The PWM works via the timers. You set a timer and it starts counting until it hits its max (ICR). You set a threshold (OCR), and then if the timer is under the threshold, the output pin will go high. Otherwise it goes low. There's some finicky stuff about phase correctness but that's about it.



The timers have a frequency that's going to be a divider of the main clock rate. We're at 16Mhz. I use the f/8 divider. Putting it in phase correct mode means it counts up and then down again, so for a full cycle it's another half that.





TCCR1B|=(1<<WGM13)|(1<<WGM11)|(1<<CS11); //PRESCALER= MODE 10(phase correct)

ICR1=20000; //50Hz (Period = 20ms).

DDRB|=(1<<PB1); //PWM Pins as Out

}




void initPWM()


{


TCCR1A|=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11); 

}

ICR 1 contains basically what the timer will count up to. So at 2 Mhz, we're going to count to 20,000 and back down again. That means 20ms per cycle. Finally, turn the pin on.







I had hoped to use timer 2, but it doesn't seem to have the ICR feature. Will have to figure that one out later.
Setting the PWM duty is pretty easy too.  OCR1A is the output compare register, and since things have worked themselves out, the units will just be a microseconds again.
OCR1A = on_time;    
So that's a PWM timer with 1usec resolution, on a 50hz cycle, with no processor overhead.


No comments:

Post a Comment