You are on page 1of 8

LIST P=PIC16F84A ; Pic a usar

#INCLUDE <P16F84A.INC> ; Lista de etiquetas de microchip

; Configuracin opciones de hardware para la programacin


__CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC

; Valores de constantes:
FRAC_INI D'12' ; Constante para inicio cuenta de fracciones de
; segundo
SEGS_INI D'196' ; Constante para inicio cuenta de segundos
MINS_INI D'196' ; Constante para inicio cuenta de minutos
HORS_INI D'244' ; Constante para inicio cuenta de horas
HORS_12H D'243' ; Constante para inicio cuenta de horas
; HORS_12H se utiliza para el clculo de las horas a mostrar.
; Si nos encontramos a las 1:00 la variable "horas" ser igual a HORS_INI (244) y el
; clculo para mostrar la hora ser:
; Hora display = horas - HORS_12H = 244 - 243 = 1
; Si son las doce, la variable "horas" ser igual a 255 de manera que se mostrar:
; Hora display = horas - HORS_12H = 255 - 243 = 12
ADJMIN D'9' ; Nmero de "frac_sec" que se necesita sumar cada
; minuto para ajustar el tiempo
ADJHOR D'34' ; Nmero de "frac_sec" que se necesita restar cada
; hora para ajustar el tiempo
ADJDIA D'3' ; Nmero de "frac_sec" que se necesita sumar cada
; 12 horas para ajustar el tiempo
;Ajustes:
; Un "frac_sec" es aproximadamente 1 / 244 s
; 1 MHz / 16 = 62.500 Hz ; 62.500 Hz / 256 = 244,140625 Hz ; T = 0,004096 s
; 0,004096 s * 244 = 0,999424 s; dif 1 segundo = -0,000576 s
; 1 "minuto" = 0,999424 s * 60 = 59,96544 s
; 60 s - 59,96544 s = 0,03456 s ; 0,03456 s / 0,004096 s = 8,4375
; 1 "minutoadj" = 59,96544 s + (0,004096 s * 9) = 59,96544 s + 0,036864 s = 60,002304 s
; 1 "hora" = 60,002304 s * 60 = 3600,13824 s
; 3600 s - 3600,13824 s = -0,13824 s ; -0,13824 s / 0,004096 s = -33,75 s ___________
; 1 "horaadj" = 3600,13824 s - (0,004096 s * 34) = DISPLAY DECENA MIN / DECENA SEG -> RA,2 -|1 \__/ 18|- RA,1 <- DISPLAY UNIDAD HR
; = 3600,13824 s - 0,139264 s = 3599,998976 s DISPLAY UNIDAD MIN / UNIDAD SEG -> RA,3 -|2 17|- RA,0 <- DISPLAY DECENA HR
; 12 "horas" = 3599,998976 s * 12 = 43199,987712 s NC -|3 16F84A 16|- XT
; 43200 s - 43199,987712 s = 0,012288 s ; 0,012288 s / 0,004096 s = 3 MCLR/ -|4 15|- XT
; 12 "horasadj" = 43199,987712 s + 0,004096 s * 3 = GND -|5 14|- Vcc
; = 43199,987712 s + 0,012288 s = 43200 s PUNTO dp -> RB,0 -|6 13|- RB,7 -> SEGMENTO g
PUL A (SEG) / SEGMENTO a -> RB,1 -|7 12|- RB,6 -> SEGMENTO f
; Activacin de RB1-3 para las entradas de los pulsadores PUL B (MIN) / SEGMENTO b -> RB,2 -|8 11|- RB,5 -> SEGMENTO e
PULSADOR B'00001110' ; RB1, RB2 y RB3 PUL C (HOR) / SEGMENTO c -> RB,3 -|9________10|- RB,4 -> SEGMENTO d

; Asignacin de banderas. Los pulsadores activos proporcionan un "1" PORTA, control displays 7 segmentos de ctodo comn
CHG H'03' ; Indica que se ha activado un pulsador o que es PORTB, segmetos de los displays, led separadores, pulsadores como entrada
; necesario actualizar los valores de la hora que tienen
; que mostrarse en los displays El pulsador A (conectado a RB1) muestra el segundero en tanto permanezca presionado.
PSEG H'04' ; Pulsador A, modo segundero. El pulsador B (conectado a RB2) avanza rpidamente los minutos.
PMIN H'05' ; Pulsador B, avance rpido minutos. El pulsador C (conectado a RB3) avanza rpidamente las horas.
PHOR H'06' ; Pulsador C, avance rpido horas.
P_ON H'07' ; Un pulsador ha sido activado

