Está en la página 1de 37

;

***************************************
**********************
; RELOJ DE 12 HORAS
;
***************************************
**********************
LIST P=PIC16F84A

; Pic

a usar
#INCLUDE <P16F84A.INC>

Lista de etiquetas de microchip


;
;
***************************************
**********************
; Configuracin opciones de hardware
para la programacin
__CONFIG
& _WDT_OFF & _XT_OSC

_CP_OFF & _PWRTE_ON

;
***************************************
***********************
; Lista de constantes y variables para
el uso del programa
;
***************************************
***********************
;
; Valores de constantes
***************************************
FRAC_INI

equ

D'12'

Constante para inicio cuenta de


fracciones de segundo
SEGS_INI

equ

D'196'

Constante para inicio cuenta de


segundos
MINS_INI

equ

D'196'

Constante para inicio cuenta de minutos


HORS_INI

equ

D'244'

Constante para cuenta de horas

HORS_12H

equ

D'243'

Constante para cuenta de horas


ADJMIN

equ

D'9'

Nmero de "frac_sec" que se necesita


sumar cada minuto
; para
ajustar el tiempo
ADJHOR

equ

D'34'

Nmero de "frac_sec" que se necesita


restar cada hora
; para
ajustar el tiempo
ADJDIA

equ

D'3'

Nmero de "frac_sec" que se necesita


sumar cada 12 horas
; para
ajustar el tiempo; Activacin de RB1-3
para las entradas de los pulsadores
PULSADOR

equ

B'00001110'

; RB1,

RB2 y RB3; Asignacin de banderas. Los


pulsadores activos proporcionan un "1"

CHG

equ

H'03'

Indica que se ha activado un pulsador o


que es necesario
;
actualizar los valores de la hora que
tienen que mostrarse
; en
los displays
PSEG

equ

H'04'

Pulsador A, modo segundero.


PMIN

equ

H'05'

Pulsador B, avance rpido minutos.


PHOR

equ

H'06'

Pulsador C, avance rpido horas.


P_ON

equ

H'07'

; Un

pulsador ha sido activadoDSPOFF


equ

B'11111111'

; Displays

apagados (PORTA)

gfedcbap
CERO
01111110

equ

H'7E'

UNO

equ

H'0C'

equ

H'B6'

equ

H'9E'

equ

H'CC'

equ

H'DA'

equ

H'FA'

equ

H'0E'

equ

H'FE'

equ

H'DE'

equ

H'00'

; Todos

00001100
DOS
10110110
TRES
10011110
CUATRO
11001100
CINCO
11011010
SEIS
11111010
SIETE
00001110
OCHO
11111110
NUEVE
11011110
SEGM_OFF

los segmentos apagados. Separador entre


horas

; y
minutos apagado (RB0).; Posicin de
memoria de variables
************************************fra
c_sec

equ

H'0C'

Fracciones de segundo (1/244)


segundos

equ

H'0D'

equ

H'0E'

horas

equ

H'0F'

; Horas

conta1

equ

H'10'

Segundos
minutos
Minutos

Variable 1 para bucle contador


display

equ

H'11'

Indicador de display que debe


actualizarse
digito1

equ

H'12'

Display unidad de minuto / unidad de


segundo

digito2

equ

H'13'

Display decena de minuto / decena de


segundo
digito3

equ

H'14'

Display unidad de hora


digito4

equ

H'15'

Display decena de hora


banderas

equ

H'16'

Banderas; 3-CHG, 4-PSEG, 5-PMIN, 6PHOR, 7-P_ON


;
***************************************
***********************
ORG 0x00
goto

;Vector de Reset

org

INICIO
0x05

;Salva el vector

de interrupcin
;
***************************************
***********************
; SUBRUTINAS

;
***************************************
***********************
CODIGO_7S

; Devuelve el

cdigo 7 segmentos
addwf

PCL,F

retlw

CERO

retlw

UNO

retlw

DOS

retlw

