You are on page 1of 13

ESCUELA SUPERIOR POLITÉCNICA DE LITORAL

Facultad de Ing. en Electricidad y Computación

LABORATORIO DE MICROCONTROLADORES

PROYECTO del PARCIAL en lenguaje Ensamblador


#4: Reloj capaz de ajustar minutos a tiempo real y generar
tonos audibles al momento del ajuste.
Autor:
Oscar Veloz Segarra

Paralelo :
3
Grupo:
2
Profesor :
Ing. Carlos Valdivieso

F. Presentación:
19-Diciembre-2011
1.- Enunciado del proyecto
Reloj capaz de ajustar minutos a tiempo real y generar tonos audibles al
momento del ajuste.

2.- Diagrama de Bloques

µC 4 UNIDADES DE
PIC16F887 SEGUNDOS
Tres (Modo Normal y
Botones de Ajuste de
conteo)

I 3 DECENAS DE
SEGUNDOS

4 UNIDADES DE
MINUTOS

3 DECENAS DE
MINUTOS

UNIDADES
4
DE HORAS

2 DECENAS DE
HORAS

3.- Diagrama de Flujo funcional del Programa principal y de las


subrutinas
Programa Principal:

4.- Descripción del algoritmo o estrategia utilizada.

1. Trabajaremos con frecuencia de 4MHz y para generar un segundo en la


vida real le asignaremos al TMR0 un valor de 217 según la fórmula de
temporización.

2. Configuramos todos los pines del puerto B como salida donde se verán
las unidades, así como los del puerto C donde saldrán las decenas.

3. Creamos con CBLOCK todas las variables necesarias para el conteo:


 contador (quien lleva la cuenta del número de interrupciones, por lo
cual lo pondremos en 100, para que cada 100 interrupciones se
incremente en uno las unidades de segundo)
 unidades y decenas de segundos, así como para minutos y horas.
 set_min_unidades y set_min_decenas son las variables que
almacenan el valor seteado o ajustado de minutos deseados por el
usuario.
 aux_seg, aux_min y aux_hora son variables auxiliares que debí
emplear para la manipulación de bits previa a mostrar por los leds. Es
que tuve que desplazar el registro de decenas y luego hacer
operaciones como iorwf y swapf, y como no quería que se borren los
valores que tenía las verdaderas variables de tiempo de decenas, me
fue necesario crearlas.

4. Luego de la configuración de la interrupción y del TMR0, dejamos que se


desborde el TMR0, dejándolo en un loop infinito con la instrucción nop.
Al desbordase se ejecutará todo el bloque de Interrupción. En el bloque
de interrupción están todos los incrementos de las variables de control
unidades, decenas y el decremento de la variable contador.

5. Al ejecutarse una sola interrupción decrementa en uno al contador. Por


tanto al ejecutarse 100 interrupciones se incrementa en uno las
unidades. Cuando se hayan incrementado 9 segundos, se incrementará
en uno las decenas. Cuando se hayan contado 5 decenas de segundos
y 9 unidades de segundo, se incrementará una unidad de minuto. Tal
como funciona un reloj real. De manera similar sucederá con las
unidades de minuto y decenas de minuto, también con las unidades de
hora y decenas de hora, considerando que sólo se debe contar hasta 24
horas.

6. Al oprimirse en cualquier momento el botón 1 se ingresa al Modo de


Ajuste. Para ajustar los minutos al valor deseado se aplasta el botón 2 y
así se irán incrementando de uno en uno. Cuando ya se haya ajustado
al minuto deseado y hacer que siga contando (a partir del minuto
ajustado) se aplasta el 3er. botón que sirve para salir de modo de ajuste.
5.- Listado del programa fuente en lenguaje ensamblador con
comentarios en las líneas de código que considere
fundamentales