DSPOFF B'11111111' ; Displays apagados

; Mapa de activacin de segmentos para los displays (PORTB)


; a
; ========= Configurar puertos como
; | | INICIO salidas, blanquear display
; f | | b
; | g |
; ========= RB Pull Up desconectadas
; | | TMR0 en modo temporizador
; e | | c (se utilizan los pulsos de reloj
; | | Configuracin OPTION: internos, Fosc/4)
; ========= # p OPTION_REG = 10000011 Preescaler 1:16
; d
;
Bits PORTA como salidas
gfedcbap
Bits PORTB como salidas
CERO H'7E' ; 01111110
Puerto A apaga los displays
UNO H'0C' ; 00001100 Configuracin PUERTOS:
Con Puerto B todos los segmentos
DOS H'B6' ; 10110110 TRISA = 0000 0000
apagados. Separador entre horas y
TRES H'9E' ; 10011110 TRISB = 0000 0000
minutos encendido (RB0).
CUATRO H'CC' ; 11001100 PORTA = DSPOFF (1111 1111)
CINCO H'DA' ; 11011010 PORTB = 0000 0001
SEIS H'FA' ; 11111010
SIETE H'0E' ; 00001110
OCHO H'FE' ; 11111110 Pone 01h en TMR0
NUEVE H'DE' ; 11011110 Inicializacin de variables: Inicia display seleccionando
SEGM_OFF equ H'00' ; Todos los segmentos apagados. Separador TMR0 = 1 decena de hora
entre horas y minutos apagado (RB0). display = 1111 1110 (decena de hora) Los valores para digito1,
digito1 = CERO digito2, digito3 y digito4
digito2 = CERO permitirn que desde el
digito3 = DOS primer momento aparezcan
digito4 = UNO las 12:00 en el display.
banderas = 0000 0000 Como las horas comienzan
; Posicin de memoria de variables con 12 , la variable "horas"
Variables de tiempo: ha de ser 255d
; Las variables de tiempo comienzan con un nmero que permite contar y ajustar el tiempo
; Por ejemplo la variable "segundos" se inicia con 196 decimal, para que despus de 60 frac_sec = FRAC_INI (12d)
; incrementos de 1 segundo se produzca un 0 (196 + 60 = 256 -> 0) segundos = SEGS_INI (196d)
frac_sec H'0C' ; Fracciones de segundo (1/244) minutos = MINS_INI (196d)
segundos H'0D' ; Segundos horas = 255d (12 horas)
minutos H'0E' ; Minutos
horas H'0F' ; Horas
conta1 H'10' ; Variable 1 para bucle contador
;
display H'11' ; Indicador de display que debe actualizarse
digito1 H'12' ; Display unidad de minuto / unidad de segundo
PRINCIPAL Pag. 2
digito2 H'13' ; Display decena de minuto / decena de segundo
digito3 H'14' ; Display unidad de hora
digito4 H'15' ; Display decena de hora
banderas H'16' ; Banderas; 3-CHG, 4-PSEG, 5-PMIN, 6-PHOR, 7-P_ON
PRINCIPAL
TMR0 cuenta libremente
para no perder ciclos de
reloj escribiendo valores

TMR0_LLENO

Incremento de TMR0 se va incrementando lbremente con la seal de


TMR0 reloj a 1.000.000 MHz / 16 = 62.500 Hz

NO Se comprueba el bit Z de STATUS


TMR0=0
TMR0 se ha desbordado y se han contado 256 * 16 = 4096
ciclos de reloj, (4,096 ms)
SI La frecuencia es: 62.500 Hz / 256 = 244,140625 Hz

Se aade 1 a frac_sec Se activa separador horas-minutos (RB0)


frac_sec = frac_sec + 1
frac_sec comienza por 12, hasta desbordarse cuenta 244 Restaura la variable frac_sec para la prxima vuelta

NO SI RB0 = 1
frac_sec = 0
frac_sec = FRAC_INI (12d) Comprueba variables pulsadores
frac_sec = 0, se ha contado 1 segundo
(0,999424 s)

