Electronic – Global variable in AVR interrupt routine

avrinterrupts

I am writing a code with interrupt routine. For debugging the code am using UART. So, here is the snippet:

volatile int overflow_count = 0;

int main(void) {
  while (1) {
    continue;
  }
}

ISR(TIMER1_OVF_vect) {
  char* time = "";
  overflow_count++;
  sprintf(time, "overflow-%d", overflow_count);
  uart_send(time);
  if (overflow_count == 2) {
    overflow_count=0;
    uart_array("Alarm code execution");
  }
}

Until first time the interrupt routine is called overflow_count value is 0 and after that, value is not incremented by one as per the code. Instead a random value (eg. 142851) is displayed while sending it from serial port. So, it never satisfies the condition if (overflow_count == 2). I am curious to know why it is not working.

Best Answer

Others have already pointed out the original problem in the comments above, namely that you need to reserve space for the character array.

I have made a few other changes to your original code, including:

  • Allocate space for the character array
  • Move code out of the interrupt service routine and back into main()
  • Using a global flag to communicate between the ISR and main()
  • Initialising all array elements to zero
  • Initialising global variables in main()

You should avoid doing any processing in the ISR, moving code out to main() accomplishes this. Using a global flag is one way of communicating from the ISR but you should be careful of race conditions between the two. Depending on your application there are a number of ways to ensure this doesn't happen.

Initialising global variables in main() means that they should be reset if your processor resets (your architecture might have special reset vectors for this).

Note that the code is untested but something along these lines might help you out.

volatile int overflow_count;
volatile char overflow_flag;

int main(void)
{
  char time[20] = { 0 };

  // Initialise global variables in case of reset
  overflow_count = 0;
  overflow_flag = 0;
  // You could memset time to NULs here also

  while(1)
  {
    if (overflow_flag) {
      // Depending on the application you may need to
      // implement some kind of mutex here, or disable
      // interrupts until you have finished.  Resetting
      // the flag as the first instruction offers the 
      // least chance you'll miss interrupts.
      overflow_flag = 0;

      sprintf(time, "overflow-%u", overflow_count);
      uart_send(time);

      if(overflow_count==2)
      {
        overflow_count=0;
        uart_array("Alarm code execution");
      }
    }
  }
}

ISR(TIMER1_OVF_vect)
{
  overflow_count++;
  overflow_flag = 1;
}