TODOPIC

Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: cristhiamjara en 18 de Mayo de 2020, 21:33:47

Título: se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 18 de Mayo de 2020, 21:33:47
Hola a toda la comunidad, me llamo Cristhiam, estoy aprendiendo a programar pics con assembly
Estuve practicando las interrupciones con los pines rb4-rb7 del portb, es muy extraño lo que sucede pero trataré de hacerles entender lo mas claro posible.

Org0x04 ;aqui viene cuando hay un cambio de estado en los pines rb4-rb7
-hago operaciones logicas y matematicas
-guardo el resultado en un registro, digamos VALOR
-paso VALOR a portA : VALOR --> portA (digamos que VALOR esta cargado con b'1010') y muestro el resultado en un arreglo de leds, que me sirve para verificar su contenido en binario
-hasta el paso anterior todo ok
-luego quiero salir de la interrupcion, hago bcf intcon,0 y luego retfie
-inmediatamente se cambia el valor binario en mis leds a un valor aleatorio que no se de donde aparece
-luego hago un testo y llamo a VALOR y muestro su contenido en portA a través del arreglo de leds, y me doy con la sorpresa que su valor se ha modificado.
-ese es mi gran problema, ya revisé mi código muchas veces y no escribí nada que modifique el contenido de VALOR.
Apreciaría mucho que me ayuden a entender que está sucediendo
gracias de antemano a todos  :-/ :-/
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: Eduardo2 en 18 de Mayo de 2020, 22:17:35
- Cuando entrás en la interrupción ¿Salvás estado?
- Al volver ¿Lo recuperás?
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 18 de Mayo de 2020, 23:17:47
- Cuando entrás en la interrupción ¿Salvás estado?
- Al volver ¿Lo recuperás?
hola eduardo, gracias por contestar.
Mira cuando inicia el programa
haga clrf VALOR
-hago mis rutinas normales y ninguna incluye modificar el contenido de VALOR
-cuando ocurre una interrupcion hago las operaciones y al final cargo el resultado en VALOR, y todo correcto
hasta una linea antes del retfie e podido verificar q VALOR esta con el contenido debido, cuando retorno de la interrupcion se modifica el contenido de VALOR
y eso es lo que no comprendo.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 18 de Mayo de 2020, 23:25:13
Código: [Seleccionar]
            org    0x04
            operaciones
            guardo el resultado en valor_real
            movfw   valor_real
    movwf   portb  ;test para comprobar que se tiene el contenido esperado
            retfie     ;para regresar de la interrupcion

el problema ocurre de regreso a la rutina
los leds que deje con el contenido de valor_real se modifican, luego ya en la rutina, osea no en la interrupcion, llamo el contenido de valor_real y los mando a los leds, pero ya no tiene
el contenido debido, sino que se modifico. Espero que me entiendan
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: Eduardo2 en 18 de Mayo de 2020, 23:35:11
A esto me refería, es la secuencia que Microchip pone en todos los datasheets.
Código: [Seleccionar]
        MOVWF W_TEMP        ;Copy W to TEMP register
        SWAPF STATUS,W      ;Swap status to be saved into W
        CLRF STATUS         ;bank 0, regardless of current bank, Clears IRP,RP1,R
        MOVWF STATUS_TEMP   ;Save status to bank zero STATUS_TEMP register
        MOVF PCLATH, W      ;Only required if using pages 1, 2 and/or 3
        MOVWF PCLATH_TEMP   ;Save PCLATH into W
        CLRF PCLATH         ;Page zero, regardless of current page
        :
        :(ISR)              ;(Insert user code here)
        :
        MOVF PCLATH_TEMP, W ;Restore PCLATH
        MOVWF PCLATH        ;Move W into PCLATH
        SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register into W
        ;(sets bank to original state)
        MOVWF STATUS        ;Move W into STATUS register
        SWAPF W_TEMP,F      ;Swap W_TEMP
        SWAPF W_TEMP,W      ;Swap W_TEMP into W 
       

Si no salvás y recuperás el estado el retorno es impredecible salvo que se esté en un bucle ocioso.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 19 de Mayo de 2020, 01:42:33
A esto me refería, es la secuencia que Microchip pone en todos los datasheets.
Código: [Seleccionar]
        MOVWF W_TEMP        ;Copy W to TEMP register
        SWAPF STATUS,W      ;Swap status to be saved into W
        CLRF STATUS         ;bank 0, regardless of current bank, Clears IRP,RP1,R
        MOVWF STATUS_TEMP   ;Save status to bank zero STATUS_TEMP register
        MOVF PCLATH, W      ;Only required if using pages 1, 2 and/or 3
        MOVWF PCLATH_TEMP   ;Save PCLATH into W
        CLRF PCLATH         ;Page zero, regardless of current page
        :
        :(ISR)              ;(Insert user code here)
        :
        MOVF PCLATH_TEMP, W ;Restore PCLATH
        MOVWF PCLATH        ;Move W into PCLATH
        SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register into W
        ;(sets bank to original state)
        MOVWF STATUS        ;Move W into STATUS register
        SWAPF W_TEMP,F      ;Swap W_TEMP
        SWAPF W_TEMP,W      ;Swap W_TEMP into W 
       

Si no salvás y recuperás el estado el retorno es impredecible salvo que se esté en un bucle ocioso.
tengo entendido que esto se hace para guardar los datos que se tienen antes de una interrupcion, ya que estos suelen cambiar durante las interrupciones. Pero en mi caso
los datos los genero dentro de la interrupcion y los guardo en un registro, y al volver de la interrupcion el valor de este registro tambien se modifica.
comparto mi código:
Código: [Seleccionar]
List p=16f84a
    #include <p16f84a.inc>
    __config _XT_OSC & _PWRTE_ON & _CP_OFF & _WDT_OFF
    org     0x00
;declaracion de variables
tmr0     equ     0x01
pcl     equ     0x02
status     equ     0x03
porta     equ     0x05
portb     equ     0x06
intcon     equ     0x0b
option_reg  equ     0x81
trisa     equ     0x85
trisb     equ     0x86
    cblock  0x0c
    conta
    filas
    columnas
    contaf
    f
    c
    valor_real
    temp
    d1
    d2
    flag
    endc
    goto    principal ;####################################
    org     0x04 ;######INTERRUPCIONES################    
    movfw   portb ;estoy leyendo 'abcdxxxx'
    movwf   columnas
    clrf    porta ;limpio porta para que no se queden colgados valores
    swapf   columnas,1 ;    ahora tengo 'xxxxabcd'
    call    delaym;
    bsf     flag,0
    nop
    movfw   contaf  ;carga w con el valor de contaf , conta
    xorlw   .1     ;comprueba si contaf vale 1
    btfsc   status,2 ;revisa : si Z=1 caso1, si Z=0 , volver a preguntar
    goto    casof1     ;;; aqui va si son iguales , caso1
    movfw   contaf     ;aqui va si no es caso 1
    xorlw   .2
    btfsc   status,2
    goto    casof2     ;;aqui va si es caso2
    movfw   contaf
    xorlw   .3
    btfsc   status,2
    goto    casof3     ;caso3
casof4     movlw   .12     ;de lo contrario pasa a casof4
    movwf   f    
    goto    chkcol;return    
casof3     movlw   .8
    movwf   f
    goto    chkcol;return
casof2     movlw   .4
    movwf   f
    goto    chkcol;return
casof1     movlw   .0
    movwf   f
