Variable global en la rutina de interrupción AVR

2

Estoy escribiendo un código con la rutina de interrupción. Para depurar el código estoy usando UART. Así que, aquí está el fragmento:

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");
  }
}

Hasta que la primera vez que se llama la rutina de interrupción, overflow_count el valor es 0 y después de eso, el valor no se incrementa en uno según el código. En su lugar, se muestra un valor aleatorio (por ejemplo, 142851) al enviarlo desde el puerto serie. Por lo tanto, nunca satisface la condición if (overflow_count == 2) . Tengo curiosidad por saber por qué no funciona.

    
pregunta gzix

1 respuesta

12

Otros ya han señalado el problema original en los comentarios anteriores, es decir, que necesitas reservar espacio para la matriz de caracteres.

He realizado algunos otros cambios en su código original, incluyendo:

  • Asigne espacio para la matriz de caracteres
  • Mueva el código fuera de la rutina de servicio de interrupción y vuelva a main ()
  • Usar una bandera global para comunicarse entre el ISR y main ()
  • Inicializando todos los elementos de la matriz a cero
  • Inicializando variables globales en main ()

Debería evitar realizar cualquier procesamiento en el ISR, moviendo el código a main () lo logra. Usar una bandera global es una forma de comunicarse desde el ISR, pero debes tener cuidado con las condiciones de la carrera entre los dos. Dependiendo de su aplicación, hay varias formas de asegurarse de que esto no suceda.

La inicialización de variables globales en main () significa que deberían restablecerse si el procesador se reinicia (su arquitectura puede tener vectores de reinicio especiales para esto).

Tenga en cuenta que el código no se ha probado, pero algo en este sentido podría ayudarlo.

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;
}
    
respondido por el David

Lea otras preguntas en las etiquetas