TRES

retlw

CUATRO

retlw

CINCO

retlw

SEIS

retlw

SIETE

retlw

OCHO

retlw

NUEVE

;
***************************************
***********************
; Comienzo del programa

;
***************************************
***********************
;
INICIO
;

Configurar puertos como salidas,

blanquear display
bsf

STATUS,RP0

; Activa

el banco de memoria 1.
movlw

B'10000011'

Configuracin del registro Option, RB


Pull Up desconectadas
movwf

OPTION_REG

; TMR0

en modo temporizador (uso de pulsos de


reloj internos, Fosc/4)
;
prescaler TMR0 a 1:16
movlw

B'00000000'

movwf

TRISA

; Pone

todas las patillas del puerto A como


salidas

movwf

TRISB

; Pone

todas las patillas del puerto B como


salidas
bcf

STATUS,RP0

; Activa

el banco de memoria 0.
;
; Establecer estados iniciales de las
salidas
movlw

DSPOFF

movwf

PORTA

; Apaga

B'00000001'

; Todos

los displays
movlw

los segmentos apagados. Separador


movwf

PORTB

; entre

horas y minutos encendido (RB0).


; Inicializacin de variables:
movlw

H'01'

movwf

TMR0

01h en TMR0
movlw

B'11111110'

; Pone

movwf

display

Inicia display seleccionando decena de


hora
movlw

CERO

movwf

digito1

Aparecer un "0" en el display unidad


de minutos
movwf

digito2

Aparecer un "0" en el display decena


de minutos
movlw

DOS

movwf

digito3

Aparecer un "2" en el display unidad


de hora
movlw

UNO

movwf

digito4

Aparecer un "1" en el display decena


de hora
movlw

B'00000000'

movwf

banderas

Coloca todas las banderas a 0

; Inicia las variables de tiempo


movlw

FRAC_INI

movwf

frac_sec

movlw

SEGS_INI

movwf

segundos

movlw

MINS_INI

movwf

minutos

movlw

D'255'

movwf

horas

; 12
; 196
; 196
; Las

horas comienzan con 12 por lo que


"horas" ha de ser 255
;
***************************************
***********************
PRINCIPAL ; Rutina principal cclica
;
***************************************
***********************
;
;

Esperar al desbordamiento de TMR0

TMR0_LLENO

4 MHz -> 1 MHz

1.000.000 Hz / 16 = 62.500 Hz

62.500 Hz / 256 = 244,140625 Hz ->

4,096 ms
movf
btfss

TMR0,W
STATUS,Z

; TMR0

cuenta libremente para no perder ciclos


del reloj
;
escribiendo valores
goto

TMR0_LLENO

; Se ha desbordado TMR0 y se han


contado 256.
; Tarda en desbordarse 4.096 ciclos de
reloj, 4,096 ms
incfsz

frac_sec,F

; Se

aade 1 a frac_sec
goto

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
; Se ha desbordado frac_sec y se han
contado 244 "frac_sec", 1 segundo.
; Tarda en desbordarse 4.096 ciclos de
reloj, 4,096 ms * 244 = 999,424 ms
; Al no consegirse exactamente 1
segundo sino 0,999424 s, luego se
necesitan ajustes
bsf

PORTB,0

Se activa separador horas-minutos


movlw

FRAC_INI

movwf

frac_sec

Restaura la variable frac_sec para la


prxima vuelta

COMPROBAR_PUL

Comprueba variables pulsadores


btfss

banderas,P_ON

Si no se ha pulsado nada, se pasa a


INC_HORA
goto

INC_HORA

Incrementa segundos, minutos y horas.


Ajustes y CHG a 1
btfsc

banderas,PSEG

Comprobar si se ha pulsado PSEG


(Pulsador segundos)
goto

INC_HORA

Se ha pulsado PSEG, (Pul A) y se


mostrarn
;
los segundos en el display
PONER_RELOJ
movlw

SEGS_INI

; 196d

