I have written a pwm code for Atmega128. I am using fast pwm mode with non-inverting pulse on compare match and I need to change the OCR0 value at certain times. Yet it doesn't change. Anyone knows what is the problem here ??
#include <avr/interrupt.h>
#include <avr/io.h>
uint8_t tick_1sec;
void timer1_init(void) // 1 second timer
{
OCR1A = 15624;
TIMSK |= (1<<OCIE1A);
TCCR1B = (1<<WGM12); //CTC mode
TCCR1B |= (1<<CS12)|(0<<CS11)|(1<<CS10);
}
ISR(TIMER1_COMPA_vect) //1 second interrupt
{
cli();
tick_1sec = 1;
sei();
}
void timer0_init(void) // fast pwm with OC0 non-inverting mode
{
TCCR0 = (1<<FOC0)|(1<<WGM01)|(1<<WGM00);
TCCR0 |= (1<<COM01)|(0<<COM00);
TCCR0 |= (1<<CS02)|(1<<CS01)|(1<<CS00);
OCR0 = 63;
TIMSK |= (1<<OCIE0);
}
int main(void)
{
uint8_t t = 0;
DDRB = 0xFF;
timer0_init();
timer1_init();
sei();
while(1){
if (tick_1sec)
{
tick_1sec = 0;
t++;
if (t == 10){
OCR0 = 127;
}
else if (t == 20){
OCR0 = 191;
}
else if (t == 30){
OCR0 = 63;
t = 0;
}
}
}
return 0;
}
Things to check:
I recommend declaring tick_1sec
as volatile
to prevent the compiler of hyper-optimizing that register.
What is your clock frequency? Your ISR will deliver 1s calls only if your CPU frequency is 16MHz (==> 16.000.000 / 1024 / 15624)
You might have a LED in your hardware which you can invert from a) the ISR
b) within the first if ()
in main
to see if this is ever reached.
update: "volatile"
The link provided by @skyrift in his comment is very worth reading.
When you use Atmel Studio, compile your code once with/without the volatile
keyword and compare what the compiler is doing ==> Solution explorer / Output Files / *.lss ... you will see each C statement and how the compiler converts it to machine code ... an exercise worth once in a while when working with micros ...