Interrupciones en los PIC

A ver si comprendo hay uno con dirección 0x41 otro 0x43 y otro 0x45 porque esos tres tienen conectados pulsadores por ejemplo, preciono un pulsador del 0x43, el pcf produce una interrupción, le llega al pic se activa y como hace para saberlo cuál fue?

 
Ya te dieron la solución, por la dirección del dispositivo.
El microcontrolador manda la dirección del PCF que se quiere leer y si durante ese tiempo ocurre una interrupción, se podrá determinar de cuál fue.
 
Al ocurrir la interrupción, mandas al PIC a leer los registros de cada PCF8574. Donde exista un cambio, ese es el dispositivo. Ahora, ésta posiblemente sea una solución de muchas, pero tendrá que descubrir si le funciona o no (cuestión de tiempos).

P.D. Usted debe pensar la forma de comparar un registro anterior con el actual.



Creo que en la imagen que subí (post #20) se observa el problema que usted expone.
 
Última edición:
Estoy trabajando con un pic 16f648a con interrupciones por cambios en el port B (4,5,6,7) el problema es que al producir una interrupción el pc salta correctamente a la dirección 0004H y ejecuta la ISR pero al ejecutar la RETFIE no regresa inmediatamente al programa principal sino que se queda, supongo, en un bucle que toma como 52 segundo y después de eso recién continua con el programa principal, lo más raro es que probando el programa en la simulación que hice en MPLAB SIM funciona perfectamente, ¿alguien tiene un explicación sobre esto?
 
Estoy trabajando con un pic 16f648a con interrupciones por cambios en el port B (4,5,6,7) el problema es que al producir una interrupción el pc salta correctamente a la dirección 0004H y ejecuta la ISR pero al ejecutar la RETFIE no regresa inmediatamente al programa principal sino que se queda, supongo, en un bucle que toma como 52 segundo y después de eso recién continua con el programa principal, lo más raro es que probando el programa en la simulación que hice en MPLAB SIM funciona perfectamente, ¿alguien tiene un explicación sobre esto?
Publica tu programa para ver que hiciste
 
Gracias Fogonazo. He hecho una simplificación total del tema para ver cual es el problema, lo pongo aqui:
La rutina principal solo prende y apaga un led RB7 en un loop continuamente y cuando provoco la interrupción prende y apaga una vez el led en RB6, esto es solo para probar y funciona en el MPLAB SIM pero no en vivo.

Código:
#include      <p16f648A.inc>

    __CONFIG      _INTOSC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF & _LVP_OFF & _CPD_OFF & _CP_OFF

        errorlevel -302;     suppress message 302 from list file

W_TEMP                 EQU        0X20
STATUS_TEMP        EQU        0X21
CONT1                    EQU        0X22
CONT2                    EQU        0X23
CONT3                    EQU        0X24

                               ORG    H'0'
Inicio                      goto    begin            ;
                               ORG    H'4'
int                           clrf       PORTA           ;clear porta
                               clrf       PORTB           ;clear portb
                               bcf        INTCON,0        ;clear flag rbif el indicador de int de change in portb(7,6,5,4)
                               bcf        INTCON,7        ;clear GIE General enable bit
                               movwf    W_TEMP            ;W(A,B)-->W_TEMP(A,B)
                               swapf    STATUS,w        ;STATUS(A,B) -*->W(B,A)
                               movwf    STATUS_TEMP        ;W(B,A)-->STATUS_TEMP(B,A)
                               bsf        PORTA,6            ;
                               call    dex500ms        ;
                               bcf        PORTA,6            ;
                               call    dex500ms        ;              
                               swapf    STATUS_TEMP,w    ;STATUS_TEMP(B,A)-*-> W(A,B)
                               movwf    STATUS            ;W(A,B)-->STATUS(A,B)
                               swapf    W_TEMP,f        ;W_TEMP(A,B)-*->W_TEMP(B,A)
                              swapf    W_TEMP,w        ;W_TEMP(B,A)-*-> W
                              retfie                 ;regresa al programa principal


;------------------------------------------------------------------------------------------------------------

begin                    clrf       PORTA           ;clear porta,0 call    chtobk1
                              clrf       PORTA           ;clear porta,0
                              bcf        OPTION_REG,7        ;pull up resistores
                              clrf    VRCON                   ;deshabilita voltaje de referencia y libera el pin ra(2)
                              movlw    0x00                  ;'00000000' (1e) --> w
                              movwf    PIE1                  ;disable periferel interrupts
                              movwf    TRISA                ; w-->trisa, pins a(7,6,5,0)salidas, pins a(4,3,2,1)entradas
                              movlw    0xf0                   ;'11110000' (00) --> w
                              movwf    TRISB                ;w --> trisb, pins b(7,6,5,4)entradas, pins b(3,2,1,0) salidas
                              call    chtobk0                  ;banco 0
                              movlw    0x07                   ;'00000111' --> w
                              movwf    CMCON             ;deshabilita comparad. y desconecta ra(0,1,2 y 3) de los comparadores
                              bcf        INTCON,RBIF       ;desabilita flag de RB
                              bsf        INTCON,GIE         ;habilita interrupciones globales
                               bsf        INTCON,RBIE       ;habilita interrupcions RB
loop                        bsf        PORTA,7            ;prende led portb(0)      
                               call    dex500ms                 ;delay 500ms
                               bcf        PORTA,7                ;apaga led portb(0)
                               call    dex500ms                  ;delay 500ms          
                               goto    loop                         ;




chtobk0                   bcf        STATUS,RP0;cambia a banco 0
                                bcf        STATUS,RP1;
                                return;
chtobk1                   bsf        STATUS,RP0;cambia a banco 1
                                bcf        STATUS,RP1;
                                return;
chtobk2                   bcf        STATUS,RP0;cambia a banco 2
                                bsf        STATUS,RP1;
                                return;
chtobk3                   bsf        STATUS,RP0;cambia a banco 3
                                bsf        STATUS,RP1;
                               return;

dex500ms                   movlw    0x01
                                   movwf     CONT3
sigue3                        movlw     0xff
                                   movwf     CONT2
sigue2                         movlw     0xff
                                   movwf    CONT1
sigue1                        decfsz     CONT1,1
                                   goto    sigue1;
                                   decfsz    CONT2,1
                                   goto    sigue2
                                   decfsz    CONT3,1
                                  goto    sigue3
                                 return
                         end
 
Última edición:
Aca envio el programa un poco más ordenado en PDF en el que se presenta el problema que se detalla:

"Estoy trabajando con un pic 16f648a con interrupciones por cambios en el port B (4,5,6,7) el problema es que al producir una interrupción el pc salta correctamente a la dirección 0004H y ejecuta la ISR pero al ejecutar la RETFIE no regresa inmediatamente al programa principal sino que se queda, supongo, en un bucle que toma como 52 segundos y después de eso recién continua con el programa principal, lo más raro es que probando el programa en la simulación que hice en MPLAB SIM funciona perfectamente, ¿alguien tiene un explicación sobre esto?"
 

Adjuntos

  • INTERRUPTS WITH RB4 ... RB7.pdf
    103.7 KB · Visitas: 13
No estoy nada puesto en el ensamblador de los pic pero
¿Las etiquetas no llevan dos puntos al final?
Inicio:

¿Las instrucciones llevan o no llevan ; al final? En unas lineas los pones y en otras no.
Que yo sepa es para poner detrás un comentario pero en unas va, en otras no, no hay espacios...

Pones org h'0' que yo sepa eso no sé lo que es '0' es el valor ascii del 0, no es el número 0
Lo mismo con el org h'4' creo o al menos me resulta confusa esa nomenclatura.
Si antes has usado 0x20 para los ecus, usa lo mismo.
creo que mejor pon org 0 y org 4 sin mas; son los mismos números en hexa que en dec
 
En principio lo que se vé de terror es el manejo de la interrupción (en el último PDF)
- Alterás Z (con clrf) al inicio y después guardás el estado.
- Meter un delay en una interrupción es mala palabra, muchísimo peor que el goto para los informáticos ;)
- La interrupción no termina con retfie sino con con un salto al bucle principal --> Además de aberrante ¿Para qué salvaste el estado?
 
