Una cosa que ayudaría (y definitivamente es la mejor práctica) sería verificar qué está causando la interrupción. También debe escribir en el latch ( LATx
register) en un 18F y necesita deshabilitar las funciones analógicas.
El código de ejemplo para esto podría ser:
#define LED_OUTPUT LATC3
void main(void) {
// .. other setup here ..
// Disable analogue functions
ADCON1 |= 0b0011;
// .. interrupt setup ..
}
void interrupt isr(void) {
// Was it the port B interrupt on change?
if (INTCONbits.RBIF) {
// Dummy read of the port, as per datasheet
if (PORTB) {
asm("nop");
}
// Use XOR to toggle the pin, saving a variable
LED_OUTPUT ^= 1;
// Reset the interrupt flag
INTCONbits.RBIF = 0;
}
}
Usar la función de interrupción en cambio con un pin de entrada específico es un poco más difícil, pero puede verificar en el ISR si el valor de entrada actual es 0
o 1
(lo que sea más relevante). No te olvides de rebotar en tu conmutador también, ya sea en hardware o en software.
condición de desajuste de PORTB
Note esta parte críptica de la hoja de datos en la sección 9.1 "Registros INTCON" con respecto al RBIF
bit:
Nota 1: una condición de falta de coincidencia continuará configurando este bit. Leyendo
PORTB finalizará la condición de discrepancia y permitirá que se borre el bit.
Para evitar que su código se atasque en el ISR (configurando repetidamente RBIF
), debe leer el puerto en su ISR incluso si no hace nada con el valor. El ejemplo de código anterior muestra esto.
(nota que encontré esta respuesta que es casi lo mismo)
Errata
La errata para tu dispositivo es otro excelente lugar para ir. Aquí está la errata para el 18F2520 , sin embargo, en este caso, no parece haber ninguna relación a las interrupciones o los puertos de datos.
Funciones especiales
Es posible que también deba desactivar otras funciones especiales en PORTB. Específicamente las funciones analógicas, que siempre deben estar deshabilitadas si está utilizando el pin como entrada digital.
// Make just AN12 (on pin B0) a digital input
ADCON1 |= 0b0011;
// Make all external pins digital inputs
ADCON1 |= 0b1111;
Mecanismos de interrupción alternativos
Tenga en cuenta que en el 18F2520 tiene tres interrupciones externas dedicadas disponibles como INT0 a INT2. Estos mapean a los pines B0 a B2. Consulte la sección 9.6 "INTx Pin Interrupts", donde encontramos lo siguiente:
Las interrupciones externas en los pines RB0 / INT0, RB1 / INT1 y RB2 / INT2 están
disparado por el borde. Si el bit INTEDGx correspondiente en el INTCON2
el registro se establece (= 1), la interrupción se activa por un flanco ascendente; Si
el bit está despejado, el disparador está en el flanco descendente.
En su lugar, podría utilizar la interrupción INT0, lo que significa que no depende de los valores de todo PORTB. Debido a que se activan en el borde, obtendrás menos interrupciones espúreas, pero aún tendrás que rebotar el interruptor.