;*********************************************************************
; RELOJ BINARIO CON MINUTOS AJUSTABLES Y TONOS AUDIBLES
; USANDO EL TMR0 COMO BASE DE TIEMPO DE 10ms (10x100)
;*********************************************************************
; NOMBRE: clock_final.asm
; FECHA: 06/dic/2011
; VERSION: 1.00
; PROGRAMADOR: Oscar Veloz
;*********************************************************************
; DESCRIPCION:
;RELOJ BINARIO donde en un mismo puerto están las unidades y decenas de
;segundos, asi como para los minutos en otro puerto, y horas en otro puerto.

; Comentario:
;Una vez ingresado al modo de ajuste, en el 99.9999% del tiempo de vida
;real que percibimos transcurrir como personas, el micro se encuentra
;ejecutando las instrucciones de la etiqueta esperando_aplaste_boton_ajuste
;o sino en la de esperando_suelte_boton_ajuste. Por esa razón es que coloco
;en esa etiqueta la instrucción goto siga_contando (validándola antes),
;para que sea posible SALIR del modo de ajuste (con botón del pin RB2).
;*********************************************************************
;DIRECTIVAS

LIST P=16F887
#include <p16F887.inc>

ERRORLEVEL -302, -306

__CONFIG _CONFIG1, _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF &
_MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
__CONFIG _CONFIG2, _WRT_OFF & _BOR21V
;advertencia por cambio
;bancos
CBLOCK 0X020
contador ;Cuenta 100 interrupciones
seg_unidades
seg_decenas
min_unidades
min_decenas
hora_unidades
hora_decenas
set_min_decenas
set_min_unidades
aux_seg
aux_min
aux_hora

ENDC
;*********************************************************************
;PROGRAMA
ORG 0x00 ;Vector de RESET
GOTO MAIN
ORG 0x04 ;Vector de interrupción
GOTO Interrupcion ;Va a rutina de interrupción

;DURANTE LA INTERRUPCION SE CUENTAN 100 INTERRUPCIONES


;PARA COMPLETAR 10x100=1000ms.
Interrupcion

btfss PORTA,0
goto modo_ajuste
goto siga_contando

;--INICIO MODO DE AJUSTE-- AQUÍ SE AJUSTA CON BOTÓN EN PIN PORTB,1


modo_ajuste
clrf PORTB
clrf PORTC
clrf PORTD
CLRF set_min_unidades
CLRF set_min_decenas
BSF PORTE,0
goto esperando_aplaste_boton_ajuste

esperando_aplaste_boton_ajuste
btfss PORTA,2 ;pregunta si se aplastó botón de salir del modo ajuste
goto siga_contando ;para salir del modo de ajuste
btfsc PORTA,1
goto esperando_aplaste_boton_ajuste ;aún no aplasto
BSF PORTE,1
BSF PORTE,2
goto esperando_suelte_boton_ajuste ;ya aplasté

esperando_suelte_boton_ajuste
btfss PORTA,1
goto esperando_suelte_boton_ajuste ;aún no suelto
BCF PORTE,1
BCF PORTE,2
goto setting ;ya solté

setting
incf set_min_unidades,f
movlw .10
subwf set_min_unidades,w
btfss STATUS,2
goto mostrar_seteo
clrf set_min_unidades

incf set_min_decenas
movlw .6
subwf set_min_decenas,w
btfss STATUS,2
goto mostrar_seteo
clrf set_min_decenas

mostrar_seteo
clrf aux_min
bcf STATUS,0
rlf set_min_decenas,w
movwf aux_min
swapf set_min_unidades,w
iorwf aux_min,w
movwf PORTC

;traspaso de mi ajuste deseado a los registros reales del reloj


movf set_min_unidades,w
movwf min_unidades
movf set_min_decenas,w
movwf min_decenas
;fin del traspaso de mi ajuste deseado

goto esperando_aplaste_boton_ajuste ;aún no aplasto botón de salir

;--FIN MODO DE AJUSTE--

siga_contando

BCF PORTE,0 ; ese led sólo debe estar prendido durante el modo
ajuste
;asignación a los puertos
clrf aux_seg
bcf STATUS,0
rlf seg_decenas,w
movwf aux_seg
swapf seg_unidades,w
iorwf aux_seg,w
movwf PORTB