Gracias Scooter:
1.- Entiendo que solo va la etiqueta sin ":"
2.- Las instrucciones llevan ";" para separar los comentarios, si no tienes comentarios puedes no ponerla pero no molesta si la pones.
3.- Creo que es lo mismo h'0' que 0x00, tienes razón voy a uniformizar eso
Muchas gracias Scooter por tu respuesta y consejos.

Gracias Eduardo:
1.- Tienes razón voy a cambiar eso, no me di cuenta del cambio en Z con el clrf, lo quitaré
2.- No sabia pero el delay es solo para visualizar el ingreso a la ISR luego lo quitaré, prometo no poner mas malas palabras.
3.- Si, en el original esta con retfie pero ante la desesperación de no poder solucionar el problema hice muchos cambios y pruebas y se quedó en el PDF pero con el retfie se presenta el problema.
4.- Voy a probar nuevamente sin los clrf y asegurarme de poner el retfie.
Muchas gracias Eduardo por tu respuesta y consejos.
 
Además de los comentarios anteriores:

- Cuando se produce la interrupt on change no basta con limpiar RBIF, hay que leer el puerto. De lo contrario despues del RETFIE
se activa de vuelta la interrupción.

- Cuando se produce la interrupcion en el 99.999% de los casos se va a estar ejecutando el delay500ms --> al ejecutarse dentro de
la interrupcion te quedan CONT1,CONT2,CONT3 en 0 , por lo tanto cuando retorna al punto donde estaba el decfsz CONT3,1 se
va a ejecutar 256 veces. Como en realidad delay500ms temporiza aprox 200ms , 256 * 0.2s = 51s
Luego... la rutina de delay debe ser otra.

