El documento describe la implementación de un reloj digital usando un microcontrolador PIC y un display LCD. Se explica cómo configurar el timer0 del PIC para generar interrupciones cada segundo y actualizar la hora. También se detalla el código y diagrama de flujo para contar los segundos, minutos y horas, y mostrar la hora actualizada en el LCD. El reloj inicialmente mostrará 00:00:00 y contará el tiempo en formato de 24 horas.
Diseño de un aerogenerador de 400w de eje vertical
Tarjeta integradora de aplicaciones (06)
1. 1
TARJETA INTEGRADORA DE APLICACIONES
IMPLEMENTACIÓN DE UN RELOJ POR MEDIO DEL
TIMER0
(PARTE 1)
M. en C. Ismael Cervantes de Anda
Docente ESCOM IPN
icervantes@saberinternacional.com.mx
En la presente entrega se muestra un empleo práctico de la tarjeta integradora de
aplicaciones cuya clave es ICA-023; en esta oportunidad estaremos ilustrando la
manera de implementar un reloj que nos indique la hora, los minutos y los
segundos, dejando para una segunda entrega el material complementario para
poder ajustar la hora del reloj.
Figura 1 Tarjeta Integradora con el display LCD conectado.
En el presente material desarrollaremos a detalle el código para generar un reloj
que posea una base de tiempo de 1 segundo (aproximadamente). El presente
reloj aun no podrá ser ajustado a la hora exacta, ya que esa parte de programa la
agregaremos como un módulo en la entrega del próximo mes.
Nuestro reloj comenzara indicando el tiempo 00:00:00 (hh:mm:ss), el cual se
incrementara cada vez que transcurra un tiempo de 1 segundo, comenzado con la
actualización de las unidades de los segundos, posteriormente las decimales de
2. 2
los segundos, como paso siguiente las unidades de los minutos, después las
decimales de los minutos, casi para terminar las unidades de las horas y por
último las decimales de las horas.
Las modificaciones de los segundos, minutos y horas se realizaran tomando en
cuenta que el conteo de los segundos y minutos es de naturaleza sexagecimal,
esto es, su conteo va del valor 00 al 59, mientras que el conteo de las horas va del
00 al 23.
Una vez que hemos planteado la forma en que trabajara nuestro reloj (considerar
también que indicara un horario corrido desde las 00 hrs, hasta las 23 hrs.), el
siguiente paso es mostrar el diagrama de flujo a partir del cual se desarrollara el
programa para el microcontrolador PIC. Por otra parte, también será empleado
el display LCD, pero como el funcionamiento y configuración de este fue explicado
anteriormente, en esta oportunidad no será el tema central aunque dentro de la
exposición se muestra la manera en que se realiza el conteo del tiempo, y del
control de los dígitos que conforman la hora del reloj. Recordando nuevamente
que para enviar datos al display LCD, el microcontrolador tiene que enviar la
información bajo código ASCII.
En primer instancia se tienen que dar de alta todos los registros que tomaran parte
dentro del programa que se alojara en el microcontrolador PIC, los registros que
serán empleados para controlar el tiempo en el reloj se especifican a continuación:
continter.- registro encargado de contar el numero de interrupciones.
segundoU.- registro encargado de contar las unidades de segundo.
segundoD.- registro encargado de contar las decimales de segundo.
minutoU.- registro encargado de contar las unidades de minuto.
minutoD.- registro encargado de contar las decimales de minuto.
horaU .- registro encargado de contar las unidades de las horas.
horaD.- registro encargado de contar las decimales de las horas.
varLCD.- registro encargado de cargar el dato que será impreso en el display LCD.
Los demás registros que son de configuración por el momento no se han descrito,
pero también deben darse de alta.
3. 3
El puerto del microcontrolador que será empleado para controlar al display LCD es
el puerto D, por lo tanto este tiene que ser configurado como salida, por medio del
registro “trisd” colocándole el valor de 00H.
Como paso siguiente se tiene que inicializar al display LCD, por medio de las
rutinas descritas en las notas publicadas con anterioridad, y aunque aquí no las
vamos a explicar con detalle si se muestra el correspondiente código en el listado
de instrucciones que componen al programa que controla el reloj. Cuando ha
sido inicializado el display LCD, el primer mensaje que se le enviara es el de la
palabra “Reloj” que será desplegado sobre el renglón superior, inmediatamente
como paso siguiente se envían los siguientes caracteres “00:00:00” que se
ubicarán sobre el renglón inferior.
El mensaje que fue enviado al display marca el inicio del conteo del tiempo por
parte del reloj, por lo que ahora tiene que inicializarse el temporizador principal,
para que basado en la base de tiempo de 1 segundo se contabilice los segundos
en primera instancia.
La base de tiempo se encuentra implementada por medio de la herramienta
interna que poseen los microcontroladores PIC que tiene por nombre “timer”. En
esta oportunidad estaremos habilitando el timer de 8 bits, el cual se configura de la
siguiente manera.
El registro esencial que tiene que ser intervenido para configurar al timer de 8 bits
(también conocido como timer0) en el microcontrolador PIC, es el identificado
como “OPTION REG” (opsion) y en el se configuran los bits que se describen a
continuación:
El bit 5 del registro OPTION REG se coloca en estado lógico “0” ó “1”, de acuerdo
de donde se quiera tomar la fuente que da origen al incremento del conteo que se
realiza en el registro contador del timer, tomando en cuenta que la manipulación
del conteo se puede dar a través del pulso que entregue un circuito oscilador
externo, conectado a la terminal del microcontrolador identificada como
RA4/T0CKI, o el conteo también se puede dar empleando el circuito de reloj
interno que posee el microcontrolador. El bit 5 del registro OPTION REG se
4. 4
identifica como T0CS (Bit selector del origen del reloj del TMR0), a continuación se
expresan las posibilidades de configuración del bit 5:
1 = Transición en el pin RA4/T0CKI.- Esta configuración se emplea para
implementar un contador externo de eventos.
0 = Ciclo de reloj Interno (CLKOUT).- Esta configuración se emplea para
implementar un temporizador.
A través del bit 3 del registro OPTION REG se configura el destino del prescaler,
que tiene como función la de establecer cuantos ciclos de instrucción deben de
ejecutarse para que se tenga un incremento de una unidad en el registro contador
del timer. El bit 3 se identifica como PSA (Bit de asignación del Prescaler), el
cual se coloca en estado lógico “0” ó “1”, dependiendo de las siguientes
posibilidades:
1 = El Prescaler es asignado al WDT.- Esta configuración se emplea para activar
al watch dog.
0 = El Prescaler es asignado al módulo Timer0.- Esta configuración se emplea
para activar al registro TMR0, que
es el registro contador del timer.
Los bits 2, 1 y 0 del registro OPTION REG se identifican como PS2, PS1 y PS0
(Bits selectores del rango Prescaler) respectivamente, tienen la tarea de fijar el
número de ciclos de instrucción que se deben ejecutar para que se incremente en
una unidad el valor del registro contador del timer, para ello en la tabla 60, se
muestran las combinaciones binarias que pueden adquirir los bits PS2, PS1 y PS0
generando las diferentes posibilidades de configuración de las cuales se tiene que
seleccionar la mas adecuada en función del valor de la temporización que sea
necesario habilitar.
Tabla 1 Configuración del preescaler del Timer0.
Combinación binaria
PS2, PS1, PS0
Rango
TMR0
Rango
WDT
000 1 : 2 1 : 1
001 1 : 4 1 : 2
010 1 : 8 1 : 4
011 1 : 16 1 : 8
100 1 : 32 1 : 16
101 1 : 64 1 : 32
110 1 : 128 1 : 64
111 1 : 256 1 : 128
5. 5
Los bits restantes del registro OPTION REG que no han sido descritos se deben
de colocar en estado lógico “0” para que el timer0 sea completamente configurado,
por otra parte, el detalle de este registro se muestra de manera completa en la
imagen de la figura 2.
Figura 2 Detalle del registro OPTION_REG.
Pasando a otra parte de la configuración del timer0, se mencionará que tiene que
hacerse uso del manejo de las interrupciones, cada vez que el registro “TMR0”
(registro contador del timer0) sufre un desbordamiento de sus datos (cuando pasa
del valor FFH al 00H), este desbordamiento es causado por la ejecución de las
instrucciones en el microcontrolador, que de acuerdo al preescaler seleccionado
se requerirá de un cierto número de ciclos de instrucción para que se vaya
incrementando de unidad en unidad el valor del registro TMR0. Para que sea
entendible la presente explicación, emplearemos un ejemplo en donde el valor del
preescaler que se ha seleccionado es de 64, que equivalente a colocar los datos
binarios “1”, “0” y “1” respectivamente en los bits PS2, PS1 y PS0 del registro
OPTION REG.
Cada vez que se desborda el registro TMR0 se tiene que producir una interrupción
para “avisar” que se ha completado un ciclo de tiempo bien establecido, para lo
cual en primera instancia se realizan las siguientes operaciones:
Ciclo de instrucción1 =
4
dorFrecOscila
=
4
4MHz
= 1 MHz
Tiempo del ciclo de instrucción =
trucciónCiclodeins
1
=
MHz1
1
= 1 μseg
Para calcular el tiempo en el que se incrementa en una unidad el valor del registro
TMR0 se hace lo siguiente:
(Prescaler)*(Tiempo del ciclo de instrucción) = (64)*(1 μseg) = 64 μseg
Por último, para calcular el intervalo de tiempo que se consume (también llamado
Ciclo de tiempo), para generar una interrupción se efectúa la siguiente operación:
1
Considerando un circuito de reloj oscilador de 4MHz.
6. 6
Ciclo de tiempo = (64 μseg)*(256 conteos en el registro TMR0)
Ciclo de tiempo = 16.38 mseg
Esto quiere decir que cada 16.38 mseg se produce una interrupción, por lo que
para establecer un tiempo base de 1 segundo tenemos que determinar el número
de interrupciones que se requieren a través de la siguiente operación:
Número de Interrupciones =
mseg
segundo
38.16
1
= 61.035 interrupciones
De manera práctica para el desarrollo de la presente aplicación, se tienen que
contabilizar 61 interrupciones, lo cual se realiza por medio del registro identificado
como “continte”. El timer se encuentra operando de manera totalmente
independiente a la ejecución de las instrucciones del programa, lo cual significa
que tan solo se tiene que estar preguntando por el valor que adquiera el registro
“continte” y cuando este llegue a 6110, quiere decir que se ha consumido 1
segundo, por lo tanto, se tiene que incrementar en una unidad al número
correspondiente de las unidades de segundo. Conviene hacerlo de esta
manera, ya que de forma inmediata se puede enviar el dato al display LCD.
En principio los registro identificados como segundoU, segundoD, minutoU,
minutoD, horaU y horaD son cargados de manera inicial con el dato 30H, que
equivale en código ASCII al valor de 0 (cero), para que este valor pueda ser
desplegado directamente por el display LCD.
Cuando se incrementa el valor de las unidades de los segundos (segundoU),
antes de enviar el dato al display LCD, se tiene que preguntar si el incremento ha
superado el valor de 39H (valor 9 en código ASCII). Si es así, entonces se tiene
que alojar nuevamente el valor de 30H, en el registro segundoU incrementando de
manera inmediata en una unidad al registro que contiene el valor de las decenas
de segundo (segundoD). Cuando se incrementa el valor del registro segundoD,
de nueva cuenta se tiene que preguntar si en este registro se ha superado el valor
de 35H (recordando que el conteo de los segundo va del número 00 al 59).
Cuando el conteo en el registro segundoU no ha superado el valor de 39H, se
envía este dato al display LCD, de la misma forma que el conteo llevado por el
registro segundoD, pero este cuando no ha superado el valor de 35H.
7. 7
Figura 3 Diagrama de flujo completo del programa del reloj.
El conteo llevado a cabo por los correspondientes registros, donde se aloja el valor
de las unidades de minuto “minutoU”, y decena de minuto “minutoD”, también se
8. 8
pregunta sí el dato del conteo no ha superado el valor de 39H en el registro
minutoU y 35H en el registro minutoD (de igual manera el conteo de minutos va del
valor 00 al 59). Se debe de tomar en cuenta que para incrementar en una
unidad el valor de los minutos, se debe de cumplir un conteo total de 60 segundos
(del 00 al 59). Si no han sido superaros los valores de los registros minutoU y
minutoD, se envían los datos al display LCD. Para una mejor referencia observe
el diagrama de flujo que se ilustra en la figura 3.
En el caso del conteo de las horas, se considera que estas van del número 00 a
23, por lo que cuando los minutos llegan al valor 59, se tiene que incrementar en
una unidad al registro que lleva el conteo de las unidades de las horas (registro
identificado como “horaU”). Aquí lo importante es tomar en cuenta que cuando el
dato en el registro horaU llega a 34 H (valor 4 en código ASCII), puede significar
una de 3 posibilidades: 1ª que se trate de la hora 04 ó 2ª que se trate de la hora 14
ó 3ª que se trate de la hora 24. En las primeras 2 posibilidades no tiene mayor
inconveniente que aceptar el incremento de las unidades de hora, enviando el
correspondiente valor al display LCD, pero si se trata de la 3ª posibilidad significa
que tanto en el registro horaU (con el valor de 34H) y en el registro horaD (con el
valor de 32H) se tiene el valor del conteo total de las 24 horas que corresponden a
un día completo, por lo que se tiene que reestablecer al reloj nuevamente con el
valor 00:00:00 para que vuelva a comenzar con el conteo del tiempo de un nuevo
día.
Para ir actualizando el dato ya sea de las unidades o decenas de los segundos o
los minutos o las horas, se debe de considerar que una vez que se envía un dato
para ser desplegado en el display LCD, estos se van imprimiendo de izquierda a
derecha, quedando el cursor esperando un nuevo carácter para ser impreso
inmediatamente después del último que fue enviado, por lo tanto, sí se quiere
refrescar por ejemplo el valor de las unidades de segundo (cuando ha pasado
precisamente 1 segundo), se tiene que movilizar al cursor 1 posición hacia la
izquierda, para que se sobre imprima el nuevo valor de las unidades de segundo.
Lo mismo sucede con las decenas de segundo, pero para imprimir esta cifra se
9. 9
tiene que desplazar al cursor 2 posiciones hacia la izquierda, reimprimiendo en
primer lugar a las decenas de segundo y después a las unidades de segundo.
De igual forma con las decenas de minuto y unidades de minuto, pero en este
caso se tiene que movilizar al cursor 5 posiciones a la izquierda, para las decenas
y 4 posiciones a la izquierda para las unidades, considerando que posterior a los
minutos de imprime un “:” para separarlos de las horas.
Para actualizar el valor de las horas, se tiene que mover el cursor 8 posiciones a la
izquierda para actualizar el valor de las decenas de hora, y 7 posiciones para
actualizar el valor de unidades de hora, también se tiene que imprimir un “:” para
separar a las horas de los minutos.
Con respecto del código de la interrupción que genera el timer0, cuando el registro
“TMR0” se desborda en el momento que pasa del valor FFH al 00H; en ella se
coloca únicamente como actividad principal a la correspondiente instrucción que
realiza el incremento en una unidad del valor del registro que lleva sobre si el
conteo del número de interrupciones, y que se identifica como “continte”.
Figura 4 Diagrama esquemático de la tarjeta integradora de aplicaciones (ICA-023).
10. 10
Cabe hacer mención de que la base de tiempo calculada para el control de reloj,
es muy cercana a 1 segundo, pero en la realidad se va a tener un ligero desfase
del conteo del tiempo, pero para diversas aplicaciones con esta rutina se tienen
muy buenas prestaciones.
A manera de recordatorio en la imagen de la figura 4 se ha colocado el diagrama
esquemático de la Tarjeta Integradora de Aplicaciones (cuya clave es ICA-023),
para que se tenga una mejor regencia una vez que se comience a analizar el
código del programa, mismo que se coloca a continuación.
;==========================================
; Reloj
; Ing. Ismael Cervantes de Anda
; 08 de febrero de 2008
; PIC: 16F874
;==========================================
LIST P=PIC16F874
;==========================================
; Declaración de Registros
;==========================================
w equ 0x00
tmr0 equ 0x01
status equ 0x03
portd equ 0x08
trisd equ 0x88
intcon equ 0x0b
pir1 equ 0x0c
opsion equ 0x81
continter equ 0x20
segundoU equ 0x21
segundoD equ 0x22
minutoU equ 0x23
minutoD equ 0x24
horaU equ 0x25
horaD equ 0x26
varLCD equ 0x27
ret1 equ 0x28
ret2 equ 0x29
ret3 equ 0x2a
var1 equ 0x2b
var2 equ 0x2c
var3 equ 0x2d
;==========================================
; Declaración de Bits
;==========================================
c equ 0
ps0 equ 0
ps1 equ 1
ps2 equ 2
z equ 2
toif equ 2
psa equ 3
toie equ 5
tocs equ 5
rp0 equ 5
rp1 equ 6
peie equ 6
gie equ 7
;==========================================
; Declaración de Letras y Números
;==========================================
_espaci equ 0x20
_0 equ 0x30
_1 equ 0x31
_2 equ 0x32
_3 equ 0x33
_4 equ 0x34
_5 equ 0x35
_6 equ 0x36
_7 equ 0x37
_8 equ 0x38
_9 equ 0x39
_R equ 0x52
_e equ 0x65
_j equ 0x6a
_l equ 0x6c
_o equ 0x6f
_dospuntos equ 0x3a
;==========================================
; Vector del reset
;==========================================
reset
org 0
goto IniProgLCD
org 4
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
btfsc intcon,toif
goto intertimer
retfie
;==========================================
; Interrupción por uso del TIMER de 8 bits
;==========================================
intertimer
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bcf intcon,gie ;desactivación de
bcf intcon,toie ; interrupciones
incf continter,1
bcf intcon,toif ;limpia la bandera
bsf intcon,toie ;activa las interrupciones
bsf intcon,gie
clrf tmr0 ;limpia el registro TMR0
retfie
;==========================================
; Comienzo del programa principal
;==========================================
IniProgLCD
bsf status,rp0 ;cambiar al banco 1
bcf status,rp1
movlw 0x00 ;configurar los pines del puerto
movw f trisd ;D como salida
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
11. 11
clrf varLCD
clrf continter
movlw _0
movw f segundoU
movw f segundoD
movw f minutoU
movw f minutoD
movw f horaU
movw f horaD
;---------------------------------------------------------------------------
; Rutina que inicializa al LCD
;---------------------------------------------------------------------------
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
movlw 0x00
movw f portd ;limpia las líneas de salida
movlw d'200' ;temporizacion de 200 ms
movw f ret1 ;para reestablecer al LCD
call Retardos
movlw d'48' ;fija operación de 8 bits en
movw f portd ;el LCD
bsf portd,3 ;genera un pulso de
call temp10micros ;habilitación durante
bcf portd,3 ;10 microsegundos
movlw d'10' ;pausa de 100 ms
movw f ret1
call Retardos
bsf portd,3 ;genera un pulso de
call temp10micros ;habilitación durante
bcf portd,3 ;10 microsegundos
bsf portd,3 ;genera un pulso de
call temp10micros ;habilitación durante
bcf portd,3 ;10 microsegundos
movlw d'32' ;fija operación de 4 bits en
movw f portd ;el LCD
bsf portd,3 ;genera un pulso de
call temp10micros ;habilitación durante
bcf portd,3 ;10 microsegundos
bsf portd,3 ;genera un pulso de
call temp10micros ;habilitación durante
bcf portd,3 ;10 microsegundos
movlw d'128' ;fija operación de 2 líneas
movw f portd ;en el LCD
bsf portd,3 ;genera un pulso de
call temp10micros ;habilitación durante
bcf portd,3 ;10 microsegundos
movlw d'14' ;instrucción que enciende
movw f varLCD ;el cursor del LCD
call modoinstru ;escribe la instrucción
;en el LCD
;---------------------------------------------------------------------------
; Primera pantalla del display despues del reset
;---------------------------------------------------------------------------
call retardo1seg
movlw d'01' ;instruccion para limpiar el
movw f varLCD ;display y coloca el cursor al
call modoinstru ;inicio de la primera línea
movlw _espaci
movw f varLCD
call modocaracter
call retardo1seg
movlw d'12' ;esconde el cursor
movw f varLCD
call modoinstru
movlw _espaci
movw f varLCD
call modocaracter
movlw _espaci
movw f varLCD
call modocaracter
movlw _espaci
movw f varLCD
call modocaracter
movlw _espaci
movw f varLCD
call modocaracter
movlw _espaci
movw f varLCD
call modocaracter
movlw _espaci
movw f varLCD
call modocaracter
movlw _R
movw f varLCD
call modocaracter
movlw _e
movw f varLCD
call modocaracter
movlw _l
movw f varLCD
call modocaracter
movlw _o
movw f varLCD
call modocaracter
movlw _j
movw f varLCD
call modocaracter
movlw d'192' ;instrucción para comenzar
movw f varLCD ;la segunda línea
call modoinstru
movlw _espaci
movw f varLCD
call modocaracter
movlw _espaci
movw f varLCD
call modocaracter
movlw _espaci
movw f varLCD
call modocaracter
movlw _espaci
movw f varLCD
call modocaracter
deshoraD
movf horaD,w
movw f varLCD
call modocaracter
deshoraU
movf horaU,w
movw f varLCD
call modocaracter
movlw _dospuntos
movw f varLCD
call modocaracter
despminD
movf minutoD,w
movw f varLCD
call modocaracter
despminU
movf minutoU,w
movw f varLCD
call modocaracter
movlw _dospuntos
movw f varLCD
call modocaracter
despsegD
movf segundoD,w
movw f varLCD
call modocaracter
despsegU
movf segundoU,w
12. 12
movw f varLCD
call modocaracter
;---------------------------------------------------------------------------
; Configuración del timer
;---------------------------------------------------------------------------
bsf status,rp0 ;cambiar al banco 1
bcf status,rp1
bcf opsion,tocs
bcf opsion,psa
bsf opsion,ps0
bcf opsion,ps1
bsf opsion,ps2
bcf status,rp0 ;cambiar al banco 0
bcf status,rp1
bsf intcon,gie ;activación de
bsf intcon,toie ;interrupciones
clrf tmr0 ;inicia en 0 al registro TMR0
;---------------------------------------------------------------------------
Conteo_del_tiempo
;---------------------------------------------------------------------------
movf continter,w
xorlw .61
btfss status,z
goto Conteo_del_tiempo
incsegundos
clrf continter ;carga 0 en continter
incf segundoU,w ;segundoU = segundoU + 1
movw f segundoU
xorlw 0x3a ;segundoU = 9?
btfsc status,z
goto incsegundoD
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
goto despsegU
incsegundoD
movlw _0
movw f segundoU ;carga 0 en segundoU
incf segundoD,w ;segundoD = segundoD + 1
movw f segundoD
xorlw 0x36 ;segundoD = 5?
btfsc status,z
goto incminutoU
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
goto despsegD
incminutoU
movlw _0
movw f segundoD ;carga 0 en segundoD
incf minutoU,w ;minutoU = minutoU + 1
movw f minutoU
xorlw 0x3a ;segundoU = 9?
btfsc status,z
goto incminutoD
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
goto despminU
incminutoD
movlw _0
movw f minutoU ;carga 0 en minutoU
incf minutoD,w ;minutoD = minutoD + 1
movw f minutoD
xorlw 0x36 ;segundoD = 5?
btfsc status,z
goto inchoraU
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
goto despminD
inchoraU
movlw _0
movw f minutoD ;carga 0 en minutoD
incf horaU,w ;horaU = horaU + 1
movw f horaU
xorlw _4 ;horaU = 4?
btfss status,z
goto continchoraU
movf horaD,w
xorlw _2 ;horaD = 2?
btfsc status,z
goto reiniciar_reloj
continchoraU
movf horaU,w
xorlw 0x3a ;horaU = 9?
btfsc status,z
goto inchoraD
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
goto deshoraU
inchoraD
movlw _0
movw f horaU ;carga 0 en horaU
incf horaD,w ;horaD = horaD + 1
movw f horaD
xorlw _3 ;horaD = 2?
13. 13
btfsc status,z
goto reiniciar_reloj
preparadeshoraD
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
movlw d'16' ;mueve el cursor 1 posición a la
movw f varLCD ;izquierda
call modoinstru
goto deshoraD
reiniciar_reloj
movlw _0
movw f horaU
movw f horaD
goto preparadeshoraD
;=============================================
; Subrutinas
;=============================================
modoinstru
movf varLCD,w ;enmascara el nibble
andlw d'240' ;alto de la variable varLCD
movw f portd
bsf portd,3 ;genera un pulso de
call temp10micros ;habilitación durante
bcf portd,3 ;10 microsegundos
sw apf varLCD,w ;intercambia los nibbles
andlw d'240' ;enmascara el nibble alto
movw f portd ;de la variable varLCD
bsf portd,3 ;genera un pulso de
call temp10micros ;habilitación durante
bcf portd,3 ; 10 microsegundos
bsf portd,0 ;regresa el LCD a modo carácter
return
modocaracter
movf varLCD,w ;enmascara el nibble
andlw d'240' ;alto de la variable varLCD
movw f portd
bsf portd,0 ;coloca al LCD a modo carácter
bsf portd,3 ;genera un pulso de
call temp10micros ;habilitación durante
bcf portd,3 ;10 microsegundos
sw apf varLCD,w ;intercambia los nibbles
andlw d'240' ;enmascara el nibble alto
movw f portd ;de la variable varLCD
bsf portd,0 ;LCD a modo carácter
bsf portd,3 ;genera un pulso de
call temp10micros ;habilitación durante
bcf portd,3 ;10 microsegundos
return
Retardos ;Retardo de 200 milisegundos
ret1_3
movlw .02
movw f ret2
ret1_2
movlw .166
movw f ret3
ret1_1
decfsz ret3,1 ;497microsegundos=
goto ret1_1 ;aprox0.5milisegundos
decfsz ret2,1
goto ret1_2
decfsz ret1,1
goto ret1_3
return
temp10micros ;Retardo de 10 microsegundos
movlw .10
movw f ret3
ret2_1
decfsz ret3,1
goto ret2_1
return
retardo1seg ;Retardo de 1 segundo
movlw .255
movw f var1
ciclo_3
movlw .08
movw f var2
ciclo_2
movlw .166
movw f var3
ciclo_1
decfsz var3,1 ;497microsegundos=
goto ciclo_1 ;aprox. 0.5 milisegundos
decfsz var2,1
goto ciclo_2
decfsz var1,1
goto ciclo_3
return
end
Sobre el código del programa del reloj se encuentran los correspondientes
comentarios, para tener una mejor regencia para cuando sea analizado el
correspondiente diagrama de flujo.
Por último a manera de comentario, en el presente material hemos hecho
referencia a una herramienta muy útil, como es el empleo de un timer, esperando
con ello que les sea de mucho beneficio para que estén en posibilidades de
14. 14
integrar un proyecto más complejo y completo. Nuevamente dejamos patente de
que aquí solo mostramos una manera de abordar y solucionar una aplicación, y
que pueden existir diversas soluciones al mismo problema, que inclusive pueden
superar con mucho al presente material, la “invitación” es a que lo hagan y
practiquen.
Figura 5 Tarjeta Integradora de Aplicaciones con la implementación del reloj.
Los invitamos a que sigan pendientes con las sucesivas entregas, ya que
continuaremos presentando proyectos empleando la Tarjeta Integradora de
Aplicaciones (ICA-023). Hasta la próxima.
Lista de componentes para armar el presente proyecto.
Tarjeta integradora de aplicaciones (ICA-023).
Microcontrolador PIC16F874 ó PIC16F877.
Display LCD 2 renglones con 16 caracteres por renglón.
Batería de 9 VCD.