COMPROBAR_PUL
El programa pasa por aqu cada 4,096
ms, esto es unas 244 veces por segundo No hay pulsadores activados
P_ON = 1
NO

Incrementar segundos, minutos y horas SI


Ajustes cada minuto, hora y 1/2 dia Se ha activado un pulsador
CHG se pone a 1 pero no es PSEG, debe ser
PMIN o PHOR
NO SI
INC_HORA PSEG = 0

Si est pulsado PSEG, (Pul


A) se mostrarn los
Pag. 7 segundos en el display

COMPROBAR_CHG Se comprueba el estado de CHG por si se ha activado algn


pulsador o es necesario actualizar los valores de la hora que
tienen que mostrarse en los displays Puesta en hora
Se actualiza hora, displays y pulsadores cada 4,096 ms (244 PMIN (Pul B) avanza los minutos PONER_RELOJ
veces por segundo) PHOR (Pul C) avanza las horas
NO SI
CHG = 1
Pag. 6

Se comprueba si se activo el
pulsador de segundos (Pul A) para
Si no se han activado pulsadores ni ha cambiado la COMPROBAR_SEG mostrar los segundos en el display
hora se salta a DISPLAY_PUL, que principalmente
refresca uno de los displays cada vez que se accede
a ella y escanea pulsadores.
SI NO
PSEG = 1

Se mostrarn los segundos en el Se guardan la hora y los