movwf

segundos

; Inicia

los segundos cuando se pone el reloj en


hora

PONER_MINUTOS
btfss

banderas,PMIN

Comprobar si se ha pulsado PMIN


(Pulsador minutos)
goto

PONER_HORAS

No se ha pulsado PMIN, ir a comprobar


estado de PHOR
movlw

H'AF'

frac_sec

175d
movwf

Avance rpido del tiempo cuando se


ajustan minutos frac_sec = 175
incfsz

minutos,F

Incrementar los minutos


goto

PONER_HORAS

movlw

MINS_INI

movwf

minutos

Iniciar minutos si al incrementar se


han desbordado
PONER_HORAS

btfss

banderas,PHOR

Comprobar si se ha pulsado PHOR


(Pulsador horas)
goto

OBTENER_H_M

No se ha pulsado PHOR, no se cambian


las horas
movlw

H'7F'

frac_sec

127d
movwf

Avance rpido del tiempo cuando se


ajustan horas frac_sec = 127
incfsz

horas,F

Incrementar la hora
goto

OBTENER_H_M

movlw

HORS_INI

movwf

horas

Iniciar la hora si al incrementar se


han desbordado
goto
INC_HORA

OBTENER_H_M
; Incrementar

segundos, minutos y horas

; Ajustes cada
minuto, hora y 12 horas
bsf

banderas,CHG

; Se

especifica que se ha producido un


cambio
incfsz

segundos,F

; Como

ha pasado un segundo se incrementa


"segundos"
goto

COMPROBAR_CHG

movlw

SEGS_INI

; Se ha

desbordado "segundos" y se reestablece


el valor inicial
movwf

segundos

; de

"segundos" para la prxima vuelta


movlw

ADJMIN

; Se

resta 9 a "frac_sec" cada minuto para


los ajustes de tiempo
subwf

frac_sec,F

; El

minuto ser 9 "frac_sec" ms largo

incfsz

minutos,F

; Se

aade 1 minuto
goto

COMPROBAR_CHG

movlw

MINS_INI

; Se ha

desbordado "minutos" y Se reestablece


el valor inicial
movwf

minutos

; de

"minutos" para la prxima vuelta


movlw

ADJHOR

; Se

suma 34 a "frac_sec" cada hora para los


ajustes de tiempo
addwf

frac_sec,F

; La

hora ser 34 "frac_sec" ms corta


;
incfsz

horas,F

; Se

aade 1 hora
goto

COMPROBAR_CHG

movlw

HORS_INI

; Se ha

desbordado "horas" y se reestablece el


valor inicial

movwf

horas

; de

"horas" para la prxima vuelta


movlw

ADJDIA

; Se

resta 3 a "frac_sec" cada 12 horas para


los ajustes de tiempo
subwf

frac_sec,F

; Cada

12 horas se aadirn 3 "frac_sec"


; 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
; Se actualiza hora, displays y
pulsadores cada 4,096 ms (244 veces por
segundo)
COMPROBAR_CHG
btfss

banderas,CHG

; Si

no se han activado pulsadores ni ha


cambiado la hora

goto

DISPLAY_PUL

; se

salta a DISPLAY_PUL, que principalmente


refresca uno de los
; displays cada vez
que se accede a ella y escanea
pulsadores.
COMPROBAR_SEG

Se

comprueba si se activo el pulsador de


segundos (Pul A)
; para mostrar los
segundos en el display
btfss

banderas,PSEG

goto

OBTENER_H_M

; No

estaba pulsado PSEG


movlw

H'00'

; Se

mostrarn los segundos en el display de


minutos
movwf

digito2

Variables "digito2" a 0
movwf

digito3

Variables "digito3" a 0

movwf

digito4

Variables "digito4" a 0
movlw

SEGS_INI

subwf

segundos,W

movwf

digito1

; Se

guarda temporalmente el nmero de


segundos en digito1
goto

DIV_DIGITOS

