Reputation: 45
I am trying to increase the brightness of an LED using PWM with Timer0 on the ATMega164PA. After running my code below the LED just stays emitted and doesn't vary its brightness.
Please take a look at my code and tell me if there is something I am doing wrong:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
int dutycycle = 0; // Variable for dutycycle
/********************************************** MAIN ****************************************************/
int main(void)
{
DDRB |= (1 << PB3); // Make pins output and OC0A pin for PWM
TCCR0A |= (1 << COM0A1) | (1<<WGM01) | (1<<WGM00); // Clear OC0A on comare match and set OC0A at BOTTOM
TIMSK0 |= (1<<TOIE0); // Overflow Interrupt Enabled
TCNT0 = 0; // Set Counter Value Register for comparison with OCR0A
OCR0A = (dutycycle / 100) * 255; // Set duty cycle ON period
sei(); // Enable global interrupts
TCCR0B |= (1 << CS00); // Prescale of 1 - start timer
while (1)
{
_delay_ms(500);
dutycycle += 10; // increase duty cycle by 10% every 500ms
if (dutycycle > 100) // if duty cycle is greater than 100% set to 0
{
dutycycle = 0;
}
}
}
ISR(TIMER0_OVF_vect)
{
OCR0A = (dutycycle / 100) * 255; // Set duty cycle ON period
}
Upvotes: 0
Views: 232
Reputation: 8459
I'm not sure of the logic of your approach, but I can see an obvious problem that is causing you difficulties.
Integer division does not produce a fraction. Instead, it rounds the result down to the nearest integer. This means that dutycycle / 100
will almost always be 0, since you ensure that dutycycle <= 100
. So OCR0A
is almost always 0. The one exception is when dutycycle
is exactly 100, which sets OCR0A
to 255.
One way around this is to use OCR0A = dutycycle * 255 / 100;
instead. I don't know if this will fix all the problems, just the first one I see.
Upvotes: 3