En el código están marcados con <<<--- los cambios , algunas instrucciones están cambiadas de lugar, lo que sobraba va marcado como comentario y alargué un poco los delays.

Código:
#include    <p16f648A.inc>

        __CONFIG _INTOSC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _BOREN_OFF & _LVP_OFF & _CPD_OFF & _CP_OFF
        errorlevel -302         ;   suppress message 302 from list file

;--------------------------DEFINICIONES----------------------------------------------------------
W_TEMP  EQU  0X20
STATUS_TEMP  EQU  0X21

CONT1   EQU  0X22
CONT2   EQU  0X23
CONT3   EQU  0X24

CONT1_int   EQU  0X25           ; <<<---  Variables para otro delay
CONT2_int   EQU  0X26           ;
CONT3_int   EQU  0X27           ;

;--------------------------PROGRAMA--------------------------------------------------------------
        ORG     H'0'
        ORG     H'0'
Inicio  goto    begin
        ORG     H'4'
;--------------------------RUTINA DE INTERRUPCION------------------------------------------------
int
        movwf   W_TEMP          ;W(A,B)-->W_TEMP(A,B)
        swapf   STATUS,w        ;STATUS(A,B) -*->W(B,A)
        movwf   STATUS_TEMP     ;W(B,A)-->STATUS_TEMP(B,A)
        ;-----------------------
      ;  clrf    PORTA           ;clear porta
      ;  clrf    PORTB           ;clear portb
        bsf     PORTA,6
        call    dex500ms_int
        bcf     PORTA,6
        call    dex500ms_int

        movf    PORTB,w         ; <<<--- Hay que leer el puerto
        bcf     INTCON,0        ;clear flag rbif el indicador de int de change in portb(7,6,5,4)

      ;  bcf     INTCON,7       ; <<<--- RETFIE se encarga de esto

        ;-----------------------
        swapf   STATUS_TEMP,w   ;STATUS_TEMP(B,A)-*-> W(A,B)
        movwf   STATUS          ;W(A,B)-->STATUS(A,B)
        swapf   W_TEMP,f        ;W_TEMP(A,B)-*->W_TEMP(B,A)
        swapf   W_TEMP,w        ;W_TEMP(B,A)-*-> W

        retfie                  ; <<<--- Por favor, no termines las interrupciones de otra manera.
        
