Autor Tema: se modifica el valor de mi registro al retornar de una interrupción  (Leído 718 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado cristhiamjara

  • PIC10
  • *
  • Mensajes: 15
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #15 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.

Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3529
    • Impresiones en 3D
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #16 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?
Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.

Desconectado cristhiamjara

  • PIC10
  • *
  • Mensajes: 15
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #17 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?

como la imágen,
coloco un 0001 en porta y lo hago rotar con rlf
las interrupciones son por rb4-rb7

Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3529
    • Impresiones en 3D
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #18 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.
Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.

Desconectado cristhiamjara

  • PIC10
  • *
  • Mensajes: 15
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #19 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  :-/ :-/

Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3529
    • Impresiones en 3D
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #20 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.
Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.

Desconectado cristhiamjara

  • PIC10
  • *
  • Mensajes: 15
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #21 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.

Desconectado Eduardo2

  • PIC18
  • ****
  • Mensajes: 347
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #22 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.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 7741
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #23 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)

Desconectado cristhiamjara

  • PIC10
  • *
  • Mensajes: 15
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #24 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

Desconectado cristhiamjara

  • PIC10
  • *
  • Mensajes: 15
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #25 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

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 7741
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #26 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.

Desconectado cristhiamjara

  • PIC10
  • *
  • Mensajes: 15
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #27 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.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 7741
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #28 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
« Última modificación: 23 de Mayo de 2020, 09:33:30 por KILLERJC »

Desconectado Leon Pic

  • Colaborador
  • DsPIC30
  • *****
  • Mensajes: 3529
    • Impresiones en 3D
Re:se modifica el valor de mi registro al retornar de una interrupción
« Respuesta #29 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.
« Última modificación: 23 de Mayo de 2020, 13:34:22 por Leon Pic »
Jesús dijo, yo soy el CAMINO, la VERDAD y la VIDA, nadie llega al PADRE si no es por mi.