chkcol     ;movfw   columnas;carga w con el valor capturado de portb en columnas
    btfss   columnas,0
    goto    $+2
    goto    casoc1     ;aqui va caso1    
    btfss   columnas,1
    goto    $+2    
    goto    casoc2
    btfss   columnas,2
    goto    $+2
    goto    casoc3
    btfss   columnas,3
    goto    $+2
casoc4     movlw   .3
    movwf   c
    goto    sumar;retfie
casoc3     movlw   .2    
    movwf   c
    goto    sumar;retfie
casoc2     movlw   .1
    movwf   c
    goto    sumar;retfie
casoc1     movlw   .0
    movwf   c
    goto    sumar;retfie
sumar     movf    c,0 ;cargamos w con el valor de c
    addwf   f,0 ;sumamos w con f y lo guardamos en w
    movwf   valor_real ;cargamos valor_real con el valor de la suma
    ;ya tengo mi valor real################################!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    ;ya tengo mi valor real################################!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
verificar   movfw   contaf ;verifica sin contaf=4 para reiniciarlo, casos contrarios <4 se incrementa su valor en 1
    xorlw   .1
    btfss   status,2 ;1 si son iguales,  0 si son diferentes
    goto    $+2
    goto    increment
    movfw   contaf
    xorlw   .2
    btfss   status,2 ;1 si son iguales, 0 si son diferentes
    goto    $+2
    goto    increment
    movwf   contaf
    xorlw   .3
    btfss   status,2
    goto    $+2
    goto    increment ; si esq si es el caso 3
re     movlw   .1    ;
    movwf   contaf  ;reinicia conta=1
    movwf   filas   ;filas=0001
    movfw   valor_real ;cargamos w con valor_real para pruebas
    movwf   portb
    call    delay500ms
    ;call    delay500ms
    ;call    delay500ms
    ;call    delay500ms
    movfw   filas   ;reinicia filas=0001
    goto    salir
increment   incf    contaf,1
    rlf     filas,1
    movfw   valor_real
    movwf   portb
    call    delay500ms
    ;call    delay500ms
    ;call    delay500ms
    ;call    delay500ms
    movfw   filas  ; 0002,3,4    
salir     bcf     intcon,0
    retfie 
principal   ;##############################################
    ;IOs
    bsf     status,5
    movlw   b'10000'   ;porta como salidas
    movwf   trisa
    movlw   b'11110000'
    movwf   trisb
    movlw   b'11010111' ;rbpullup no, intedge=subida, t0cs=f/4 ,t0ie:bajada, psa->tmr0 ratio 1:256
    movwf   option_reg
    bcf     status,5;de vuelta al banco0
    movlw   b'10001000'
    movwf   intcon
    clrf    porta
    clrf    portb
    movlw   .1 ;cargar 1
    movwf   contaf  ;se inicia con 1
    movwf   filas   ;se inicia con 0001
    clrf    valor_real
    clrf    columnas
    goto    inicio
delay50ms
    movwf   temp
    movlw   .60
    movwf   tmr0
    btfss   intcon,2
    goto    $-1
    bcf     intcon,2
    movfw   temp
    return
delaym
    movwf   temp
    movlw   .220
    movwf   tmr0
    btfss   intcon,2
    goto    $-1
    bcf     intcon,2
    movfw   temp
    return
delay500ms
    movwf   temp
    movlw   .10
    movwf   d1
    call    delay50ms
    decfsz  d1
    goto    $-2
    movfw   temp
    return
notecla    
    movfw   contaf  ;verificar si contaf es 4
    xorlw   .4     ;verificar si contaf es 4
    btfsc   status,2;verificar si contaf es 4
    goto    si4
    incf    contaf,1  ;si son diferentes
    rlf     filas,1
    movfw   filas
    return
si4     movlw   .1
    movwf   contaf
    movwf   filas
    movfw   filas
    return    
inicio    
    btfss   flag,0
    goto    aqui
    bcf     flag,0
    clrf    porta
    nop
aqui     ;bsf     intcon,7
    movfw   filas   ;w se carga con el valor de filas *******
    movwf   porta
    nop
    call    delaym    
    call    notecla
    nop
    nop;aqui va lo que se hará si no se presiono una tecla
    goto    inicio
    end