display de minutos minutos para su tratamiento
OBTENER_H_M
Se guarda temporalmente el nmero
de segundos en digito1
Resto de variables digit a 0
digito2 = 0 digito3 se utiliza temporalmente para
digito3 = 0 almacenar la hora, (Si la hora es 255, digito3 = horas HORS_12H (243d)
digito4 = 0 digito3 sera 255 243 = 12 digit 1 = minutos MINS_INI (196d)
digito1 = second SEGS_INI (196d) digito1 se utiliza temporalmente para
almacenar los minutos

Divide los segundos o los minutos y las


Pag. 4 DIV_DIGITOS horas en digitos independientes, ejemplo,
[14] lo pasa a [1]-[4]

Convierte cada digito (digito1, digito2, digito3 y digito4)


Pag. 5 CONVER_COD_7S
en valores para los segmentos del display

Se borran los bits de flag para actualizar su estado


Escanea pulsadores, si alguno est activado se pone a 1 la
Pag. 3 DISPLAY_PUL bandera que le corresponda as como P_ON y CHG
Muestra los digitos correspondientes a los segundos o a los
minutos y horas en el display que corresponda.
Cada display se actualiza cada 244,14 Hz / 4 = 61,04 Hz.
Se borran los bits de flag para actualizar su estado
Escanea pulsadores, si alguno est pulsado se pone a 1 el pulsador
que le correspoda as como "P_ON" y "CHG"
DISPLAY_PUL Muestra los digitos correspondientes a los segundos o a los minutos y
horas en el display que corresponda.

banderas = 0000 0000


Se borran los bits de flag para actualizar su estado
PORTA = DSPOFF (1111 1111)
Apagar los segmentos respetando separador horas-minutos (RB0)
w = SEGM_OFF XOR PORTB
Se apagan los displays
w = w AND B'11111110'
Se configuran los bits 1, 2 y 3 de PORTB como entrada
PORTB = w XOR PORTB
Se almacena el estado de los pulsadores en var
TRISB = PULSADOR (0000 1110)

COMPROBAR_PSEG w = SEGM_OFF XOR PORTB


w = w AND B'11111110'
PORTB = w XOR PORTB

SI CHG = 1 Este cdigo copia los bits del literal SEGM_OFF que
RB1 = 1 PSEG= 1 se quieran en PORTB, Se copiaran aquellos bits de
P_ON = 1 SEGM_OFF cuya posicin coincida con un 1 en la
mscara que se utiliza con la funcin AND y se
NO
respetaran los valores de los bits PORTB que
coincidan con un 0 en la mscara. En este caso
SEGM_OFF = 00H y en la operacin AND se utiliza
B'11111110' con lo que en PORTB se respetar el
COMPROBAR_PMIN valor de RB0 y se pondrn a cero el resto de bits.

En nuestro caso se podra simplificarse el proceso,


eliminando la primera XOR pero entonces no se
SI CHG = 1 podra trabajar con otros posibles valores de
RB2 = 1 PMIN= 1 SEGM_OFF
P_ON = 1
Ejemplos:
NO
Si PORTB es 1000 1110

w = SEGM_OFF XOR PORTB:


COMPROBAR_PHOR 0000 0000
1000 1110
---------------
1000 1110
SI CHG = 1
RB3 = 1 PHOR= 1
w = w AND B'11111110':
P_ON = 1
1000 1110
NO 1111 1110
--------------
1000 1110

PORTB = w XOR PORTB


ACTIVAR_SEGM 1000 1110
1000 1110
--------------
Puerto B como salida 0000 0000
TRISB = 0000 0000

Se determina que display debe actualizarse, es


decir, que dato debe presentarse en el puerto B y Si PORTB es 1000 1111
se establece el siguiente display
w = SEGM_OFF XOR PORTB:
0000 0000
Display es SI 1000 1111
w = digito4
XXXX XXX0 ---------------
1000 1111
NO
w = w AND B'11111110':
1000 1111
Display es SI 1111 1110
w = digito3
XXXX XX0X --------------
1000 1110
NO
PORTB = w XOR PORTB
1000 1110
Display es SI
w = digito2 1000 1111
XXXX X0XX --------------
0000 0001
NO

Display es SI
w = digito1
XXXX 0XXX

NO

Se entregar el valor de w en Para rotar el display a la prxima posicin


w = w XOR PORTB
el puerto B respetando el se utiliza el siguiente cdigo:
w = w AND B'11111110'
valor de RB0
PORTB = w XOR PORTB
rlf display,F ; Rota display 1 bit a la prxima
posicin
bsf display,0 ; Asegura un 1 en la posicin
ms baja de display (luego se har 0 si es
Se apagan los puntos de necesario)
NO separacin. Se activ en btfss display,4 ; Comprueba si el ltimo
Bit 7 de
RB0 = 0 INICIO y se activa cada vez display fu actualizado
frac_sec = 0
que frac_sec se hace 0. bcf display,0 ; Si lo fu, se vuelve a habilitar
el primer display
SI
La variable display va cambiando:
Se habilita el display correspondiente 1111 1101
PORTA = display Cada display se enciende con una 1111 1011
cadencia de 244 Hz / 4 = 61 Hz 1111 0111
1110 1110
1101 1101
1011 1011
En la variable display se va desplazando un cero a
Rota display a 0111 0111
la izquierda. Slo se tendrn en cuenta los 4 bits
siguiente posicin 1110 1110
menos significativos
Slo valen los 4 bits menos significativos

PRINCIPAL Pag. 2
Divide los segundos o los minutos y las
DIV_DIGITOS horas en digitos independientes, ejemplo,
[14] lo pasa a [1]-[4]

Se ponen a cero las posiciones de las decenas para el caso de


digito4 = 0 que no se incrementen Se vuelve a comprobar si es
digito2 = 0 Bucle para convertir cada nmero (segundos o minutos y horas) necesario sumar uno a la
conta1 = 2 Direccin de digito1 en FSR para usar INDF decena cada vez que sta
FSR = digito1 La primera vez, FSR = digito1 (minutos o segundos) y la segunda se ha incrementado
vez FSR = digito3 (horas)

Este LOOP se utiliza primero para los minutos o los segundos y


despus para las horas
INC_DECENAS

LOOP
El puntero apunta a la
primera posicin de las
Incf FSR,F decenas
Incf INDF,F Se aade 1 a las decenas
Averiguar cuantas decenas Decf FSR,F Se restaura el valor de INDF
INDF = INDF - 10 hay en el nmero. El nmero para la prxima resta hasta
menos diez en cada bucle. que se termine

CARRY = 1 SI

Se comprueba "CARRY",
NO que se pone a 1 si en la
resta no se ha producido
llevada
Si C = 1 se aadir 1 a la
posicin de las decenas

INDF = 10 + INDF
Este LOOP se C = 0, no se incrementan las
utiliza para las decenas y se suma 10 para
horas despus de restaurar las unidades
trabajar con los
minutos o los
segundos

LOOP2

FSR = digito3
PROX_NUM

conta1 = conta1 -1 Prximo nmero:


Primero ha sido segundos o
minutos y luego horas

NO
conta1 = 0

SI

CONVER_COD_7S Pag. 5
Convierte cada dgito a
CONVER_COD_7S cdigo 7 segmentos para los
displays

Coloca la direccin del primer


FSR = digito1 digito (digito1) en FSR
conta1 = 4 Prepara la variable conta1 para el
bucle de los 4 displays

PROX_DIGITO

Obtener el valor de la
w = INDF
variable "digito" actual

LLamar a la rutina de
Pag. 8 CODIGO_7S conversin a cdigo 7
segmentos

Colocar en la variable "digito" actual el


INDF = w cdigo 7 segmentos devuelto
FSR = FSR + 1 Incremente INDF para el prximo
conta1 = conta1 - 1 "digito"
Se resta 1 a conta1

NO Permitir que conta1 de slo


conta1 = 0
4 vueltas

SI

BORRAR_CERO
Si hay un cero en el display de las
decenas de hora no se muestra (borrado
NO de los ceros a la izquierda)
digito4 = 0?

SI

digito4 = SEGM_OFF
Si est pulsado PSEG no se muestra nada en el
display de la posicin de la unidad de hora.
Contando con BORRAR_CERO, esto significa que
slo se mostrarn los segundos.

BORRAR_CERO_SEG

SI
PSEG = 1

NO digito3 = SEGM_OFF

DISPLAY_PUL Pag. 3
Puesta en hora de horas y
PONER_RELOJ
minutos

Inicia los segundos cuando se


segundos = SEGS_INI (196d)
pone el reloj en hora

PONER_MINUTOS

Comprobar si se ha pulsado
PMIN (Pulsador minutos)

NO
PMIN = 1

SI

Avance rpido del tiempo


cuando se ajustan minutos frac_sec = 175d
frac_sec = 175 minutos = minutos + 1
Incrementar los minutos

NO
minutos = 0

SI

Iniciar minutos si al
incrementar se han minutos = MINS_INI
desbordado

PONER_HORAS

Comprobar si se ha pulsado
PHOR (Pulsador horas)

NO
PHOR = 1

SI

Avance rpido del tiempo


cuando se ajustan horas frac_sec = 127d
frac_sec = 127d horas = horas + 1
Incrementar las horas

NO
horas = 0

SI

horas = HORS_INI (244d)

OBTENER_H_M Pag. 2
Incrementar segundos, minutos y horas
INC_HORA
Ajustes cada minuto, hora y 12 horas

CHG = 1 Se especifica que se ha producido un cambio

Como ha pasado un segundo se incrementa


segundos = segundos + 1
segundos

NO
segundos = 0

SI

Se ha desbordado "segundos" y se reestablece el


valor inicial de segundos para la prxima vuelta
segundos = SEGS_INI (196d)
Se resta 9 a frac_sec cada minuto para los
frac_sec = frac_sec ADJMIN (9d)
ajustes de tiempo
minutos = minutos + 1
El minuto ser 9 frac_sec ms largo.
Se aade 1 minuto

NO
minutos = 0

SI

Se reestablece el valor inicial de minutos para la


prxima vuelta
minutos = MINS_INI (196d)
Se suma 34 frac_sec a cada hora para los
frac_sec = frac_sec + ADJHOR (34d)
ajustes de tiempo
horas = horas + 1
La hora ser 34 frac_sec ms corta
Se aade 1 hora

NO
horas = 0

SI

Se reestablece el valor inicial de horas para la


prxima vuelta
horas = HORS_INI (244d)
Se resta 3 a frac_sec cada 12 horas para los
frac_sec = frac_sec ADJDIA (3d)
ajustes de tiempo
Cada 12 horas se aadirn 3 "frac_sec"

COMPROBAR_CHG Pag. 2
SUBRUTINAS

CODIGO_7S
Devuelve el cdigo 7
segmentos

addwf PCL,F
retlw CERO
retlw UNO
retlw DOS Devuelve en el acumulador
retlw TRES el valor de la constante
retlw CUATRO CERO a NUEVE segn el
retlw CINCO valor que se hubiese
retlw SEIS colocado en w
retlw SIETE
retlw OCHO
retlw NUEVE

You might also like