clrf aux_min
bcf STATUS,0
rlf min_decenas,w
movwf aux_min
swapf min_unidades,w
iorwf aux_min,w
movwf PORTC

clrf aux_hora
bcf STATUS,0
rlf hora_decenas,w
movwf aux_hora
bcf STATUS,0
rlf aux_hora,f ;sólo para horas roto dos veces
swapf hora_unidades,w
iorwf aux_hora,w
movwf PORTD

decfsz contador,f ;Cuenta espacios de 10ms


goto Seguir ;Aún no son 100 interrupciones

;segundos
incf seg_unidades,f ;Ahora sí 10x100=1000ms=1seg
movlw .10
subwf seg_unidades,w
btfss STATUS,2
goto cont
clrf seg_unidades

incf seg_decenas
movlw .6
subwf seg_decenas,w
btfss STATUS,2
goto cont
clrf seg_decenas

;minutos
incf min_unidades,f
movlw .10
subwf min_unidades,w
btfss STATUS,2
goto cont
clrf min_unidades

incf min_decenas
movlw .6
subwf min_decenas,w
btfss STATUS,2
goto cont
clrf min_decenas

;hora
incf hora_unidades,f
movlw .2
subwf hora_decenas,w
btfsc STATUS,2
goto son_mas_de_20_horas

movlw .10
subwf hora_unidades,w
btfss STATUS,2
goto cont
clrf hora_unidades
incf hora_decenas,f
goto cont

son_mas_de_20_horas
movlw .4
subwf hora_unidades,w
btfss STATUS,2
goto cont
clrf hora_unidades
clrf hora_decenas
goto cont

cont ; sirve para generar 1s de retardo lo cual equivale a la ejecución de 100


; interrupciones
movlw .1
movwf contador ;Precarga contador con 100
; OJO aquí no retorno a la interrupción, x eso no pongo retfie como
; en la etiqueta Seguir. Luego de ejecutar toda la etiqueta cont vuelve a ejecutar toda
; la etiqueta Interrupcion desde su primera instrucción.

Seguir
bcf INTCON,T0IF ;Repone flag del TMR0
movlw .217
movwf TMR0 ;Repone el TMR0 con ~.39
retfie ;Retorno de interrupción

MAIN
;SETEO DE PUERTOS
BANKSEL ANSEL
CLRF ANSEL
CLRF ANSELH
BANKSEL TRISB ;Selecciona el Bank1
CLRF TRISA
COMF TRISA,f ;PORTA es el único configurado como entrada
CLRF TRISB ;PORTB configurado como salida
CLRF TRISC ;PORTC configurado como salida
CLRF TRISD
CLRF TRISE

;INICIALIZACION
BANKSEL PORTB ;Selecciona el Bank0
MOVLW 0XFF ;inicialmente y normalmente están en nivel
MOVWF PORTA ;alto los pines de PORTA a menos que se presionen los botones
CLRF PORTB ;Borra latch de salida de PORTB
CLRF PORTC ;Borra latch de salida de PORTC
CLRF PORTD
CLRF PORTE
CLRF seg_unidades
CLRF seg_decenas
CLRF min_unidades
CLRF min_decenas
CLRF hora_unidades
CLRF hora_decenas
clrf set_min_decenas
clrf set_min_unidades
clrf aux_seg
clrf aux_min
clrf aux_hora

;El valor calculado para cargar en TMR0 es de 217 con un


;preescaler de 256 y a una frecuencia de 4MHz, para obtener
;una interrupción cada 10mS. Cálculo al final del ejercicio.

;PROGRAMACION DEL TMR0


banksel OPTION_REG
movlw b'00000111' ;TMR0 como temporizador
movwf OPTION_REG ;con preescaler de 256
BANKSEL TMR0
movlw .217 ;Valor decimal 217
movwf TMR0 ;Carga el TMR0 con 217

