La interrupción en el cambio se produce dos veces en PIC16F1825

1

Tengo una mala conducta alucinante en mi PIC16F1825. Básicamente, estoy usando el pin 3 (RA4) para alternar un LED usando una Interrupción en Cambio. El problema es que, aunque se enciende el led cada vez que presiono el botón (que se presiona externamente), después de un segundo, el LED se vuelve a encender, lo que significa que se llamó nuevamente a la rutina de interrupción, y no debería, aunque lo borre. la bandera de entrada.

Aquí está el código (solo la función IOconfig_portA () y toggleLed () son importantes para el problema en cuestión:

#include <stdio.h>
#include <stdlib.h>
#include <PIC16F1825.h>

char temp=0;

void interrupt toggleLed() {

    INTCONbits.GIE = 0;

    if(INTCONbits.IOCIF == 1) {
        temp = PORTA;
        INTCONbits.IOCIF = 0;
        LATC3 = ~LATC3;
        for (int i = 0; i < 100000; i++);
    }

    INTCONbits.GIE = 1;
}

void CLOCKconfig() {
    OSCCON  = 0x6A; //Sets the internal oscillator fosc = 4 MHz
    OSCSTAT = 0x00;
    OSCTUNE = 0x00;
}

void IOconfig_portA() {
    ANSELA = 0x00;           // All ports set as DIGITAL
    TRISAbits.TRISA4 = 1;    // Set as input
    //OPTION_REG &= 0x7F;    // Clear bit 7, to enable the weak pull-up
    //WPUA |= (1<<2);        // Enable the WPU for RA2
    CM1CON0 = 0x00;
    CM1CON1 = 0x00;
    IOCANbits.IOCAN4  = 1;  // Generate Interrupt on Negedge
    IOCAP  = 0x00;  // Disable Interrupt on Posedge
    INTCON = 0x88;    // Enable GIE and IoC interrupts
}

int main(int argc, char** argv) {

    TRISC = 0;

    CLOCKconfig();

    ANSELC &= 0x00; // All bits on port C are set to Digital I/O's
    TRISC  &= 0x00; // All bits on Port C are set to Outputs
    APFCON0 |= (1<<5); // Don't use special features on Pin RC3
    APFCON1 |= (1<<2); // Don't use special features on Pin RC3

    IOconfig_portA();

    LATC |= (1<<3);

    while(1) {

    }

    return (EXIT_SUCCESS);
}

Gracias de antemano!

    
pregunta José Fonseca

3 respuestas

1

¡Encontré la respuesta! Es bastante oscuro, debo decir. Básicamente, el PIC tiene un temporizador de vigilancia que restablece el dispositivo cada 4 segundos. Por extraño que parezca, viene habilitado de forma predeterminada (¿eso tiene sentido?). Para deshabilitar el temporizador de vigilancia, debe agregar la siguiente directiva de precompilador:

#pragma config WDTE = OFF
    
respondido por el José Fonseca
3

Según la página 92 de PIC16F1825 Hoja de datos :

  

Nota 1: el bit del indicador IOCIF es de solo lectura y se borra cuando el software ha eliminado todos los indicadores de interrupción en el cambio en el registro IOCxF

Básicamente, cuando haces esto en tu código:

INTCONbits.IOCIF = 0;

En realidad no hace nada, el indicador de interrupción no se borra porque ese bit es de solo lectura.

Para borrar el indicador de interrupción de las fuentes de Interrupción en Cambio, debe escribir en el registro IOCAF para borrar los indicadores que desee. Si desea eliminarlos todos, puede hacerlo:

IOCAF = 0x0;

Si solo desea borrar ciertos bits, como IOCAF4 en su caso, puede hacerlo:

IOCAFbits.IOCAF4 = 0;
    
respondido por el Tom Carpenter
0

¿Es posible que el circuito se reinicie debido a múltiples interrupciones (por ejemplo, apilamiento sobre flujo)?

En un reinicio, repetirías todo el código y volverías a habilitar la interrupción. (Como en la otra respuesta, podría haber un cambio de conmutador que haga que esto suceda).

El retraso del contador de 100k puede ser demasiado corto, intente aumentar esto a algo humanamente medible como un retraso total de 500 ms si es posible.

También para probar un reinicio no deseado, concédete una rutina de encendido para encender un código único en el LED, que te dirá si todo ha sido reciclado.

    
respondido por el Nedd

Lea otras preguntas en las etiquetas