;---------------------------PRINCIPAL------------------------------------------------------------
begin   call    chtobk1
        bcf     OPTION_REG,7    ;pull up resistores
        clrf    VRCON           ;deshabilita voltaje de referencia y libera el pin ra(2)
        movlw   0x00            ;'00000000' (1e) --> w
        movwf   PIE1            ;disable periferel interrupts
        movwf   TRISA           ; w-->trisa, pins a(7,6,5,0)salidas, pins a(4,3,2,1)entradas
        movlw   0xf0            ;'11110000' (00) --> w
        movwf   TRISB           ;w --> trisb, pins b(7,6,5,4)entradas, pins b(3,2,1,0) salidas
        call    chtobk0         ;banco 0
        clrf    PORTA           ; <<<--- Para que arranque los leds apagados
        movlw   0x07            ;'00000111' --> w
        movwf   CMCON           ;deshabilita comparad. y desconecta ra(0,1,2 y 3)
        bcf     INTCON,RBIF     ;desabilita flag de RB
        bsf     INTCON,GIE      ;habilita interrupciones globales

        movf    PORTB,w         ; <<<--- Hay que leer el puerto
        bcf     INTCON,0        ; <<<--- Se limpia la interrupcion porque si no cuando se
                                ;        habilite RBIE  se genera una interrupcion.

        bsf     INTCON,RBIE     ;habilita interrupcions RB

loop    bsf     PORTA,7    ;prende led portb(0)
        call    dex500ms        ;delay 500ms
        bcf     PORTA,7         ;apaga led portb(0)
        call    dex500ms        ;delay 500ms
        goto    loop
;---------------------------CAMBIO DE BANCOS-----------------------------------------------------
chtobk0 bcf  STATUS,RP0         ;cambia a banco 0
        bcf  STATUS,RP1
        return

chtobk1 bsf  STATUS,RP0         ;cambia a banco 1
        bcf  STATUS,RP1
        return

chtobk2 bcf  STATUS,RP0         ;cambia a banco 2
        bsf  STATUS,RP1
        return

chtobk3 bsf  STATUS,RP0         ;cambia a banco 3
        bsf  STATUS,RP1
        return
;---------------------------DELAY----------------------------------------------------------------

dex500ms
        movlw  0x03
        movwf   CONT3
sigue3  movlw   0xff
        movwf   CONT2
sigue2  movlw   0xff
        movwf   CONT1
sigue1  decfsz  CONT1,1
        goto    sigue1
        decfsz  CONT2,1
        goto    sigue2
        decfsz  CONT3,1
        goto    sigue3
        return


dex500ms_int                    ; <<<--- No se puede usar la misma rutina de retardo
        movlw  0x03             ;        en la interrupcion.
        movwf   CONT3_int       ;
sigue3_int                      ;
        movlw   0xff            ;
        movwf   CONT2_int       ;
sigue2_int                      ;
        movlw   0xff            ;
        movwf   CONT1_int       ;
sigue1_int                      ;
        decfsz  CONT1_int,1     ;
        goto    sigue1_int      ;
        decfsz  CONT2_int,1     ;
        goto    sigue2_int      ;
        decfsz  CONT3_int,1     ;
        goto    sigue3_int      ;
        return                  ;

        end
 
Atrás
Arriba