Reloj de ajedrez digital con LCD y PIC 16F84
Aquí les traigo este diseño para los amantes del ajedrez, este reloj digital posee una tecla que permitirá programar el tiempo de juego desde 5 hasta 55 minutos, con incrementos de 5 ( en RA4); para la gestión y manejo por los jugadores en el tiempo de juego se utiliza un switch de dos pasos (RA0, una entrada a 1 logico y la otra a 0 logico). La visualización del tiempo se realiza a través de en LCD alfanumérico de 16x2 esto quiere decir dos líneas de 16 caracteres (utilice este porque era el que tenia), las lineas de datos del lcd son al puerto B, las de control son como sigue RS->RA1, RW->RA2 y E->RA3. Les aseguro que funciona. Como ven el diseño del hardware aprovecha todos los puertos del microcontrolador.
La programación del PIC la hice en MPLAB 7.5, como verán el algoritmo no incluye interrupciones, el mecanismo es solo por encuesta, y la simulación del circuito en Proteus 7 sp2.
Sin más los dejo con el código en ASM, saludos desde Cuba
Rolando Mondeja Rodríguez
rmondeja@uclv.edu.cu <mailto:rmondeja@uclv.edu.cu>
;**********************************************************************
; This file is a basic code template for assembly code to a chess *
; clock using pic 16f84 *
; *
;**********************************************************************
; Author: rmondeja *
;***********************************************************************
list p=16F84A ; list directive to define processor
#include <p16F84A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC
;***** VARIABLE DEFINITIONS
Del1 EQU 0x10 ;para subrutina de demora
Del2 EQU 0x11 ;para subrutina de demora
Del3 EQU 0x12 ;para subrutina de demora
seg00 EQU 0x13
seg01 EQU 0x14;la direccion 15 es la de los dos puntos
dosp0 EQU 0x15
min00 EQU 0x16
min01 EQU 0x17;ahora vienen 6 space
seg10 EQU 0x1E
seg11 EQU 0x1F;la 26 es de los :
dosp1 EQU 0x20
min10 EQU 0x21
min11 EQU 0x22
control EQU 0x23
cont0 EQU 0x24;este es para la subrrutina de demora de 1s
cont1 EQU 0x25;este es para la subrrutina de demora de 1s
time0 EQU 0x26
time1 EQU 0x27
E EQU 3
RW EQU 2
RS EQU 1
Funtion_Set EQU H'38'
DisplayON_OFF EQU B'00001110'
DisplayClear EQU H'01'
EntryModeSet EQU B'00000100'
F EQU 1
W EQU 0
S EQU 4
;**********************************************************************
ORG 0x000
goto main
ORG 0x004
retfie
;**********************************
; usuario0;
;**********************************
user0 decfsz cont0,F;si salta paso un segundo
goto fin0
movlw D'196';paso 1 seg
movwf cont0;contador por soft a 250
movlw H'00'
xorwf seg00,W
btfss STATUS,Z;si salta es que seg00 es 0
goto dec
rec movlw H'09'
movwf seg00
;ahora si las decenas de segundos esta en 0 se cambia a 6 y si no se decrementa
movlw H'00'
xorwf seg01,W
btfss STATUS,Z;si salta es que seg00 es 0
goto seg2dec
movlw H'06'
movwf seg01
;ahora se las unidades de los minutos estan en 0 las cambia a 9, y si no las decrementa
movlw H'00'
xorwf min00,W
btfss STATUS,Z;si salta es que seg00 es 0
goto min1dec
movlw H'0A'
movwf min00
;ahora si las decenas de minutos estan en 0 se cambian por 6 y si no se decrementan
movlw H'06'
xorwf min01,W
btfss STATUS,Z;si salta es que seg00 es 0
goto min2dec
movlw H'06'
movwf min01
min2dec decf min01,F
min1dec decf min00,F
seg2dec decf seg01,F
goto bb
dec decf seg00,F
bb call lcdini
call show
fin0 return
;**********************************
; usuario1
;**********************************
user1 decfsz cont1,F;si salta paso un segundo
goto fin1
movlw D'196';paso 1 seg
movwf cont1;contador por soft a 250
movlw H'00'
xorwf seg10,W
btfss STATUS,Z;si salta es que seg00 es 0
goto dec1
movlw H'09'
movwf seg10
;ahora si las decenas de segundos esta en 0 se cambia a 6 y si no se decrementa
movlw H'00'
xorwf seg11,W
btfss STATUS,Z;si salta es que seg00 es 0
goto seg2dec1
movlw H'06'
movwf seg11
;ahora se las unidades de los minutos estan en 0 las cambia a 9, y si no las decrementa
movlw H'00'
xorwf min10,W
btfss STATUS,Z;si salta es que seg00 es 0
goto min1dec1
movlw H'0A'
movwf min10
;ahora si las decenas de minutos estan en 0 se cambian por 6 y si no se decrementan
movlw H'06'
xorwf min11,W
btfss STATUS,Z;si salta es que seg00 es 0
goto min2dec1
movlw H'06'
movwf min11
min2dec1 decf min11,F
min1dec1 decf min10,F
seg2dec1 decf seg11,F
goto bb1
dec1 decf seg10,F
bb1 call lcdini
call show
fin1 return
;**********************************
; para parar al perder;
;**********************************
stop0
clrw
xorwf min01,W
btfss STATUS,Z;decenas de minutos
goto user0
clrw
xorwf min00,W
btfss STATUS,Z;unidades de minutos
goto user0
clrw
xorwf seg01,W
btfss STATUS,Z;decenas de segundos
goto user0
clrw
xorwf seg00,W
btfss STATUS,Z;decenas de minutos
goto user0
return
;**********************************
; para parar al perder;
;**********************************
stop1
clrw
xorwf min11,W
btfss STATUS,Z;decenas de minutos
goto user1
clrw
xorwf min10,W
btfss STATUS,Z;unidades de minutos
goto user1
clrw
xorwf seg11,W
btfss STATUS,Z;decenas de segundos
goto user1
clrw
xorwf seg10,W
btfss STATUS,Z;decenas de minutos
goto user1
return
;**********************************
; DEMORAS
;**********************************
DEM movlw D'1'
movwf Del1
Loop1
movlw D'1'
movwf Del2
Loop2
decfsz Del2,F
goto Loop2
decfsz Del1,F
goto Loop1
return
DEM2 movlw D'30'
movwf Del1
Loop3
movlw D'10'
movwf Del2
Loop4
decfsz Del2,F
goto Loop4
decfsz Del1,F
goto Loop3
return
DEM3 movlw D'1'
movwf Del1
Loop5
movlw D'1'
movwf Del2
Loop6
movlw D'1'
movwf Del3
Loop7
decfsz Del3,F
goto Loop7
decfsz Del2,F
goto Loop6
decfsz Del1,F
goto Loop5
return
dem4
movlw D'250'
movwf Del1
loop
movlw D'250'
movwf Del2
looop decfsz Del2,F
goto looop
decfsz Del1,F
goto loop
return
;**********************************
; devuelve el dato a mostrar
;**********************************
DATO_1 ADDWF PCL,1
RETLW '0'
RETLW '1'
RETLW '2'
RETLW '3'
RETLW '4'
RETLW '5'
RETLW '6'
RETLW '7'
RETLW '8'
RETLW '9'
RETLW ':'
RETLW ' '
;**********************************
; visualizacion en lcd
;**********************************
show bsf PORTA,RS;DATO NO INSTRUCCION
; a partir de ahora lo que hace es mostrar lo qu esta en los registros
movlw H'22'
movwf FSR
dbucle movf INDF,W
call DATO_1
movwf PORTB
bsf PORTA,E;habilita el LCD
call DEM2
bcf PORTA,E;deshabilita el LCD
decf FSR
movlw H'12'
xorwf FSR,W
btfss STATUS,Z
goto dbucle
return
;**********************************
; inicializacion de lcd
;**********************************
lcdini clrw;comienza inicializacion de display
movwf PORTA
call DEM2
movlw Funtion_Set
movwf PORTB
bsf PORTA,E
call DEM
bcf PORTA,E
call DEM2
movlw DisplayON_OFF
movwf PORTB
bsf PORTA,E
call DEM
bcf PORTA,E
call DEM2
movlw DisplayClear
movwf PORTB
bsf PORTA,E
call DEM
bcf PORTA,E
call DEM2
movlw EntryModeSet ;modo de dezplazamiento cuando se introcuce un caracter
movwf PORTB
bsf PORTA,E
call DEM
bcf PORTA,E ;termina la inicializacion
return
;**********************************
; reprogramacion
;**********************************
rep
clrf seg00;para inicializar los segundos son 0
clrf seg01
clrf seg10
clrf seg11
clrw
xorwf time0,W;compara con 0
btfsc STATUS,Z
goto rec5
goto ifrec0
rec5 movlw H'05';esto es si las unidades de minutos son 0
movwf time0
movwf min00
movwf min10
movf time1,W;w=time1
movwf min01
movwf min11
goto dis
ifrec0 movlw H'05';si las unidades de minutos son 5 se compara las decenas para condicion de recarga completa
xorwf time1,W
btfsc STATUS,Z;compara time1 con 5
goto rec05
goto recinc
rec05 clrf time1;esto es si las decenas son 5 y las unidades son 5
clrf min01
clrf min11
movlw H'05'
movwf time0
movwf min00
movwf min10
goto dis
recinc incf time1;esto es si las unidades son 5 pero las decenas no
movf time1,W
movwf min01
movwf min11
clrf time0
clrf min00
clrf min10
dis call lcdini
call show
call dem4
return
;**********************************
; programa principal
;**********************************
main
bsf STATUS,RP0; banco 1
clrf TRISB;puerto b como salida de datos a display
movlw B'00000001'
movwf TRISA;puerto a:bit0 como entrada, los demas como salida de configuracon de display
movlw H'03'
movwf OPTION_REG;configura el divf a 16 y se lo asigna al TMR0
bcf STATUS,RP0;banco 0
clrf seg00;para inicializar en 10:00_____10:00
clrf seg01
clrf min01
clrf seg10
clrf seg11
clrf min11
clrf time1;;el timepo es de 10 minutos
movlw H'05'
movwf min00
movwf min10
movwf time0;el timepo es de 10 minutos
movlw H'0A'
movwf dosp0
movwf dosp1;
movlw H'18'
movwf FSR
lazo movlw D'11'
movwf INDF
incf FSR
movlw H'1E'
xorwf FSR,W
btfss STATUS,Z
goto lazo;para inicializar en 10:00_____10:00
call lcdini
call show
movlw H'01'
andwf PORTA,W
movwf control;queda en control lo que esta en el puerto a al inicio
buc btfss PORTA,4
call rep;si se a[rieta la tecla en este punto se recarga
movlw H'01'
andwf PORTA,W
xorwf control,W;compara
btfsc STATUS,Z
goto buc
;si llega aqui es porque se cambio el estado en el RA0, comienza la partida
movlw H'05'
movwf TMR0;carga el tmr0 a 5 para 250us
movlw D'196'
movwf cont0;contador por soft a 250
movwf cont1;contador por soft a 250
bcf INTCON,2
int btfss INTCON,2;espera desborde
goto int
movlw H'05'
movwf TMR0;carga el tmr0 a 5 para 250us*16, despues del desborde
bcf INTCON,2;limpia bandera
btfss PORTA,0
call stop0;va a user0 si el interr esta en 0
btfsc PORTA,0
call stop1
goto int
ciclo goto ciclo
END ; directive 'end of program'