Así que hay un par de cosas que deben cambiar en su código. El microcontrolador puede estar detectando la interrupción, pero su código no lo maneja correctamente. Al codificar ASM en la familia PIC, debe encargarse de muchas cosas manualmente. Las interrupciones en ASM requieren que guarde el estado y los registros de trabajo antes de ocuparse realmente de la interrupción. Normalmente sondeará la bandera periférica, pero es cuando se trata de interrupciones múltiples. Ya que solo tienes uno, lo mantendremos simple.
Al inicio del programa, la forma habitual de decirle al microcontrolador que vaya al programa principal es poner un goto
después del ORG 0x00
. Así que ordenar las partes iniciales de su código dará como resultado:
LIST p=p18f45k50
INCLUDE "p18f45k50.inc"
; Aim of program: input at B1 toggles the led at D1
; Assembly source line config statements
CONFIG WDTEN = OFF
CONFIG LVP = OFF
CONFIG FOSC = INTOSCIO
begin
ORG 0x00
goto prog
hinterrupt
ORG 0x08
goto introutine
ORG 0x22
prog
BCF INTCON3, 0 ;clear flag INT1IF
CLRF LATB ;clear latB
;D1
En la 'Introutina' de la rutina de servicio de interrupción, usaste la instrucción goto
en lugar de la instrucción retfie
. Citando el manual de la sección 10.3:
La instrucción "regresar de interrupción", retfie
sale de la rutina de interrupción y establece el bit GIE / GIEH (GIEH / GIEL si se usan niveles de prioridad), que vuelve a habilitar las interrupciones.
Así que reuniendo toda la información proporcionada hasta ahora, su ISR genérico sigue este procedimiento:
- Guardar estado y registros de trabajo
- Deshabilitar interrupciones globales para niveles altos y bajos
- indicador de interrupción de sondeo (si hay más de una interrupción)
- La operación definida por el usuario depende de si el indicador es alto o no
- Borrar bandera de interrupción periférica
- Estado de restauración y registros de trabajo
- Salir de ISR con
retfie
El siguiente ISR asume que ya ha asignado un registro para W_TEMP
y STATUS_T
ISR
MOVWF W_TEMP ; SAVE W AND STATUS REGISTERS
SWAPF STATUS,W
MOVWF STATUS_T
BCF INTCON, 7 ;Disable all interrupts inside interrupt service routine (disable GIEH)
BCF INTCON3, 0 ;clear flag INT1IF
MOVLW 0x01
BSF PORTD, 1
SWAPF STATUS_T,W ; RESTORE W AND STATUS REGISTERS
MOVWF STATUS
SWAPF W_TEMP,F
SWAPF W_TEMP,W
RETFIE
El motivo movwf
y swapf
se usan porque esas instrucciones no modifican el estado de los indicadores de transferencia de dígitos, cero o de transporte. También se debe tener en cuenta que en este momento el ISR solo enciende el LED y no lo enciende, eso se podría hacer con una simple máscara XOR.
Por último, dado que todo el programa está controlado por interrupciones, tendría sentido tener el microcontrolador en un bucle después de haber configurado todo. Así: '
***code from before**
;INT1 hence B1 settings
BSF INTCON3, 6 ;set INT1 to high priority
BSF INTCON2, 5 ;+ve edge trigger for B1
BSF INTCON3, 3 ;enable INT1
BSF RCON, 7 ;set IPEN to HIGH thus enabling priorities on interrupts
BSF INTCON, 7 ;set GIEH to high, enabling high priority interrupts
loop
goto loop
De esta manera, después de configurar todas las interrupciones y el LED, el microcontrolador permanece en un bucle y reacciona solo a la interrupción