; **** Encabezado ****
list p=16F84A
#include P16F84A.inc
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;**** Definicion de variables ****
;
CBLOCK ; En las subrutinas no se debe fijar la dirección
; de la RAM de usuario. Se toma a continuación de
; la última asignada.
NTecla ; Seleccionamos posición en la memoria RAM (GPR) para guardar
W_Temp ; Registro para guardar temporalmente W.-
STATUS_Temp ;Registro para guardar temporalmete STATUS
valor_tecla ;Valor de la tecla guardada.
bandera ;Bandera para saber si se obtuvo un nuevo valor del teclado.
BCD_Centenas
BCD_Decenas
BCD_Unidades
ENDC
;**** Inicio del Micro ****
Reset
org 0x00 ; Aquí comienza el micro.-
goto Inicio ; Salto a inicio de mi programa.-
;**** Vector de Interrupcion ****
org 0x04 ; Atiendo Interrupcion.-
goto Inicio_ISR
;**** Programa principal ****
;**** Configuracion de puertos ****
Inicio
bsf status,5
movlw b'00000' ;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
bcf INTCON,RBIF ; Borramos bandera de Interrupcion.-
movlw b'10001000' ; Habilitamos GIE y RBIE (interrupción RB4 a RB7)
movwf INTCON
clrf NTecla
bcf bandera,0
goto Bucle
;
BIN_a_BCD
clrf BCD_Centenas ; Carga los registros con el resultado inicial.
clrf BCD_Decenas ; En principio las centenas y decenas a cero.
movwf BCD_Unidades ; Se carga el número binario a convertir.
BCD_Resta10
movlw .10 ; A las unidades se les va restando 10 en cada
subwf BCD_Unidades,W ; pasada. (W)=(BCD_Unidades) -10.
btfss STATUS,C ; ¿C = 1?, ¿(W) positivo?, ¿(BCD_Unidades)>=10?
goto BIN_BCD_Fin ; No, es menor de 10. Se acabó.
BCD_IncrementaDecenas
movwf BCD_Unidades ; Recupera lo que queda por restar.
incf BCD_Decenas,F ; Incrementa las decenas y comprueba si ha llegado
movlw .10 ; a 10. Lo hace mediante una resta.
subwf BCD_Decenas,W ; (W)=(BCD_Decenas)-10).
btfss STATUS,C ; ¿C = 1?, ¿(W) positivo?, ¿(BCD_Decenas)>=10?
goto BCD_Resta10 ; No. Vuelve a dar otra pasada, restándole 10 a
BCD_IncrementaCentenas ; las unidades.
clrf BCD_Decenas ; Pone a cero las decenas
incf BCD_Centenas,F ; e incrementa las centenas.
goto BCD_Resta10 ; Otra pasada: Resta 10 al número a convertir.
BIN_BCD_Fin
swapf BCD_Decenas,W ; En el nibble alto de (W) también las decenas.
addwf BCD_Unidades,W ; En el nibble bajo de (W) las unidades.
return ; Vuelve al programa principal.
;**** Bucle ****
Bucle
sleep ;si da problemas, desactivarlo. El pic debe despertar al entrar una interrupción.
nop ;y si desactivamos sleep, no es necesario este nop
btfss bandera,0 ;¿Hay nuevo valor a mostrar?
goto Bucle ;No, seguimos esperando
movfw valor_tecla
call BIN_a_BCD ;Si, convertimos el valor binario a BCD para mostrarlo en un display 7 seg.
movwf portb ;Solo va a mostrar los primero 4 bit del BCD, ya que el puerto solo maneja 4 bit.
bcf bandera,0 ;Pongo a 0 al bit 0 de bandera, para indicar que ya lo mostramos en el display.
goto Bucle
;**** Rutina de servicio de Interrupcion ****
;---> Aqui haremos copia de respaldo para mostrar como se hace aunque no es
; necesario ya que el micro no hace otra tarea mientras tanto <---
; Guardado de registro W y STATUS.-
Inicio_ISR
movwf W_Temp ; Copiamos W a un registro Temporario.-
swapf STATUS, W ;Invertimos los nibles del registro STATUS.-
movwf STATUS_Temp ; Guardamos STATUS en un registro temporal.-
;**** Interrupcion por TMR0 ****
ISR
btfss INTCON,RBIF ; Consultamos si es por RB4 a RB7.-
goto Fin_ISR ; No, entonces restauramos valores.-
call Tecla_Presionada ; Se detecta que tecla fue presionada
movfw NTecla
movwf valor_tecla;
bsf bandera,0 ;Ponemos a 1 al bit cero de bandera para indicar que tenemos nuevo valor.
; Restauramos los valores de W y STATUS.-
Fin_ISR
swapf STATUS_Temp,W ; Invertimos lo nibles de STATUS_Temp.-
movwf STATUS
swapf W_Temp, f ; Invertimos los nibles y lo guardamos en el mismo registro.-
swapf W_Temp,W ; Invertimos los nibles nuevamente y lo guardamos en W.-
retfie ; Salimos de interrupción.-
;**** Rutinas *****
; Rastreamos Tecla presionada.-
Tecla_Presionada
clrf NTecla ; Borra Numero de Tecla y
incf NTecla,1 ; prepara NTecla para primer codigo.
movlw b'00001110' ; Saca 0 a la primera fila
movwf PORTA ; de la Puerta A
nop ; Para estabilizacion de señal.
Test_Columnas
btfss PORTB,4 ; Primera columna = 0
goto Suelta_tecla ; Sale si se ha pulsado tecla.
incf NTecla,1 ; Si no tecla pulsada, incrementa nº tecla.
btfss PORTB,5 ; Segunda columna = 0
goto Suelta_tecla ; Sale si se ha pulsado tecla.
incf NTecla,1 ; Si no tecla pulsada, incrementa nº tecla.
btfss PORTB,6 ; Tercera columna = 0
goto Suelta_tecla ; Sale si se ha pulsado tecla.
incf NTecla,1 ; Si no tecla pulsada, incrementa nº tecla.
;
; btfss PORTB,7 ; Cuarta columna = 0
; goto Suelta_tecla ; Sale si se ha pulsado tecla.
; incf NTecla,1 ; Si no tecla pulsada,incrementa nº Tecla.
Ultima_tecla
btfss PORTA,3 ; Ya se revisaron todas las filas?
goto Null_tecla ; Si, Falsa alarma, no se ha presionado ninguna.-
bsf STATUS,C ; No, seguimos con la siguiente.Pone a 1 Bit C
rlf PORTA,1 ; asi la Fila 1 pasa a 1 con la rotación a izqda.
goto Test_Columnas
Null_tecla
clrf NTecla ; Coloca variable Tecla a 0 (Ninguna)
bcf INTCON,RBIF ; Borramos bandera de Interrupcion.-
clrf PORTB ; Dejamos Puerto para recibir otra tecla.-
return ; y regresa.
Suelta_tecla
; Ahora se espera a que la tecla sea soltada para evitar rebotes
; y reactivaciones de tecla
Espera1
btfss PORTB,4 ; Si no se suelta la tecla FILA 1
goto Espera1 ; vuelve a esperar.
Espera2
btfss PORTB,5 ; Si no se suelta la tecla FILA 2
goto Espera2 ; vuelve a esperar.
Espera3
btfss PORTB,6 ; Si no se suelta la tecla FILA 3
goto Espera3 ; vuelve a esperar.
Espera4
btfss PORTB,7 ; Si no se suelta la tecla FILA 4
goto Espera4 ; vuelve a esperar.
bcf INTCON,RBIF ; Borramos bandera de Interrupcion.-
clrf PORTB ; Dejamos Puerto para recibir otra tecla.-
return ; vuelve al programa principal que hizo la llamada.
;..........................................
end