PIC18F45K50 Interrupciones

1

Estoy tratando de escribir código en el ensamblaje que detecta una interrupción (botón pulsador) en mi PIC18F45K50 y al detectar una interrupción, se enciende un LED. Por alguna razón el microcontrolador no está detectando la interrupción. Estoy usando una interrupción INT1 (por lo tanto, la entrada B1) y el LED está en D1.

Este es mi código ASM:

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 0
        BCF INTCON3, 0 ;clear flag INT1IF 
        CLRF LATB ;clear latB
        goto prog 

hinterrupt  ORG 0x08
        goto introutine

        ORG 0x22
prog    ;D1
        BCF ANSELD, 1 ;set D1 to digital
        BCF TRISD,1 ;configure PORTD.1 as output pin
        ;BSF PORTD, 1

        ;B1
        BCF ANSELB, 1 ;set B1 to digital
        BSF TRISB, 1 ;configure B1 as input pin 

        ;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


        goto prog


introutine  BCF INTCON3, 0 ;clear flag INT1IF
        BCF INTCON, 7 ;Disable all interrupts inside interrupt service routine (disable GIEH)
        MOVLW 0x01
        BSF PORTD, 1
        goto prog

END
    
pregunta beur_x

1 respuesta

1

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:

  1. Guardar estado y registros de trabajo
  2. Deshabilitar interrupciones globales para niveles altos y bajos
  3. indicador de interrupción de sondeo (si hay más de una interrupción)
  4. La operación definida por el usuario depende de si el indicador es alto o no
  5. Borrar bandera de interrupción periférica
  6. Estado de restauración y registros de trabajo
  7. 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

    
respondido por el S.Ramjit

Lea otras preguntas en las etiquetas