I used to write my codes in ICCAVR and I had no problem there, but not for some reason I should migrate to AtmelStudio. in the following code, the LED is flashing in the interrupt, but when I only set a flag in the interrupt and want to flash the LED in polling (using the flag) it wouldn't work:
#include<avr/io.h>
#include<avr/interrupt.h>
#define LED PA1
ISR (TIMER1_OVF_vect) // Timer1 ISR
{
//PORTA ^= (1 << LED);
TCNT1 = 63974; // for 1 sec at 16 MHz
PORTA ^= (1 << LED);
}
int main()
{
DDRA = (0x01 << LED); //Configure the PORTD4 as output
TCNT1 = 63974; // for 1 sec at 16 MHz
TCCR1A = 0x00;
TCCR1B = (1<<CS10) | (1<<CS12);; // Timer mode with 1024 prescler
TIMSK = (1 << TOIE1) ; // Enable timer1 overflow interrupt(TOIE1)
sei(); // Enable global interrupts by setting global interrupt enable bit in SREG
while(1)
{
}
}
while this change would make it not to flash:
#include<avr/io.h>
#include<avr/interrupt.h>
#define LED PA1
unsigned int counter=0;
unsigned char flag=0;
ISR (TIMER1_OVF_vect) // Timer1 ISR
{
//PORTA ^= (1 << LED);
TCNT1 = 63974; // for 1 sec at 16 MHz
counter++;
if(counter>=10)
{
flag=1;
counter=0;
}
}
int main()
{
DDRA = (0x01 << LED); //Configure the PORTD4 as output
TCNT1 = 63974; // for 1 sec at 16 MHz
TCCR1A = 0x00;
TCCR1B = (1<<CS10) | (1<<CS12);; // Timer mode with 1024 prescler
TIMSK = (1 << TOIE1) ; // Enable timer1 overflow interrupt(TOIE1)
sei(); // Enable global interrupts by setting global interrupt enable bit in SREG
while(1)
{
if(flag)
{
flag=0;
PORTA ^= (1 << LED);
}
}
}
could anyone please help me?
Compiler saw that flag
set to 0 at start of program and can't know that the variable can be changed by interrupt handler (the code never called directly in program).
So it optimized out flag
check in while
loop.
Use volatile
qualifier for variables that accessed from different code streams (main code and interrupt handler, different threads in multi-threaded environment).
volatile unsigned char flag = 0;