Hi,
I'm having a problem understanding what is happening when it comes to detecting when an ISR has changed a global variable.
I wrote the little program below and I'm seeing some different behaviors.
Of the four test functions below only number two works as desired.
The others appear to be hanging in different ways.
Any help in understanding what is going on "behind the scenes" would be much appreciated.
I have attached the sketch file.
Thanks much.
Frederick
// ------------------------------
// start of file
// ------------------------------
// ------------------------------------------------------------------------------------------
// Comments:
//
// Tested on an Arduino UNO
//
// Trying to understand when a global variable can be accessed by BOTH an ISR and a program loop.
//
// My need is to have a function invoked from the main loop wait within the function code
// until the ISR has set a global variable to a certain value
//
// In my tests only #2 below works - the others appear to be hang different ways
//
// the ***/fff/=== in the print statements are just to make it easy to identify
// the source when watching the console
// ------------------------------------------------------------------------------------------
// ------------------------------
// defines
// ------------------------------
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
// ------------------------------
// setup
// ------------------------------
void setup() {
Serial.begin(57600);
Serial.println("----------------------------------------"); Serial.println("setup started...");
// setup timer 1 to generate an interrupt every second
TCCR1A = 0x00; TCCR1B = 0x00; TCCR1C = 0x00; TCNT1 = 0; OCR1A = 15625; TCCR1B = _BV(WGM12) | _BV(CS12) | _BV(CS10);
// enable interrupt
sbi(TIMSK1, OCIE1A);
Serial.println("setup done");
}
// ------------------------------
// global var so ISR and loop can access
// ------------------------------
int counter;
// ------------------------------
// timer compare interrupt handler
// ------------------------------
ISR (TIMER1_COMPA_vect) {
if (counter > 0) { counter--; Serial.print("=== compare interrupt: "); Serial.println(counter); }
}
// ------------------------------
// function_1()
// ------------------------------
void function_1() {
Serial.println("fff setting counter to 5"); counter = 5;
do { delay(1); } while (counter > 0);
Serial.println("fff counter is now 0");
}
// ------------------------------
// function_2()
// ------------------------------
void function_2() {
if (counter == 0) { Serial.println("fff setting counter to 5"); counter = 5; }
do { delay(1); } while (counter > 0);
if (counter == 0) { Serial.println("fff counter is now 0"); }
}
// ------------------------------
// function_3()
// ------------------------------
void function_3() {
Serial.println("fff setting counter to 5"); counter = 5;
do { delayMicroseconds(1000); } while (counter > 0);
Serial.println("fff counter is now 0");
}
// ------------------------------
// function_4()
// ------------------------------
void function_4() {
if (counter == 0) { Serial.println("fff setting counter to 5"); counter = 5; }
do { delayMicroseconds(1000); } while (counter > 0);
if (counter == 0) { Serial.println("fff counter is now 0"); }
}
// ------------------------------
// loop
// ------------------------------
void loop() {
static char key = '?';
if (key == '?') { key = '0'; Serial.println("*** press 1 or 2 or 3 or 4"); }
if (Serial.available() > 0) {
key = Serial.read(); Serial.print("*** key pressed: "); Serial.println(key);
switch (key) {
case '1': {
function_1();
break;
}
case '2': {
function_2();
break;
}
case '3': {
function_3();
break;
}
case '4': {
function_4();
break;
}
default: {
Serial.println("*** invalid key pressed");
}
}
key = '?'; // trigger prompt
}
delay(250);
}
// ------------------------------
// end of file
// ------------------------------
Test_Timer_Interrupts_1.zip (1.17 KB)