;PROGRAMACION DE INTERRUPCION
movlw b'10100000'
movwf INTCON ;Activa la interrupción del TMR0
movlw .100 ;Cantidad de interrupciones a contar
movwf contador ;Nº de veces a repetir la interrupción

Loop
nop
goto Loop

END ; Fin del programa fuente

;CALCULO DEL VALOR A CARGAR EN TMR0 A 4MHz


;PARA OBTENER TEMPORIZACION DE 10 MILISEGUNDOS
;CON PREESCALADOR DE 1:256
;Temporización=(4Tosc)(256-ValorTMR0)(preescalador)
;0.010=(4Tosc)(256-ValorTMR0)(256)
;ValorTMR0=217
6.- Copia impresa del circuito armado en PROTEUS para la
simulación en el momento de su ejecución

Fig 1. Reloj en Modo Normal contando

En esta Fig 1 se muestra el reloj andando normalmente. Marca las


14h32’43’’ , teniendo en cuenta que para los 3 grupos de leds que
existen: horas, minutos y segundos (nombrados de izquierda a derecha);
la columna de la izquierda es para las decenas y la de la derecha es
para las unidades.

Fig 2. Reloj en Modo de Ajuste


Cuando se presiona el 1er botón se logra entrar a Modo de Ajuste. En este
modo se puede ajustar los minutos al valor deseado. En la Fig 2 se ve cómo al
instante se han ajustado 15 minutos, lo cual se hace aplastando el 2do botón.
Se sale del Modo de Ajuste con el 3er botón, así inmediatamente regresará al
Modo Normal contando con la hora y segundos con que estaba hasta antes de
ingresar al Modo de Ajuste, pero con los minutos establecidos por el ajuste.

7.- Conclusiones

 En el bloque de interrupción es donde coloqué las transiciones de


variables de unidades, decenas, mostré por los puertos las salidas, fue
en la interrupción donde programé casi todo. Ya que casi el 100% de
todo el tiempo se halla el micro ejecutando las interrupciones (las cuales
tiene que ejecutar 100 interrupciones para NOSOTROS VER un
cambio).
 Se puede aumentar la velocidad del reloj de tres maneras, la primera es
aumentando la frecuencia del oscilador (ahora está en 4MHz), la
segunda es variando el valor que se le asigna al TMR0 (el cual recibe un
valor de 217 cada vez que desborda), y la tercera es disminuyendo el
valor de la variable contador que lleva la cuenta del número de
interrupciones ejecutadas (ahora está en contador=100).

 Es necesario validar que el reloj no exceda los 59 segundos, 59 minutos


y 24 horas.

 Es necesario para este diseño de placa hacer una ligera manipulación


de bits, para que sean mostrada la hora por los pines donde están ya
puestos los leds. Esta manipulación de bits consiste en hacer un
desplazamiento del registro de decenas porque como se ve en el diseño
de placa no existen leds en ciertos pines. En el caso de decenas de
horas fue necesario 2 desplazamientos.

8.- Recomendaciones

 No aplastar al mismo tiempo los botones. En especial no aplastar al


mismo tiempo el botón para Entrar al Modo de Ajuste y de Salir de Modo
de Ajuste simultáneamente, porque si bien es cierto el botón de Entrar
tiene mayor prioridad, se prenderán impredeciblemente.

 Es preferible usar más variables temporales de las necesarias, cuando


son programas muy extensos, para evitar errores de programación,
porque podemos hacer asignaciones inadecuadas al manipular las
variables importantes y perder los valores que llevaban éstas. Entonces
las variables temporales serán usadas y luego borradas, evitándonos
riesgos.
 Este reloj binario es fácil porque muestra las unidades de segundos en
el puerto B y decenas de segundos en el puerto D. Cuando sea
necesario mostrar unidades y decenas en un mismo puerto (4 primeros
bits para unidades y los otros 4 para decenas) será más difícil. Por eso
recomiendo ahí usar instrucciones como swapf, iorfw, rlf, rrf, para
manipular los bits y así cambiarlos de posición a su gusto.

You might also like