OBTENER_H_M
movlw

HORS_12H

subwf

horas,W

movwf

digito3

; La

variable digito3 almacena temporalmente


el valor para las horas
movlw

MINS_INI

subwf

minutos,W

movwf

digito1

; La

variable digito1 almacena temporalmente


el valor para los minutos

DIV_DIGITOS

; Divide los

segundos o los minutos y las horas en


dgitos independientes
; ejemplo, [14] lo
pasa a [1]-[4]
movlw

H'00'

movwf

digito4

; Se

ponen a cero las posiciones de las


decenas
movwf

digito2

; para

el caso de que no se incrementen


movlw

H'02'

movwf

conta1

; Bucle

para convertir cada nmero (segundos o


minutos y horas)
movlw

digito1

Direccin de digito1 en FSR para usar


INDF
movwf

FSR

; La

primera vez, FSR = digito1 (minutos o


segundos) y la segunda vez FSR =
digito3 (horas)

goto

LOOP

LOOP2

; Este LOOP se utiliza para

las horas despus de trabajar con los


minutos o los segundos
movlw

digito3

movwf

FSR

LOOP

; Este LOOP se utiliza primero

para los minutos o los segundos y


despus para las horas
movlw

D'10'

Averiguar cuantas "decenas" hay en el


nmero
subwf

INDF,F

; En

cada LOOP restar 10 al nmero


btfsc

STATUS,C

; Se

comprueba "C", que se pone a 1 si en la


resta no se ha
; producido llevada

goto

INC_DECENAS

; C

= 1 por lo que se aade 1 a la posicin


de las decenas
addwf

INDF,F

; C = 0,

no se incrementan las decenas y se suma


10 para restaurar
; las unidades
goto

PROX_NUM

INC_DECENAS
incf

FSR,F

; El

puntero apunta a la primera posicin de


las decenas
incf

INDF,F

; Se

aade 1 a las decenas


decf

FSR,F

; Se

restaura el valor de INDF para apuntar


al nmero
goto

LOOP

; para la

prxima resta hasta que se termine


; Con "goto LOOP"
se vuelve a comprobar si es necesario

; sumar uno a la
decena cada vez que esta se ha
incrementado
PROX_NUM

; Prximo

nmero, primero ha sido segundos o


minutos y luego horas
decfsz
goto

conta1,F
LOOP2

CONVER_COD_7S

Convierte cada dgito a cdigo 7


segmentos para los displays
movlw

digito1

movwf

FSR

; Coloca la

direccin del primer digito (digito1)


en FSR
movlw

H'04'

movwf

conta1

Prepara la variable conta1 para el


bucle de los 4 displays

PROX_DIGITO
movf

INDF,W

; Obtener

el valor de la variable "digito" actual


call

CODIGO_7S

; LLamar a

la rutina de conversin a cdigo 7


segmentos
movwf

INDF

; Colocar

en la variable "digito" el cdigo 7


segmentos devuelto
incf

FSR,F

Incremente INDF para el prximo


"digito"
decfsz

conta1,F

; Permitir

que conta1 de slo 4 vueltas


goto
;BORRAR_CERO

PROX_DIGITO
; Si hay un

cero en el display de las decenas de


hora
; no se
muestra (borrado de los ceros a la
izquierda)

movlw

CERO

subwf

digito4,W

btfss

STATUS,Z

goto

BORRAR_CERO_SEG

movlw

SEGM_OFF

movwf

digito4

;
BORRAR_CERO_SEG
btfss

banderas,PSEG

; Si

est pulsado PSEG no se muestra nada en


el display de la
goto

DISPLAY_PUL

posicin de la unidad de hora.


movlw

SEGM_OFF

Contando con BORRAR_CERO, esto


significa que slo se
movwf

digito3

mostrarn los segundos.


movwf
DISPLAY_PUL

digito4
; 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"
; Muestra los
dgitos correspondientes a los segundos
o a
; los minutos y
horas en el display que corresponda.
movlw