es un programa para leer un teclado matricial y mostrar la tecla presionada en un diplay a traves de un codificador bcd 74ls48
(https://lh3.googleusercontent.com/cHekHSve2K3oPRSRjc-eGQwhm79AVY-nt60CQxLZzsin9Zr1e9lBuwuJumkBmHoyAePhpcGS_4shhk3D2SocQIHiPpvfKVRp9P9GSixrpcVVj6fuKNRNPi5BiSX9pEWQKbMOaQ4Vyzatz3zoZSsHvlXAJgQ3IvEjv0LSv1KTX_wGaDykdJtW9xUKEcOrooq7rJK-tt_MulcWP1hLkykCOEFAPTXndhbHcgNp9BJCECYeLKuCNk_lCGGMQd8CN5Fxa7oMFVWOHLybVTYbOSZWCjZhwfIDu6jxs1kD89TlGpKMi_rCAMMLiDUit9AT26nCMtQE2slyHLp_iTetPt9HxGaZ-z4uMqaylvhLYqdR5eYbNPcIdZWovyUTTdf2lKF_bpI05UV8lEw4Q6lizWYOTgbky85hChEalM3FFguOMwiCXjLSFgfUtr05i6-LUt4VabRyfDd-hyyiKbtni4lB6jUniSHSpZu26N-CAZfoEUa0sMy7ZQ3Fj_sXQzQIHoCVbXjxXRjX83jb5V3_Y3jft2z3DPC-EStp71StUvcU0LxxGdGuB7d970KWEEri8PiYyp8a3IQvLqJJl0XhZ3heBgPzlI29PmbctDdg8uhEqRDG6oIdP91bk8zOZ69ZLnEQzpu4ldGhYgT1rFPL8KD4xxI0UyTebp_zqYPP92o8aXxhnaZfNiWag5571c0d=w1336-h706-no?authuser=0)
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: KILLERJC en 19 de Mayo de 2020, 08:23:45
Citar
tengo entendido que esto se hace para guardar los datos que se tienen antes de una interrupcion


Ese codigo que te pasaron se DEBE realizar SIEMPRE, te doy un ejemplo:

Tu programa principal esta corriendo y antes de un BTFSS STATUS,Z salta a la interrupcion, vamos as decir que las banderas estaban en Z=1 C=0 (es decir no ejecuta el BTFSS)
En la interrupcion entras y operas, el registro STATUS cambia por las instrucciones que usas, llegas al final y tu registro status quedo Z=0 C=0
Vuelve al programa y ejecuta el BTFSS... Sorpresa, el BTFSS no salta porque Z=0...

Lo mismo puede ocurrir con W, si tenes cualquier instruccion que tome de W para operar y tenes una interrupcion antes, vas a tener problemas. Entonces ese código ES OBLIGATORIO en es PIC (hay otros PIC que tiene un auto-guardado)

Y como ves en tu programa estas modificando W y STATUS (con otras instrucciones) en todo momento.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: Leon Pic en 19 de Mayo de 2020, 09:34:48
Me parece, que el problema te lo da el call delaym dentro de la interrupción.
Por un tema del contador de programa, es preferible que todas las subrutinas estén por encima del programa, así cuando el CP tiene que volver, lo puede hacer sin problemas.
Entonces, en tu programa, el call tiene que ir más abajo y al subir, puede ser que lo esté haciendo en cualquier lado del programa; y no desde lo llamaste. Deberías simular esto con MPLAB; y asegurarte que retorne al lugar correcto.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 19 de Mayo de 2020, 13:25:22
Me parece, que el problema te lo da el call delaym dentro de la interrupción.
Por un tema del contador de programa, es preferible que todas las subrutinas estén por encima del programa, así cuando el CP tiene que volver, lo puede hacer sin problemas.
Entonces, en tu programa, el call tiene que ir más abajo y al subir, puede ser que lo esté haciendo en cualquier lado del programa; y no desde lo llamaste. Deberías simular esto con MPLAB; y asegurarte que retorne al lugar correcto.

hola, en este caso todas las subrutinas estan por encima del programa pero debajo de la interrupción, debería colocar las subrutinas por arriba de org0x04?
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 19 de Mayo de 2020, 13:38:10
Citar
tengo entendido que esto se hace para guardar los datos que se tienen antes de una interrupcion


Ese codigo que te pasaron se DEBE realizar SIEMPRE, te doy un ejemplo:

Tu programa principal esta corriendo y antes de un BTFSS STATUS,Z salta a la interrupcion, vamos as decir que las banderas estaban en Z=1 C=0 (es decir no ejecuta el BTFSS)
En la interrupcion entras y operas, el registro STATUS cambia por las instrucciones que usas, llegas al final y tu registro status quedo Z=0 C=0
Vuelve al programa y ejecuta el BTFSS... Sorpresa, el BTFSS no salta porque Z=0...

Lo mismo puede ocurrir con W, si tenes cualquier instruccion que tome de W para operar y tenes una interrupcion antes, vas a tener problemas. Entonces ese código ES OBLIGATORIO en es PIC (hay otros PIC que tiene un auto-guardado)

Y como ves en tu programa estas modificando W y STATUS (con otras instrucciones) en todo momento.
buenas, ya implementé el codigo de salvar status y w y recuperarlos antes de volver a la interrupción pero sigue ocurriendo lo mismo,
durante la interrupcion mando un valor al display y al retornar de la interrupion el display cambia y muestra otro valor, osea las salidas del pic cambia de estado.
A pesar que en bluckle principal no tengo ninguna sentencia que mande valores de salida al puerto.
PD: Gracias a todos por su atención
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: Leon Pic en 19 de Mayo de 2020, 18:42:25
Me parece, que el problema te lo da el call delaym dentro de la interrupción.
Por un tema del contador de programa, es preferible que todas las subrutinas estén por encima del programa, así cuando el CP tiene que volver, lo puede hacer sin problemas.
Entonces, en tu programa, el call tiene que ir más abajo y al subir, puede ser que lo esté haciendo en cualquier lado del programa; y no desde lo llamaste. Deberías simular esto con MPLAB; y asegurarte que retorne al lugar correcto.

hola, en este caso todas las subrutinas estan por encima del programa pero debajo de la interrupción, debería colocar las subrutinas por arriba de org0x04?

Para ser más preciso, en las interrupciones se trata de hacer lo menos posible; y por sobretodo evitar llamar con call. Si lo haces, tenes que asegurarte de no sobrepasar la pila. El pic que estás usando, tiene un tamaño de 8 posiciones la pila; por lo que podes llamar hasta 8 veces la pila en forma anidada. O sea, llamas con un call, dentro de ese; llamás a otro, y así hasta 8 veces. El problema que las interrupciones consumen una posición de pila.

Ahora bien. Cada llamado debe de estar por encima. El call de la interrupción, está en la posición 0x08, y la subrutina llamada está 0x74
Esto debe ser al revés; o sea, la subrutina tiene que estar en una posición más chica que la llamada (dije por encima, al principio, porque es por el orden en cascada que se escribe el programa). Te doy un ejemplo:


Código: ASM
  1. org 0x00
  2.         goto principal
  3. org 0x04
  4.         MOVWF W_TEMP        ;Copy W to TEMP register
  5.         SWAPF STATUS,W      ;Swap status to be saved into W
  6.         CLRF STATUS         ;bank 0, regardless of current bank, Clears IRP,RP1,R
  7.         MOVWF STATUS_TEMP   ;Save status to bank zero STATUS_TEMP register
  8.         MOVF PCLATH, W      ;Only required if using pages 1, 2 and/or 3
  9.         MOVWF PCLATH_TEMP   ;Save PCLATH into W
  10.         CLRF PCLATH         ;Page zero, regardless of current page
  11.         goto interrupcion
  12. ;
  13. delay50ms
  14.             movwf   temp
  15.             movlw   .60
  16.             movwf   tmr0
  17.             btfss   intcon,2
  18.             goto    $-1
  19.             bcf     intcon,2
  20.             movfw   temp
  21.             return
  22. delaym
  23.             movwf   temp
  24.             movlw   .220
  25.             movwf   tmr0
  26.             btfss   intcon,2
  27.             goto    $-1
  28.             bcf     intcon,2
  29.             movfw   temp
  30.             return
  31. delay500ms
  32.             movwf   temp
  33.             movlw   .10
  34.             movwf   d1
  35.             call    delay50ms
  36.             decfsz  d1
  37.             goto    $-2
  38.             movfw   temp
  39.             return
  40. ;
  41. notecla
  42.             movwf temp     
  43.             movfw   contaf  ;verificar si contaf es 4
  44.             xorlw   .4      ;verificar si contaf es 4
  45.             btfsc   status,2;verificar si contaf es 4
  46.             goto    si4
  47.             incf    contaf,1  ;si son diferentes
  48.             rlf     filas,1
  49.             movfw   filas
  50.             movfw temp
  51.             return
  52. si4         movlw   .1
  53.             movwf   contaf
  54.             movwf   filas
  55.             movfw   filas
  56.             return
  57. ;
  58. interrupcion
  59.             movfw   portb       ;estoy leyendo 'abcdxxxx'
  60.             movwf   columnas
  61.             clrf    porta ;limpio porta para que no se queden colgados valores
  62.             swapf   columnas,1 ;    ahora tengo 'xxxxabcd'
  63.             call    delaym;
  64.             bsf     flag,0
  65.             nop
  66.             movfw   contaf  ;carga w con el valor de contaf , conta
  67.             xorlw   .1      ;comprueba si contaf vale 1
  68.             btfsc   status,2    ;revisa : si Z=1 caso1, si Z=0 , volver a preguntar
  69.             goto    casof1          ;;; aqui va si son iguales , caso1
  70.             movfw   contaf          ;aqui va si no es caso 1
  71.             xorlw   .2
  72.             btfsc   status,2
  73.             goto    casof2          ;;aqui va si es caso2
  74.             movfw   contaf
  75.             xorlw   .3
  76.             btfsc   status,2
  77.             goto    casof3          ;caso3
  78. casof4      movlw   .12     ;de lo contrario pasa a casof4
  79.             movwf   f      
  80.             goto    chkcol;return          
  81. casof3      movlw   .8
  82.             movwf   f
  83.             goto    chkcol;return
  84. casof2      movlw   .4
  85.             movwf   f
  86.             goto    chkcol;return
  87. casof1      movlw   .0
  88.             movwf   f
  89. chkcol      ;movfw   columnas;carga w con el valor capturado de portb en columnas
  90.             btfss   columnas,0 
  91.             goto    $+2
  92.             goto    casoc1          ;aqui va caso1         
  93.             btfss   columnas,1
  94.             goto    $+2    
  95.             goto    casoc2
  96.             btfss   columnas,2
  97.             goto    $+2
  98.             goto    casoc3
  99.             btfss   columnas,3
  100.             goto    $+2
  101. casoc4      movlw   .3 
  102.             movwf   c
  103.             goto    sumar;retfie
  104. casoc3      movlw   .2     
  105.             movwf   c
  106.             goto    sumar;retfie
  107. casoc2      movlw   .1
  108.             movwf   c
  109.             goto    sumar;retfie
  110. casoc1      movlw   .0
  111.             movwf   c
  112.             goto    sumar;retfie
  113. sumar       movf    c,0 ;cargamos w con el valor de c
  114.             addwf   f,0 ;sumamos w con f y lo guardamos en w
  115.             movwf   valor_real  ;cargamos valor_real con el valor de la suma
  116.             ;ya tengo mi valor real################################!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  117.             ;ya tengo mi valor real################################!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  118. verificar   movfw   contaf      ;verifica sin contaf=4 para reiniciarlo, casos contrarios <4 se incrementa su valor en 1
  119.             xorlw   .1
  120.             btfss   status,2    ;1 si son iguales,  0 si son diferentes
  121.             goto    $+2
  122.             goto    increment
  123.             movfw   contaf
  124.             xorlw   .2
  125.             btfss   status,2    ;1 si son iguales, 0 si son diferentes
  126.             goto    $+2
  127.             goto    increment
  128.             movwf   contaf
  129.             xorlw   .3
  130.             btfss   status,2
  131.             goto    $+2
  132.             goto    increment   ; si esq si es el caso 3
  133. re          movlw   .1     ;
  134.             movwf   contaf  ;reinicia conta=1
  135.             movwf   filas   ;filas=0001
  136.             movfw   valor_real  ;cargamos w con valor_real para pruebas
  137.             movwf   portb
  138.             call    delay500ms
  139.             ;call    delay500ms
  140.             ;call    delay500ms
  141.             ;call    delay500ms
  142.             movfw   filas   ;reinicia filas=0001
  143.             goto    salir      
  144. increment   incf    contaf,1
  145.             rlf     filas,1
  146.             movfw   valor_real
  147.             movwf   portb
  148.             call    delay500ms
  149.             ;call    delay500ms
  150.             ;call    delay500ms
  151.             ;call    delay500ms
  152.             movfw   filas  ; 0002,3,4      
  153. salir       MOVF PCLATH_TEMP, W ;Restore PCLATH
  154.         MOVWF PCLATH        ;Move W into PCLATH
  155.         SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register into W
  156.         ;(sets bank to original state)
  157.         MOVWF STATUS        ;Move W into STATUS register
  158.         SWAPF W_TEMP,F      ;Swap W_TEMP
  159.         SWAPF W_TEMP,W      ;Swap W_TEMP into W
  160.         bcf         intcon,0
  161.         retfie  
  162.  ;
  163. principal   ;##############################################
  164.             ;IOs
  165.             bsf     status,5
  166.             movlw   b'10000'   ;porta como salidas
  167.             movwf   trisa
  168.             movlw   b'11110000'
  169.             movwf   trisb
  170.             movlw   b'11010111' ;rbpullup no, intedge=subida, t0cs=f/4 ,t0ie:bajada, psa->tmr0 ratio 1:256
  171.             movwf   option_reg
  172.             bcf     status,5;de vuelta al banco0
  173.             movlw   b'10001000'
  174.             movwf   intcon
  175.             clrf    porta
  176.             clrf    portb
  177.             movlw   .1 ;cargar 1
  178.             movwf   contaf  ;se inicia con 1
  179.             movwf   filas   ;se inicia con 0001
  180.             clrf    valor_real
  181.             clrf    columnas
  182.            ; goto    inicio
  183.  inicio  btfss   flag,0
  184.             goto    aqui
  185.             bcf     flag,0     
  186.             clrf    porta
  187.             nop
  188. aqui        ;bsf            intcon,7
  189.             movfw   filas   ;w se carga con el valor de filas *******
  190.             movwf   porta
  191.             nop
  192.             call    delaym         
  193.             call    notecla
  194.             nop
  195.             nop;aqui va lo que se hará si no se presiono una tecla
  196.             goto    inicio
  197.             end

Ahora, el la llamada del call dentro de la rutina de interrupción, está por debajo de las subrutinas (hablando de la escritura en cascada). Si ahora lo vemos por la posición de memoria, la subrutina llamada delay500ms está en la posición 0x14 y el call que llama a esta subrutina está en la posición 0x36 (no te guíes por las numeraciones de línea. Recuerda que las etiquetas no ocupan posición de memoria, y las intrucciones que están con ; no son cargadas al pic.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 20 de Mayo de 2020, 13:32:49
Gracias Leon, probé el código modificado que sugeriste, pero sigue con el mismo resultado inesperado, por algún motivo que aún no entiendo el valor en mi display se modifica
No sé si compilaste el código en el circuito que adjunté en la foto, espero que se animen a hacerlo y así podamos resolver este problema.
Gracias!
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: Leon Pic en 20 de Mayo de 2020, 17:55:20
Me parece que ya encontré el error.
La subrutina notecla te estaba cambiando el valor de w. En la subrutina de delay, lo salvabas en una variable llamada temp para luego recuperar este dato antes de salir, pero en la otra no lo hiciste.

Volvé a carga mi programa de mi mensaje anterior, que ya lo actualicé.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 20 de Mayo de 2020, 19:25:36
Me parece que ya encontré el error.
La subrutina notecla te estaba cambiando el valor de w. En la subrutina de delay, lo salvabas en una variable llamada temp para luego recuperar este dato antes de salir, pero en la otra no lo hiciste.

Volvé a carga mi programa de mi mensaje anterior, que ya lo actualicé.
Hola de nuevo, ya lo probé y sigue igual,
fijate que dentro de todo el programa la única linea donde hago un "movwf portb" está dentro de la interrupción, en ninguna otra parte mando valores al portb, por eso no entiendo porque se cambia mi display que va conectado al portb.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: Leon Pic en 21 de Mayo de 2020, 09:49:13
Vamos a partir del principio, como debimos hacerlo.
Primero, explicá mejor como funciona, ya que no se bien que es lo que tiene que hacer.

Necesito saber que hace cada rutina o subrutina; excepto las de delay que son obvias; ya que me pierdo en el programa. Que obtenés en cada rutina y en donde se guarda y para qué.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 21 de Mayo de 2020, 16:01:39
Vamos a partir del principio, como debimos hacerlo.
Primero, explicá mejor como funciona, ya que no se bien que es lo que tiene que hacer.

Necesito saber que hace cada rutina o subrutina; excepto las de delay que son obvias; ya que me pierdo en el programa. Que obtenés en cada rutina y en donde se guarda y para qué.
Ok aqui vamos:
Es un programa para detectar que tecla se a presionado en el teclado matricial, basicamente coloco un bit a 1 del portA y lo hago rotar, cuando se presiona una tecla se produce una interrupcion
y se hacen todas las operaciones para calcular el valor de la tecla que se presionó y se almacena en valor_real y valor real lo mando a los 4 primeros pines del portb que van conectados al display.
Todo funciona ok, valor_real se carga con el valor de la tecla que le corresponde pero luego inexplicablemente se cambia a un valor que no se de donde aparece y modifica el resultado del display.
En todo el programa solamente una vez hago movwf portb y es para mover valor_real al portb, luego no hago esa llamada nunca mas, asi que no deberia cambiar el valor del display. Me resulta ilogico, te invito a que compiles el codigo y lo implementes en un circuito como el que puse en la foto de arriba.
Saludos y gracias.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: Leon Pic en 21 de Mayo de 2020, 16:42:26
¿Cómo está conectado el teclado al PIC? y ¿como está conectado el LCD al PIC?
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 21 de Mayo de 2020, 17:26:23
¿Cómo está conectado el teclado al PIC? y ¿como está conectado el LCD al PIC?
(https://lh3.googleusercontent.com/kMPytM-S2e9H340qYIohPT-TU7rHCtztOksX3VN1zM22MXCxNQTNWZl-YtLGC4BhSbcSYxpI--363FAvj90LAo_YFF2NVXwpZffOwDDQxCv8BfTT66Ltydfgk1BGc_D9tjbrvuqC_wUmAUvb6l14Apg7IScmOtpgsSc68D0XqtYEYz14OgxnTZCyC9LDaZAIBJ1uQUYZfAfasdseU37dfAQpUJqNLifSuSRs_Wt7rTj5dzZHzgDruamCDW7vmSYVDjHrBBmNTdvoPW3aPnuJbvlECcXLfuY0wT6cxakCdE4SPlUuRGKUxDWkr_gwg8t5g5Std2_TAZXh8_CPVGvC3831BX_MqVJfBIImWDDgcBaSWIaJ1I8MTVXNXjKLH_z-3LyzzaF7NEk8PbzmizIgPQAQq4qQzwcm73ALc3gp6DnlvoSfJVcQmEbeDVhLfOWbBv05AeGB4JCIjHJj4Zn9gdFBBt3OdgtFLp5KnWudTnhsrCKF1F4TZJ3xcUHIfqYfm5ABkKCEprFZH2g8jRAR-HkFWnqhJAedKpzYdbdz_ZA00PETpXIiDfBDqaCQ5OlLevrW-CVQEHPvvYdOdID_ZKcLxFQ2jv5wPts5C9fXcJdO7fpmO6mZULOArG7Kn-aPJUhNQ8owl40gmqnnO_KkDkihXtI1EwNjCEydphG1rUFzXJTxUH1dDJLrFyBP=w1336-h706-no?authuser=0)
como la imágen,
coloco un 0001 en porta y lo hago rotar con rlf
las interrupciones son por rb4-rb7
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: Leon Pic en 21 de Mayo de 2020, 19:19:47
No puedo ver la imagen.
Adjuntalo aquí en un tamaño no mayor de 800 x 600 pixeles.
En la ventana de respuestas, abajo, hay una opción que dice Adjuntos y otras opciones. Haz click en el + y podrás adjuntarlo.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 21 de Mayo de 2020, 21:16:15
No puedo ver la imagen.
Adjuntalo aquí en un tamaño no mayor de 800 x 600 pixeles.
En la ventana de respuestas, abajo, hay una opción que dice Adjuntos y otras opciones. Haz click en el + y podrás adjuntarlo.
listo  :-/ :-/
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: Leon Pic en 22 de Mayo de 2020, 12:15:18
Ahora entiendo bastante, pero me pierdo.
Dame un tiempo considerable, ya que debo simularlo para ver que está pasando.

Me da la impresión que; cuando lees el puerto a, que lo tienes como salida, recuperas el valor de lo que entrega este puerto. Como lo hace a 4mhz los cambios son muy rápidos, y en 1 segundo, el puerto cambió muchas veces. También, al tener RA4 como entrada, y al aire, está entrando mucho ruido. Pero es una teoría.

No obstante, tu programa para escanear un puerto y mostrarlo en un código BCD es muy complicado. En la red hay muchísimos programas ya escrito que hacen esto.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 22 de Mayo de 2020, 12:58:10
Ahora entiendo bastante, pero me pierdo.
Dame un tiempo considerable, ya que debo simularlo para ver que está pasando.

Me da la impresión que; cuando lees el puerto a, que lo tienes como salida, recuperas el valor de lo que entrega este puerto. Como lo hace a 4mhz los cambios son muy rápidos, y en 1 segundo, el puerto cambió muchas veces. También, al tener RA4 como entrada, y al aire, está entrando mucho ruido. Pero es una teoría.

No obstante, tu programa para escanear un puerto y mostrarlo en un código BCD es muy complicado. En la red hay muchísimos programas ya escrito que hacen esto.
Así es León, recupero el valor de porta que esta en filas, y recupero el valor de rb4-rb7 que está en columnas, hago operaciones para convertirlo en el valor de la tecla que se presionó y lo muestro al display.
Seguramente deben haber códigos mejores que este, apenas llevo 1 mes con esto de los pic en assembler y me sirve para desarrollar mi propia lógica.
Tienes razon que en 1 segundo mientras se presiona una tecla seguro se llevan a acabo varias interrupciones, pero todas deberían mostrar el mismo resultado ya que se está presionando la misma tecla.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: Eduardo2 en 22 de Mayo de 2020, 13:33:06
En la imagen que subiste no se ven resistencias de pulldown en RB4..7   

En lugar de confiar en que la electrostatica va a estar a tu favor, agregalas o  activá las resistencias de pullup del puerto.
Esto último es mas "correcto" pero es mas trabajo porque hay que reescribir el escaneo desplazando un 0 e invirtiendo la lógica de lectura.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: KILLERJC en 22 de Mayo de 2020, 14:42:34
Algo mas ismple para leer el teclado:
No esta probado el codigo, pero es mas corto
Código: ASM
  1. CLRF  PORTA
  2.   BSF   STATUS, C
  3. LOOPLEER:
  4.   RLF   PORTA, F
  5.   BTFSC PORTA, 4
  6.   GOTO  NO_BOTON
  7.   MOVLW 0xF0
  8.   ANDWF PORTB, W
  9.   BTFSS STATUS, Z
  10.   GOTO  LOOPLEER  ;Esta todo en 0, nada presionado
  11.   MOVF  PORTA, W  ;Si llego aca algo presionado hay
  12.   ANDLW 0xF
  13.   MOVWF BOTONES
  14.   MOVF  PORTB, W
  15.   ANDLW 0xF0
  16.   MOVWF BOTONES     ;Quedaria PORTB:PORTA
  17.   ;SWAPF BOTONES, F
  18.   CLRF PORTA
  19.   RETURN
  20.  
  21. NO_BOTON
  22.   CLRF PORTA
  23.   CLRF BOTONES
  24.   RETURN

Citar
Tienes razon que en 1 segundo mientras se presiona una tecla seguro se llevan a acabo varias interrupciones, pero todas deberían mostrar el mismo resultado ya que se está presionando la misma tecla.

Si estas usando la interrupcion de RB4-7, estos se activan por cambio de nivel, es decir cuando pasan de 0 a 1, o de 1 a 0. Por lo cual al tener presionado 1 sola tecla, entraria dos veces.
Cuando lo detecta el 1 (ya que activaste esa fila) o el 0 cuando cambiaste de fila o soltaste. Por lo que no creo que sea lo correcto usar este tipo de interrupcion para un teclado. Es mas rapido leerlo directamente, y luego si queres que se lea mas lento o no se repita podes hacerlo bajo interrupcion de un timer (mas lento) o comprobar que no es la misma tecla y esperar que se suelte (no se repita)
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 22 de Mayo de 2020, 18:11:15
En la imagen que subiste no se ven resistencias de pulldown en RB4..7   

En lugar de confiar en que la electrostatica va a estar a tu favor, agregalas o  activá las resistencias de pullup del puerto.
Esto último es mas "correcto" pero es mas trabajo porque hay que reescribir el escaneo desplazando un 0 e invirtiendo la lógica de lectura.
Hola Eduardo, si llevan resistencias pulldown, por eso esque hago rotar un 1
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 22 de Mayo de 2020, 18:13:18
Algo mas ismple para leer el teclado:
No esta probado el codigo, pero es mas corto
Código: ASM
  1. CLRF  PORTA
  2.   BSF   STATUS, C
  3. LOOPLEER:
  4.   RLF   PORTA, F
  5.   BTFSC PORTA, 4
  6.   GOTO  NO_BOTON
  7.   MOVLW 0xF0
  8.   ANDWF PORTB, W
  9.   BTFSS STATUS, Z
  10.   GOTO  LOOPLEER  ;Esta todo en 0, nada presionado
  11.   MOVF  PORTA, W  ;Si llego aca algo presionado hay
  12.   ANDLW 0xF
  13.   MOVWF BOTONES
  14.   MOVF  PORTB, W
  15.   ANDLW 0xF0
  16.   MOVWF BOTONES     ;Quedaria PORTB:PORTA
  17.   ;SWAPF BOTONES, F
  18.   CLRF PORTA
  19.   RETURN
  20.  
  21. NO_BOTON
  22.   CLRF PORTA
  23.   CLRF BOTONES
  24.   RETURN

Citar
Tienes razon que en 1 segundo mientras se presiona una tecla seguro se llevan a acabo varias interrupciones, pero todas deberían mostrar el mismo resultado ya que se está presionando la misma tecla.

Si estas usando la interrupcion de RB4-7, estos se activan por cambio de nivel, es decir cuando pasan de 0 a 1, o de 1 a 0. Por lo cual al tener presionado 1 sola tecla, entraria dos veces.
Cuando lo detecta el 1 (ya que activaste esa fila) o el 0 cuando cambiaste de fila o soltaste. Por lo que no creo que sea lo correcto usar este tipo de interrupcion para un teclado. Es mas rapido leerlo directamente, y luego si queres que se lea mas lento o no se repita podes hacerlo bajo interrupcion de un timer (mas lento) o comprobar que no es la misma tecla y esperar que se suelte (no se repita)
hola Killer, gracias por el code, lo voy a probar.
Respecto a las interrupciones es cierto que cuando presiono una tecla se ejecutan varias interrupciones, pero todas deberian arrojar el mismo resultado mientres presione la misma tecla
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: KILLERJC en 22 de Mayo de 2020, 23:41:05
Citar
pero todas deberian arrojar el mismo resultado mientres presione la misma tecla

A eso voy que es erroneo lo que planteas... Ya que para leer el teclado haces un barrido... Voy a intentar ser mas claro con un ejemplo.

Supongamos que tenes presionado la tecla 7 (para hacerlo mas corto)

Estados iniciales-> PORTA=0 , PORTB = 0 (solo la parte alta que es del teclado voy a escribir)

Iniciamos el barrido hacemos PORTA = 0001 (RA0 - Primera fila) PORTB = 0001 (RB4 - primera columna)
Se dispara la interrupcion y obtenes tu tecla.
Aca puede suceder varias cosas segun tu programa y/o lo que suceda primero:

- Si seguis con el barrido del teclado:
  PORTA = 0010  PORTB = 0000 , Se dispara de nuevo la interrupcion. No tengo el mismo valor que antes.
- No seguis con el barrido y se suelta el boton:
  PORTA = 0001 PORTB = 0000, Se dispara de nuevo la interrupcion. Tampoco tengo el mismo valor que antes.
- No seguis con el barrido y reinicias el PORTA:
  PORTA = 0000 PORTB = 0000, Se dispara de nuevo la interrupcion. Tampoco tengo el mismo valor que antes.
- No seguis con el barrido y se presiona el 8,9 o el %
  PORTA = 0001 PORTB = 0101, Se dispara la interrupcion. Tampoco tengo el mismo valor que antes.

Mientras tengas presionado el boton, y NO sigas con el barrido, y NO se presione algun otro boton, no tendrias interrupciones mas que la primera... ( No cuento posibles rebotes)
En resumen:

Siempre vas a tener dos interrupciones cuando trabajas con botones e interrupciones por cambio de nivel. Tiene sus ventajas también. Por ejemplo si detectas que hay algo gracias a la interrupcion, entonces no seguis con el barrido. Te detenes.
En la interrupcion esperas dos cosas, si antes se disparo por estar todo en 0 entonces ahora tomas el valor y ese es tu boton.
Si esta todo en cero, entonces quiere decir que te permite tomar nuevos valores

Entonces con esto de tomar el valor de un boton, luego omitir toda interrupcion que signifique cualquier valor menos el de nada presionado, y cuando se detecte nada, recién ahí habilitas para que lea el teclado el nuevo valor. Pero es bastante complicado de implementar cuando el barrido y la toma de decisiones estan separados (uno en la interrupcion y otro en el programa principal)

Parece lindo, pero esto no tiene sentido, y es mejor hacer una interrupcion con un Timer cada 100ms por ejemplo. Cada 100ms haces un barrido (que es rapido de realizarse como ves en el programa), no se necesitarian delays (ya que el timer mismo de 100ms te da el delay). Anotas el boton y actuas en consecuencia, en las proximas entradas solo esperas que se suelte todo, y una ves detectado que se solto todo, empezas a buscar tu proximo boton, es decir se repite todo el proceso. Basicamente solo contas que se presiono el boton cuando se solto y se volvio a presionar otro.

Por supuesto todo esto tenes que acompañarlo con un pequeño codigo que proteja en el caso de que ese primer boton hubiera 2 presionado, dando prioridad a alguno de estos u omitiendo la lectura.

Este ultimo metodo ademas permite muchas mas cosas, permite:
- Definir un tiempo de "anti-rebote". Por ejemplo el de esperar 3 interrupciones hasta considerarlo valido al boton.
- Contar cuanto tiempo se tiene presionado. Por si queres hacer que se "repita" lo escrito, muy parecido al teclado de una PC, util para las felchitas cuando tenes algun valor y necesitas que se incremente "rapido". Supongamos que si esta presionado por mas de 20 interrupciones (2s), empiezo a aumentar de a 10 (y no de a 1 como lo hacia), y definir intervalos distinto de incremento, por ejemplo cada 4 interrupciones ( 0.4s) incrementaria.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: cristhiamjara en 23 de Mayo de 2020, 00:36:03
Citar
pero todas deberian arrojar el mismo resultado mientres presione la misma tecla

A eso voy que es erroneo lo que planteas... Ya que para leer el teclado haces un barrido... Voy a intentar ser mas claro con un ejemplo.

Supongamos que tenes presionado la tecla 7 (para hacerlo mas corto)

Estados iniciales-> PORTA=0 , PORTB = 0 (solo la parte alta que es del teclado voy a escribir)

Iniciamos el barrido hacemos PORTA = 0001 (RA0 - Primera fila) PORTB = 0001 (RB4 - primera columna)
Se dispara la interrupcion y obtenes tu tecla.
Aca puede suceder varias cosas segun tu programa y/o lo que suceda primero:

- Si seguis con el barrido del teclado:
  PORTA = 0010  PORTB = 0000 , Se dispara de nuevo la interrupcion. No tengo el mismo valor que antes.
- No seguis con el barrido y se suelta el boton:
  PORTA = 0001 PORTB = 0000, Se dispara de nuevo la interrupcion. Tampoco tengo el mismo valor que antes.
- No seguis con el barrido y reinicias el PORTA:
  PORTA = 0000 PORTB = 0000, Se dispara de nuevo la interrupcion. Tampoco tengo el mismo valor que antes.
- No seguis con el barrido y se presiona el 8,9 o el %
  PORTA = 0001 PORTB = 0101, Se dispara la interrupcion. Tampoco tengo el mismo valor que antes.

Una pregunta, cuando ocurre una interrupcion, acaso no se detiene todo para atender lo que este dentro de la interrupcion?
osea si ocurre una interrupcion el codigo que hace el barrido se detendra y se ejecutara lo que esta dentro de la interrupcion, una vez terminado(obtengo mi resultado en display) se vuelve con lo del barrido, y si aun tengo la misma tecla presionada(cosa que si, porq el barrido ocurre en micro segundos o milisegundos) vuelve a ejecutar la misma interrupcion y vuelvo a obtener el mismo resultado en display, y puesto que la interrupcion esta por flanco de subida, si mantego presionado el boton , al salir una rutina de interrupcion se reanuda el barrido, y al regresar el 1 a la fila donde estoy presionando vuelve a entrar a la interrupcion porq detecta un cambio logico de 0 a 1, pero debo obtener el mismo resutado, y eso es lo que ocurre en la practica, al compilar el codigo si mantienes la tecla presioanda el display muesta el valor de la tecla presionada pero alterna con un valor inesperado.
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: KILLERJC en 23 de Mayo de 2020, 09:22:42
Citar
osea si ocurre una interrupcion el codigo que hace el barrido se detendra y se ejecutara lo que esta dentro de la interrupcion, una vez terminado(obtengo mi resultado en display) se vuelve con lo del barrido, y si aun tengo la misma tecla presionada(cosa que si, porq el barrido ocurre en micro segundos o milisegundos) vuelve a ejecutar la misma interrupcion y vuelvo a obtener el mismo resultado en display

Depende de tu codigo como te dije....
Ya que el barrido se encuentra en el programa principal, cuando comience y detecte la tecla vas a tener tu primera interrupcion. Ejecuta la interrupcion y sale.
Continua donde dejo el barrido (ya que se habia detenido para atender la interrupcion), al cambiar de fila, por mas que tengas la tecla presionada, en la otra fila no vas a tener NADA es decir RB4 a RB7 va a ser 0, entonces vas a tener tu segunda interrupcion! Y si tu programa considera que cada vez que tiene una interrupcion hay una tecla presionada, entonces ahi tenes un error.

Por eso te digo que vas a tener 2 interrupciones si o si.
La unica forma simple de solucionarlo es detectar si hubo 2 o mas interrupciones con RB4 a RB7 en 0, para saber cuando se solto la tecla, e ignorar (simplemente entrar y salir) cuando sea todo 0. Dicho de otra forma: Detectar si es todo 0, si lo es omitirlo y contar estas omisiones, pasada 2 omisiones quiere decir que se solto la tecla. Si no es 0, es una tecla presionada y ademas necesitas resetear el contador de omisiones.

PD: Te estoy dando soluciones respecto a la forma que queres hacerlo, pero debido al tiempo que toma hacer el barrido de un teclado, no tiene ningun sentido complicarse con esta interrupcion. Por eso hice ese codigo arriba. Lo unico que le faltaria es crear el numero o tecla desde los datos del PORTA y PORTB que quedo en BOTONES.

PD2: De paso te explico mi código por si tenes que arreglarlo:

Asumo RA5 como salida, sino se puede (ya que algunos son solo entradas) entonces cambiar la condicion BTFSS PORTA,5 por STATUS,Z
El código inicia con PORTA = 0 y C = 1
Rota a la izquierda y queda PORTA = 0001
Se fija si PORTB es distinto de 0 (si hay algo presionado)
-- Si lo hay, entonces guardo los valores de PORTA y PORTB, hago PORTA = 0 y salgo.
Si no lo hay, entonces repito desde que se rota a la izquierda

Necesito saber cuando llego al final, por eso uso PORTA,5 como salida para cuando este en 1 saber que llego (ya que no lo usas).
Si es una entrada únicamente, entonces vas a tener que: hacerle una AND dejando los 4 primeros bits (0xF), y revisar si es 1 el STATUS, Z
Título: Re:se modifica el valor de mi registro al retornar de una interrupción
Publicado por: Leon Pic en 23 de Mayo de 2020, 12:57:16
Como veo que ya hay más errores, lo mejor sería arreglar este programa; y viendo que arreglarlo se me hace muy difícil, vamos a re escribirlo:

Código: ASM
  1. ; **** Encabezado ****
  2.     list p=16F84A
  3.     #include P16F84A.inc
  4.     __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
  5.     ;**** Definicion de variables ****
  6. ;
  7. CBLOCK    ; En las subrutinas no se debe fijar la dirección
  8.                    ; de la RAM de usuario. Se toma a continuación de
  9.                    ; la última asignada.
  10. NTecla              ; Seleccionamos posición en la memoria RAM (GPR) para guardar
  11. W_Temp     ; Registro para guardar temporalmente W.-
  12. STATUS_Temp    ;Registro para guardar temporalmete STATUS
  13. valor_tecla    ;Valor de la tecla guardada.
  14. bandera   ;Bandera para saber si se obtuvo un nuevo valor del teclado.
  15. BCD_Centenas    
  16. BCD_Decenas        
  17. BCD_Unidades  
  18.    ENDC
  19.      
  20.      
  21.     ;**** Inicio del Micro ****
  22.     Reset          
  23.             org     0x00            ; Aquí comienza el micro.-
  24.             goto    Inicio          ; Salto a inicio de mi programa.-
  25.     ;**** Vector de Interrupcion ****
  26.             org     0x04            ; Atiendo Interrupcion.-
  27.             goto    Inicio_ISR
  28.     ;**** Programa principal ****
  29.     ;**** Configuracion de puertos ****
  30.     Inicio
  31.            bsf     status,5
  32.             movlw   b'00000'   ;porta como salidas
  33.             movwf   trisa
  34.             movlw   b'11110000'
  35.             movwf   trisb
  36.             movlw   b'11010111' ;rbpullup no, intedge=subida, t0cs=f/4 ,t0ie:bajada, psa->tmr0 ratio 1:256
  37.             movwf   option_reg
  38.             bcf     status,5;de vuelta al banco0
  39.             bcf     INTCON,RBIF             ; Borramos bandera de Interrupcion.-
  40.             movlw   b'10001000'     ; Habilitamos GIE y RBIE (interrupción RB4 a RB7)
  41.             movwf   INTCON
  42.             clrf    NTecla
  43.             bcf     bandera,0
  44.             goto  Bucle
  45. ;
  46. BIN_a_BCD
  47.    clrf   BCD_Centenas      ; Carga los registros con el resultado inicial.
  48.    clrf   BCD_Decenas      ; En principio las centenas y decenas a cero.
  49.    movwf   BCD_Unidades      ; Se carga el número binario a convertir.
  50. BCD_Resta10
  51.    movlw   .10         ; A las unidades se les va restando 10 en cada
  52.    subwf   BCD_Unidades,W      ; pasada. (W)=(BCD_Unidades) -10.
  53.    btfss   STATUS,C      ; ¿C = 1?, ¿(W) positivo?, ¿(BCD_Unidades)>=10?
  54.    goto    BIN_BCD_Fin      ; No, es menor de 10. Se acabó.
  55. BCD_IncrementaDecenas
  56.    movwf   BCD_Unidades      ; Recupera lo que queda por restar.
  57.    incf   BCD_Decenas,F      ; Incrementa las decenas y comprueba si ha llegado
  58.    movlw   .10         ; a 10. Lo hace mediante una resta.
  59.    subwf   BCD_Decenas,W      ; (W)=(BCD_Decenas)-10).
  60.    btfss   STATUS,C      ; ¿C = 1?, ¿(W) positivo?, ¿(BCD_Decenas)>=10?
  61.    goto   BCD_Resta10      ; No. Vuelve a dar otra pasada, restándole 10 a
  62. BCD_IncrementaCentenas         ; las unidades.
  63.    clrf   BCD_Decenas      ; Pone a cero las decenas
  64.    incf   BCD_Centenas,F      ; e incrementa las centenas.
  65.    goto   BCD_Resta10      ; Otra pasada: Resta 10 al número a convertir.
  66. BIN_BCD_Fin
  67.    swapf   BCD_Decenas,W      ; En el nibble alto de (W) también las decenas.
  68.    addwf   BCD_Unidades,W      ; En el nibble bajo de (W) las unidades.
  69.    return            ; Vuelve al programa principal.
  70.     ;**** Bucle ****
  71.     Bucle
  72.             sleep                      ;si da problemas, desactivarlo. El pic debe despertar al entrar una interrupción.
  73.             nop                         ;y si desactivamos sleep, no es necesario este nop
  74.             btfss   bandera,0   ;¿Hay nuevo valor a mostrar?
  75.             goto    Bucle          ;No, seguimos esperando
  76.             movfw  valor_tecla
  77.             call     BIN_a_BCD ;Si, convertimos el valor binario a BCD para mostrarlo en un display 7 seg.
  78.             movwf portb           ;Solo va a mostrar los primero 4 bit del BCD, ya que el puerto solo maneja 4 bit.
  79.             bcf     bandera,0    ;Pongo a 0 al bit 0 de bandera, para indicar que ya lo mostramos en el display.
  80.             goto     Bucle
  81.     ;**** Rutina de servicio de Interrupcion ****
  82.      
  83.     ;---> Aqui haremos copia de respaldo para mostrar como se hace aunque no es
  84.     ; necesario ya que el micro no hace otra tarea mientras tanto <---
  85.      
  86.     ;  Guardado de registro W y STATUS.-
  87.     Inicio_ISR
  88.             movwf   W_Temp  ; Copiamos W a un registro Temporario.-
  89.             swapf   STATUS, W       ;Invertimos los nibles del registro STATUS.-
  90.             movwf   STATUS_Temp     ; Guardamos STATUS en un registro temporal.-
  91.     ;**** Interrupcion por TMR0 ****
  92.     ISR
  93.             btfss   INTCON,RBIF     ; Consultamos si es por RB4 a RB7.-
  94.             goto    Fin_ISR         ; No, entonces restauramos valores.-
  95.             call    Tecla_Presionada        ; Se detecta que tecla fue presionada
  96.             movfw   NTecla
  97.             movwf   valor_tecla;
  98.             bsf        bandera,0    ;Ponemos a 1 al bit cero de bandera para indicar que tenemos nuevo valor.
  99.     ; Restauramos los valores de W y STATUS.-
  100.     Fin_ISR
  101.             swapf   STATUS_Temp,W   ; Invertimos lo nibles de STATUS_Temp.-
  102.             movwf   STATUS
  103.             swapf   W_Temp, f       ; Invertimos los nibles y lo guardamos en el mismo registro.-
  104.             swapf   W_Temp,W        ; Invertimos los nibles nuevamente y lo guardamos en W.-
  105.             retfie                  ; Salimos de interrupción.-
  106.      
  107.      
  108.     ;**** Rutinas *****
  109.     ; Rastreamos Tecla presionada.-
  110.     Tecla_Presionada
  111.             clrf    NTecla          ; Borra Numero de Tecla y
  112.             incf    NTecla,1        ; prepara NTecla para primer codigo.
  113.             movlw   b'00001110'     ; Saca 0 a la primera fila
  114.             movwf   PORTA           ; de la Puerta A
  115.             nop                     ; Para estabilizacion de señal.  
  116.     Test_Columnas        
  117.             btfss   PORTB,4         ; Primera columna = 0        
  118.             goto    Suelta_tecla    ; Sale si se ha pulsado tecla.
  119.             incf    NTecla,1        ; Si no tecla pulsada, incrementa nº tecla.
  120.             btfss   PORTB,5         ; Segunda columna = 0
  121.             goto    Suelta_tecla    ; Sale si se ha pulsado tecla.
  122.             incf    NTecla,1        ; Si no tecla pulsada, incrementa nº tecla.
  123.             btfss   PORTB,6         ; Tercera columna = 0
  124.             goto    Suelta_tecla    ; Sale si se ha pulsado tecla.
  125.             incf    NTecla,1        ; Si no tecla pulsada, incrementa nº tecla.
  126.  ;  
  127.     ;       btfss   PORTB,7         ; Cuarta columna = 0
  128.     ;       goto    Suelta_tecla    ; Sale si se ha pulsado tecla.
  129.     ;       incf    NTecla,1        ; Si no tecla pulsada,incrementa nº Tecla.
  130.                                
  131.     Ultima_tecla    
  132.             btfss   PORTA,3                 ; Ya se revisaron todas las filas?
  133.             goto    Null_tecla              ; Si, Falsa alarma, no se ha presionado ninguna.-
  134.             bsf     STATUS,C        ; No, seguimos con la siguiente.Pone a 1 Bit C    
  135.             rlf     PORTA,1         ; asi la Fila 1 pasa a 1 con la rotación a izqda.
  136.             goto    Test_Columnas                                                
  137.                                                                
  138.     Null_tecla        
  139.             clrf    NTecla          ; Coloca variable Tecla a 0 (Ninguna)
  140.             bcf     INTCON,RBIF             ; Borramos bandera de Interrupcion.-
  141.             clrf    PORTB                   ; Dejamos Puerto para recibir otra tecla.-
  142.             return                  ; y regresa.        
  143.                                                                
  144.     Suelta_tecla    
  145.     ; Ahora se espera a que la tecla sea soltada para evitar rebotes
  146.     ; y reactivaciones de tecla
  147.     Espera1        
  148.             btfss   PORTB,4         ; Si no se suelta la tecla FILA 1
  149.             goto    Espera1         ; vuelve a esperar.
  150.     Espera2        
  151.             btfss   PORTB,5         ; Si no se suelta la tecla FILA 2
  152.             goto    Espera2         ; vuelve a esperar.
  153.     Espera3
  154.             btfss   PORTB,6         ; Si no se suelta la tecla FILA 3
  155.             goto    Espera3         ; vuelve a esperar.              
  156.     Espera4
  157.             btfss   PORTB,7         ; Si no se suelta la tecla FILA 4
  158.             goto    Espera4         ; vuelve a esperar.          
  159.      
  160.             bcf     INTCON,RBIF             ; Borramos bandera de Interrupcion.-  
  161.             clrf    PORTB                   ; Dejamos Puerto para recibir otra tecla.-              
  162.             return                          ; vuelve al programa principal que hizo la llamada.
  163.     ;..........................................
  164.             end

La rutina del teclado, lo saqué de aquí http://www.todopic.com.ar/foros/index.php?topic=24720.msg201410#msg201410
Y la rutina de la conversión de binario a BCD lo saqué de aquí https://www.todopic.com.ar/foros/index.php?topic=43422.msg360034#msg360034

Nota. No lo he probado. Pero debería funcionar.