PIC: variable global no modificada dentro del controlador de interrupciones

0

Tengo un controlador de interrupciones para mi PIC 16 que debería modificar una variable global. Luego, la variable global se lee con main() en un bucle infinito.

Por alguna razón, parece que la variable global se está modificando dentro del controlador de interrupción, pero que las modificaciones no persisten fuera del controlador de interrupción. Estoy seguro de que:

  • El controlador de interrupción se llama correctamente
  • El controlador modifica la variable global dentro del controlador
  • El código en main() que lee la variable global es correcto

Finalmente, he tenido cuidado de declarar la variable global como volatile como se recomienda aquí .

¿Qué podría explicar que el cambio de variable global en el controlador de interrupción no persista en main() ?

[Nota: Mi código C está compilado por XC8. A continuación se muestra el código completo de mi caso de prueba reducido.]

#include <pic16f1824.h>
#include <xc.h>

volatile unsigned char buttonPress = 0b0;

void interrupt InterruptServiceRoutine(void) {
    // Update the button press value
    buttonPress = 0b1;
}

void main(void) {
    // Make RA4 an output
    TRISAbits.TRISA4 = 0b0;

    // Turn off status LED
    LATAbits.LATA4 = 0b0;

    // Enable interrupts
    INTCONbits.GIE = 0b1;

    // Enable interrupt-on-change to wake from sleep
    INTCONbits.IOCIE = 0b1;

    // Make the RA2 pin a digital input
    TRISAbits.TRISA2 = 0b1;
    ANSELAbits.ANSA2 = 0b0;

    // Interrupt on RA2 negedges
    IOCANbits.IOCAN2 = 0b1;

    while(1) {
        if(buttonPress == 0b1) {
            // Turn on LED <-- Never turns on
            LATAbits.LATA4 = 0b1;
        }
    }
}
    
pregunta Randomblue

2 respuestas

4

Ahora que hay más código disponible, aquí está mi teoría:

El indicador de interrupción no parece restablecerse, por lo que la interrupción se llama una y otra vez después de la primera vez, por lo que el código en el bucle principal nunca progresa.

    
respondido por el apalopohapa
4

¿Ha identificado la variable global como volatile ?

Para asegurarse de que el compilador no optimice las actualizaciones de variables que se espera que se realicen dentro de un controlador de interrupciones, la declaración de la variable debe ser:

volatile unsigned int theVariableThatTheIsrChanges;

Editar a la pregunta original invalida la solución anterior . Otros posibles problemas:

  • La variable global no está dentro del alcance de ISR: esto debería generar un error, pero algunos compiladores y banderas de compilación tienen una declaración automática de variables no declaradas en el primer acceso, lo que hace que estos errores sean notoriamente difíciles de rastrear.
  • Deshabilite todas las optimizaciones del compilador para la depuración: es posible que, por algún motivo, el compilador no vea la actualización real de la variable y, por lo tanto, optimice el código que ya no existe.
  • El LED se enciende, pero por una duración demasiado corta: el código button_debounce() no está en la lista, no está seguro de cómo se comporta. Intente cambiar el código para usar valores booleanos, y establezca la variable en un retorno positivo de button_debounce, y nunca lo reinicie (O el valor de retorno) para la depuración: el LED ahora debería encenderse pero nunca apagarse.

Más posibilidades:

  • initialize_stuff() tiene algún error que provoca que ISR nunca se configure
  • ISR no se llama en absoluto
  • La interrupción no se ha habilitado
  • El bucle while() está bloqueando las interrupciones ( ¿por qué? )
  • El indicador de interrupción no se está restableciendo, por lo tanto, la próxima interrupción nunca se genera

Actualización final : el último punto anterior fue la solución.

    
respondido por el Anindo Ghosh

Lea otras preguntas en las etiquetas