I am working in a project where i'm reading some adc inputs periodically. (using timer1)
The period of measurement is 500 us and then i use a global variable to make sure the function that processes the adc values get the corret ones. However, i am using an if statement to check if that variable is 1 inside a loop, but it seems that despite im assigning 1 to the variable in a timer interrupt the loop is never run. However, if i put an else statement with the if, for example doing a Serial print, the code runs as i expected. I dont know whats causing this, so i hope you could help me. I'm posting a code that simulates the behavior im getting in my project code.
void setup() {
TCCR1A = 0;
TCCR1B = 0;
OCR1A = 8000; //500 us
TCCR1B |= (1<<WGM12); //CTC MODE, TIMER OFF
TIMSK1 |= (1<<OCIE1A);
Serial.begin(9600);
}
int proceed = 0;
ISR(TIMER1_COMPA_vect){
/*
ADC READS
*/
proceed = 1;
}
unsigned long testFunction(unsigned int n){
int i = n;
TCCR1B |= (1<<CS10); //STARTS THE TIMER
while(i > 0){
if(proceed){
i--;
proceed = 0;
}
else{
Serial.print('\0'); //IF COMMENTED DOESNT WORK
}
}
TCCR1B &= (0<<CS10); //STOPS THE TIMER
return n*500;
}
void loop() {
int t = testFunction(20);
Serial.println("Micros Passed: " + String(t));
}
Since you (for some reason that's beyond me) declared 'proceed' as an int, access to it will be non-atomic on an 8-bit AVR processor. Either declare it as a one-byte variable type (i.e. uint8_t) or access it in a Critical Section (interrupts off) when in non-ISR code.
Thanks for all the help guys i solved it. It was what you both said about assigning volatile and uint8_t to the variable. Can you explain or refer me to documentation that explains why does it have to be this way?
You need to use volatile as a warning to the compiler that the variable may be modified at any time so the variable needs to be accessible at all times and not pushed onto the stack, for instance where it is difficult to modify
If you use a variable whose value is held in more than one byte, such as the 2 byte of an int, then there is a chance that unless you take precautions, such as turning off interrupts before changing the value and turning them on again afterwards, that the process of updating the variable may be interrupted between changing one byte and another. By using a uint8_t variable you avoid the need to do this guarding as the single byte update is guaranteed not to be interrupted