B'00000000'

movwf

banderas

; Se

borran los bits de flag para actualizar


su estado
; Apagar los displays
movlw

DSPOFF

movwf

PORTA

; Apagar los segmentos respetando


separador horas-minutos

movlw

SEGM_OFF

; Respeta

valor RB0
xorwf

PORTB, w

andlw

B'11111110'

Poner "1" el la posicin del bit a


copiar
xorwf

PORTB, f

; Configurar los bits 1, 2 y 3 de


PORTB como entrada
bsf

STATUS,RP0

; Activa

el banco 1.
movlw

PULSADOR

movwf

TRISB

; Se

configuran los bits 1, 2 y 3 de PORTB


como entrada
bcf

STATUS,RP0

; Activa

el banco 0.
nop

; Las

instrucciones "nop" pueden no ser


necesarias.

nop

; En principio

proporcionan el tiempo suficiente para


que los
nop

; estados

anteriores de las salidas se actualicen


a travs de
nop

; las

resistencias de 10K (y de las de 820


ohm si est activado
nop

; algn

pulsador) antes de leer las patillas


del puerto.
COMPROBAR_PSEG

; Se comprueba

Pulsador PSEG
btfss

PORTB,1

goto

COMPROBAR_PMIN

bsf

banderas,CHG

bsf

banderas,PSEG

bsf

banderas,P_ON

COMPROBAR_PMIN

; Se comprueba

Pulsador PMIN
btfss

PORTB,2

goto

COMPROBAR_PHOR

bsf

banderas,CHG

bsf

banderas,PMIN

bsf

banderas,P_ON

COMPROBAR_PHOR

; Se comprueba

Pulsador PHOR
btfss

PORTB,3

goto

ACTIVAR_SEGM

bsf

banderas,CHG

bsf

banderas,PHOR

bsf

banderas,P_ON

ACTIVAR_SEGM

; Se coloca en PORTB el

valor para los segmentos del display


actual
bsf

STATUS,RP0

el banco 1.
movlw

H'00'

; Activa

movwf

TRISB

; Puerto

B como salida
bcf

STATUS,RP0

; Activa

el banco 0.
; Se determina que display debe
actualizarse, es decir, que dato debe
; presentarse en el puerto B y se
establece el siguiente display
btfss

display,0

; Si es

el primer display (decena de hora)


tomar digito4
movf

digito4,W

btfss

display,1

; Si es

el segundo display (unidad de hora)


tomar valor digito3
movf

digito3,W

btfss

display,2

; Si es

el tercer display (decena de min/seg)


tomar valor digito2
movf

digito2,W

btfss

display,3

; Si es

el cuarto display (unidad de min/seg)


tomar valor digito1
movf

digito1,W

; Entregar el valor en puerto B y


respetar valor RB0
xorwf

PORTB, w

andlw

B'11111110'

Poner "1" el la posicin del bit a


copiar
xorwf

PORTB, f

btfsc

frac_sec,7

Establecer el separador de horas y


minutos a un 50%
bcf

PORTB,0

; del

ciclo (1/2 segundo encendido, 1/2


segundo apagado)

movf

display,W

; Tomar

el valor del display que debe


habilitarse
movwf

PORTA

; Cada

display se enciende con una cadencia


de 244 Hz / 4 = 61 Hz
; Cada display se enciende con
una cadencia de 244 Hz / 4 = 61 Hz
; En este momento estn encendidos
los segmentos correspondientes
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 necesario)
btfss

display,4

Comprueba si el ltimo display fue


actualizado
bcf

display,0

; Si lo

fue, se vuelve a habilitar el primer


display

; La
variable display va cambiando:
;

1111

1111

1111

1110

1101

1011

0111

1110

1101
1011
0111
1110
1101
1011
0111
1110
; Slo
valen los 4 bits menos significativos

goto

PRINCIPAL

realizar todo el proceso


END

; Volver a

También podría gustarte