Anda di halaman 1dari 16

MICROPROCESADORES II

Practica 2do Parcial


EJERCICIO 1: Teclado matricial y LCD de caracteres: reloj de ajedrez
Planteamiento del diseo:
Basndose en el empleo de un microcontrolador PIC16F877 se desea
realizar un reloj digital para el desarrollo de partidas de ajedrez
Dicho reloj deber mostrar el tiempo de partida restante para la realizacin
de jugadas tanto para el jugador que lleva las piezas blancas (BL) como
para el que conduce las negras (NG), y todo ello con una precisin que
permita mostrar hasta las dcimas de segundo.
La informacin aparecer en un display de cuarzo lquido (LCD) de 2
filas y 16 caracteres visibles por fila, este LCD es compatible con el
HD44780U de Hitachi.
Para establecer la configuracin de tiempo para cada jugador (editar dicho
tiempo al principio), iniciar la partida, pararla y jugar existe un teclado
matricial de 4 filas x 4 columnas cuyas teclas aparecen en la figura 2.
Funcionamiento esperado (Especificaciones):
Inicialmente cuando se alimenta o resetea el equipo, aparecen ambos
relojes parados y mostrando un tiempo restante de 5 minutos para cada uno
de los jugadores.
En ese estado, es posible modificar los tiempos de cada jugador mediante
las teclas numricas y las flechas de desplazamiento a derecha e izquierda
presentes en el teclado. La posicin del nmero que se pueda editar en cada
momento deber aparecer resaltado de alguna manera (mediante el
parpadeo del mismo o la presencia de un cursor debajo de esa posicin).
Durante la edicin, para saltar de una lnea a otra del LCD, se utilizan las
teclas B (edicin del tiempo del jugador de blancas) y N (para la edicin del
tiempo del jugador de negras).
Para iniciar el juego, se acta sobre la tecla de inicio (I) y empezar a
descontar el tiempo del jugador al que le corresponde hacer el movimiento.
Durante el tiempo de juego, no resulta posible editar los tiempos de los
jugadores.
Una marca (<) a la derecha del tiempo de uno de ellos indicar siempre a
quin le corresponde realizar la jugada. En el transcurso de la partida, cada
jugador realizar el movimiento cuando le toque y a continuacin actuar
sobre la tecla que corresponda al color de sus piezas (B N) para activar el
reloj del adversario que deber proceder tambin de idntica manera.
Cuando el tiempo de un jugador llegue a cero, aparecer un asterisco a la
izquierda de su tiempo y sonar una alarma (mediante el zumbador
piezoelctrico presente en la PICDEM2 plus) durante 2 segundos que
advertir de tal circunstancia.
Durante el desarrollo de una partida, se puede actuar sobre la tecla de
parada (P), en cuyo caso se detendr el reloj del jugador al que le
corresponda mover. En ese estado, si se pulsa por segunda vez esa tecla,
se vuelve a los tiempos de configuracin inicial establecidos para la partida
en curso. En cualquiera de los dos estados, s que resultara posible editar
los tiempos restantes para cada jugador.

El microcontrolador PIC16F877 emplea un reloj de frecuencia 4 MHz,


dispone de la alimentacin y de la circuitera necesaria para su
funcionamiento adems de las conexiones de los distintos elementos, que
son las que aparecen en la figura 1.
En estas condiciones se pide:
a) Explique cmo sera el proceso global que se pretende implementar en el
microcontrolador con los diversos bloques internos que se van a utilizar
b) Desglose en pseudo-cdigo o similar el proceso anteriormente referido
c) Realice el paso al cdigo fuente y verifique el resto de los pasos
necesarios para conseguir el funcionamiento de dicho cdigo en la tarjeta
de aplicacin hardware disponible.

EJERCICIO 2: Convertidor A/D: realizacin de un voltmetro digital


Realizar un programa que se encargue de medir continuamente una tensin
analgica comprendida entre 0 y 5V y mostrar su valor en voltios, en 3
displays de 7 segmentos de nodo comn (con segmento adicional de punto
decimal). La medida se realizar mediante un canal de entrada del mdulo
de conversin Analgico a Digital de un microcontrolador PIC16F877 ( en
su versin PIC16F877A) que dispone de un oscilador de 4MHz.
La tensin se introduce en la entrada analgica 0 del PORTA (RA0) que se
puede variar mediante un potencimetro. Para conseguir la visualizacin en
los displays, a la placa de entrenamiento se le aade una placa de circuito
impreso mediante un conector vertical, esta placa responde al esquema
elctrico que se adjunta en la figura 2 (es la que se ha usado en prcticas
anteriores).

Figura 1.- Elementos a utilizar para la prctica

Un posible planteamiento:
Se utiliza el mdulo A/D para realizar la conversin de la entrada de tensin
del canal analgico 0.
Se configura el mdulo A/D para que utilice el reloj basado en la red RC
interna independiente del oscilador del microcontrolador (valor nominal de
Tad de 4s y con una variacin posible entre 2s y 6s). Se lanza la
conversin con el canal seleccionado y se activa la generacin de
interrupciones cuando finalice dicha conversin.
El mdulo A/D puede proporcionar el resultado con una resolucin de 10 bits
(de b9 a b0) en dos registros: ADRESH y ADRESL, pudiendo realizarse la
justificacin del resultado a la izquierda, con este resultado:

o bien con justificacin a la derecha y con este otro formato:

Dado que la precisin de 8 bits resulta suficiente, configuraremos el


resultado con justificacin a la izquierda y tomaremos el resultado
proporcionado en los 8 bits del registro ADRESH, despreciando los dos bits
menos significativos de la conversin presentes en ADRESL.
En el programa de tratamiento de la interrupcin se recoge el valor
resultante de la conversin en el registro ADRESH de 8 bits y se convierte el
valor a su equivalente de tensin en voltios. Como la tensin de referencia
es de 5V, la resolucin del convertidor empleando 8 bits es de
5V/256 = 0,0195V/bit (195E-4 V). Realizando el producto (subprograma
que se desarrollar posteriormente) del valor resultante por 195
obtendremos un valor de tensin analgica comprendida entre 0 y 49725
diezmilsimas de voltio (0 y 49725*10-4 V). Empleando las diezmilsimas
de voltio como unidad de medida, se puede almacenar el valor en binario en
dos bytes y lo podemos descomponer en sus 5 dgitos BCD (con un

subprograma que se detallar posteriormente) para la representacin en


los displays, nicamente de los 3 dgitos ms significativos (voltios,
dcimas y centsimas).
El programa principal ejecutar un bucle continuo de barrido de los 3
displays que representan los voltios con dos decimales, se asegura la
permanencia de cada dgito durante 5ms mediante una temporizacin
realizada con el mdulo TMR0.
El bucle de barrido recoger los valores a mostrar de unas posiciones
denominadas BCD2 y BCD1 que sern cargadas mediante el subprograma
que realiza la conversin del dato binario de 16 bits que representa las
diezmilsimas de voltio a BCD:

Estas posiciones sern modificadas por tanto tras la conversin del


resultado digital en el programa de tratamiento de interrupcin.
Nos debemos asegurar que hayan transcurrido 2Tad (8s) y el tiempo de
adquisicin antes de lanzar la nueva conversin (el propio programa de
tratamiento lo asegura), pondremos a cero el flag de indicacin de fin de
conversin (ADIF) y arrancaremos una nueva conversin antes de retornar
del programa de tratamiento.
Detalle del Subprograma que realiza la multiplicacin de dos
bytes (PRODUCTO_2)
Realiza el producto de los 8 bits contenidos en FACTOR1 por los 8 bits
almacenados en la posicin FACTOR2 y el resultado en conjunto, va a parar
a dos posiciones denominadas: BIN_ALTO + BIN_BAJO
FACTOR2 = b7 b6 b5 b4 b3 b2 b1 b0
FACTOR1 = a7 a6 a5 a4 a3 a2 a1 a0
Operacin a realizar para la multiplicacin en binario:
Resultado = FACTOR1 * FACTOR2 = b0 * FACTOR1 + b1 * (2 * FACTOR1) +
+ b2 * (2 * (2 * FACTOR1)) + ...+ b7 * (2*(2*(2*(2*(2*(2*(2*FACTOR1)))))))
Cada multiplicacin por 2 en binario consiste en realizar un desplazamiento
a la izquierda introduciendo un cero por la derecha, tras cada
desplazamiento se realiza la suma o no en funcin del bit b correspondiente
a FACTOR2
La operacin total a realizar desde dentro hacia fuera sera:

Para realizar estas operaciones que se irn acumulando, debemos operar


con los bytes BIN_ALTO y BIN_BAJO en conjunto:
BIN_ALT
BIN_BAJ
O
O
Las sucesivas multiplicaciones por 2 de FACTOR1 se almacenan en dos
bytes encadenados que se denominan SUMA_ALTO (parte alta a sumar) &
SUMA_BAJO (parte baja a sumar):
SUMA_BAJ
O

SUMA_ALT
O
Subprograma de conversin de Binario a BCD (BINBCD)
Se puede utilizar cualquiera de los ejemplos de conversin de Binario a BCD
que estn disponible.
Algoritmo desarrollado:
INICIALIZACIN
CONVERTIDOR A/D:
-Entrada RA0 como analgica y referencia de 5V, resto entradas digitales. El
resultado de la conversin lo recogeremos ajustado a la izquierda (los 8 bits
ms significativos en el registro ADRESH)
-Reloj de conversin Tad basado en red RC interna (4s)
-Canal analgico de entrada: canal 0.
PUERTOS:
-PORTA (RA1, RA2 y RA3 con salidas para activacin de los displays, resto
de las lneas como entradas).
-PORTD (salida para control de los segmentos)
TMR0: definido en modo temporizador y con prescaler de 32 para
temporizar posteriormente 5 ms.

INTERRUPCIONES: habilitar las de fin de conversin A/D con la mscara


particular ADIE en PIE1, mscara de perifricos PEIE y global GIE en registro
INTCON. Se borra a su vez el flan ADIF del registro PIR1.
Inicializamos variables BCD2 y BCD1 (valores a mostrar en los displays)
hasta que se acabe la primera conversin
Se lanza la primera conversin A/D poniendo el bit GO a 1 (en el registro
ADCON0)
BUCLE DE BARRIDO DE LOS DISPLAYS
Centsimas de voltio:
Activacin del display poniendo la combinacin de entrada adecuada en el
PORTA
Extraemos el valor de la parte baja de BCD1
Bsqueda en la tabla de los led a iluminar y los sacamos al PORTD
(Subprograma TABLALED)
Espera durante 5 ms (llamada a Subprograma ESPERA)
Tiempo muerto: apagamos todos los segmentos
Dcimas de voltio: dem extrayendo los 4 bits altos de BCD1
Unidades de voltio: dem extrayendo los 4 bits bajos de BCD2. Adems, para
las unidades de voltio se activa el punto decimal del display para marcar la
separacin (RD7 se pone a 0)
Se vuelve al inicio del bucle de barrido de los displays
SUBPROGRAMA ESPERA
Se precarga TMR0 con un valor de 100 para conseguir desbordamiento al
cabo de 5 ms:
5ms 4/4MHz * 32 * (256-100)
Se pone a 0 el flag T0IF
Nos situamos en un bucle de espera hasta que T0IF se ponga a 1
Retornamos del subprograma
PROGRAMA DE TRATAMIENTO DE LA INTERRUPCIN
Comprobamos que el flag ADIF est a 1 (fin de conversin A/D)
Se salva el contexto del programa principal (W, STATUS y PCLATH)
Tomamos el resultado de la conversin en ADRESH
Lo cargamos en la posicin FACTOR1
Cargamos 195 en FACTOR2
Llamamos a subprograma PRODUCTO_2 para realizar la multiplicacin
de FACTOR1 por FACTOR2
Se recoge el resultado en dos bytes (BIN_ALTO BIN_BAJO) y se
descompone en sus 5 dgitos decimales con el subprograma BINBCD
Finalizamos el programa de tratamiento poniendo a 0 el flag ADIF
Recuperamos el contexto (PCLATH, STATUS y W)
Lanzamos una nueva conversin poniendo de nuevo GO a 1

Subprograma PRODUCTO_2
Realiza el producto de los 8 bits contenidos en FACTOR1 por los 8 bits
almacenados en la posicin FACTOR2 y el resultado en conjunto, va a parar
a dos posiciones denominadas: BIN_ALTO + BIN_BAJO (vase detalle del
algoritmo en el planteamiento inicial)
;
;
;
;
;
;
;

Subprograma que realiza el producto de dos bytes FACTOR1 y FACTOR2 y el resultado


lo almacena en dos posiciones denominadas: BIN_ALTO y BIN_BAJO
Para probarlo, cargar en FACTOR1 y FACTOR2 unos valores
y llamar al subprograma
LIST p=16F877
include "p16f877.inc"

;Fichero de inclusin

CBLOCK 0x20
FACTOR1, FACTOR2
SUMA_ALTO, SUMA_BAJO
BIN_ALTO,BIN_BAJO
CONTADOR

;Posiciones donde se guardan los datos de entrada


;Posiciones para ir cargando FACTOR1 desplazado
;Definicin posiciones del dato
;Contador de desplazamientos

ENDC
; Esta parte de cdigo slo llama al subprograma y se queda esperando en un bucle infinito
; hasta que detengamos el programa desde el entorno MPLAB para comprobar el resultado que
; se obtiene en BIN_ALTO y BIN_BAJO

ESPERA

ORG
CALL
GOTO

0
PRODUCTO_2
ESPERA

;Inicio del subprograma


ORG
0x120
;***************************************************************************
; Subprograma de multiplicacin de dos bytes
;
; Recibe los valores en posiciones FACTOR1 y FACTOR2
; y entrega el resultado en dos bytes: BIN_ALTO & BIN_BAJO
;***************************************************************************
PRODUCTO_2
clrf
SUMA_ALTO
;Ponemos a cero parte alta del sumando
clrf
BIN_ALTO ;Ponemos a cero el acumulador de
clrf
BIN_BAJO ;los resultados
movlw
0x08
;Cargamos 8 en el contador de operaciones
movwf
CONTADOR ;de rotacin
movf
movwf
A_SUMAR rrf
btfss
goto
movf
addwf

OTRO_BIT

btfsc
incf
movf
addwf
decfsz
goto
return

A_ROTAR bcf
rlf
rlf
goto

FACTOR1,W
SUMA_BAJO

;Cargamos FACTOR1 en la parte baja de sumando


;para efectuar rotaciones

FACTOR2
;Rotamos a la derecha para comprobar
STATUS,C ;en el carry el bit que "toque"
OTRO_BIT ;si el carry qued a 0 es que no hay que sumar
SUMA_BAJO,W
;si qued a 1 es que hay que sumar
BIN_BAJO,F
;la parte baja del acumulador con el sumando
;que corresponde al FACTOR1 desplazado a la izq.
STATUS,C ;comprobamos si hubo acarreo en esa suma
BIN_ALTO ;si hubo, sumamos 1 al siguiente byte
SUMA_ALTO,W
;sumamos la parte alta del acumulador con
BIN_ALTO,F
;el FACTOR1 desplazado
CONTADOR,F
A_ROTAR

;Decrementamos el contador de operaciones parciales


;si no hemos llegado a cero, seguimos rotando
;si ya hemos hecho 8 veces la operacin, retorno

STATUS,C ;Para rotar FACTOR1 a la izquierda, ponemos a 0 el carry


SUMA_BAJO,F
;rotamos encadenando la parte baja
SUMA_ALTO,F
;con la parte alta
A_SUMAR
;y vamos a comprobar si es necesario sumar o no

END

Subprograma BINBCD
Se encarga de tomar los 16 bits almacenados en las posiciones BIN_ALTO y
BIN_BAJO y devuelve los 5 dgitos BCD correspondientes a la representacin
decimal de ese valor que almacena en 3 posiciones de RAM:

;
;
;
;
;
;
;
;
;

Programa que realiza la conversin de un dato binario de 16 bits a un


formato BCD almacenndolo en 5 dgitos que ocupan medio byte cada uno
El dato binario est almacenado en dos bytes contiguos: BIN_ALTO y BIN_BAJO
y el resultado va a parar a 3 bytes tambin consecutivos que son de mayor
a menor peso: BCD2, BCD1 y BCD0
Estos almacenan los 5 dgitos, estando presente en los 4 bits ms bajos de
BCD2 nicamente el dgito ms significativo

; Esta versin realiza sucesivas restas por diez mil, mil, cien y diez
; hasta que el resultado sea inferior a estos valores para ir obteniendo
; los sucesivos dgitos decimales
;
; Posiciones Auxiliares:
CBLOCK 0x20
MINU_ALTO
MINU_BAJO
SUSTRA_ALTO
SUSTRA_BAJO
RESTO_ALTO
RESTO_BAJO
AUXILIAR
BIN_ALTO
BIN_BAJO
BCD2, BCD1, BCD0
ENDC
list p=16f877
include "p16f877.inc"

;Microcontrolador PIC16f877
;Fichero de inclusin

ORG

CALL
GOTO

BIN16BCDv2
ESPERA

;Llamamos al subprograma
;y nos quedamos esperando a la vuelta

ORG
BIN16BCDv2
clrf
clrf
clrf

0x100

;Coloco el subprograma a partir de la 0x100

BCD2
BCD1
BCD0

;Pongo a cero
;las posiciones finales
;donde irn a parar los dgitos decimales

DEC_MIL movf
movwf
movf
movwf

BIN_ALTO,W
MINU_ALTO
BIN_BAJO,W
MINU_BAJO

;Empezamos cargando el nmero de partida


;en el minuendo en su parte alta
;y en su parte baja

0x27
SUSTRA_ALTO
0x10
SUSTRA_BAJO

;Cargamos d'10000' en el sustraendo


;descompuesto en dos bytes= 0x2710
;de la parte alta y la parte baja

ESPERA

movlw
movwf
movlw
movwf
RESTADM call
btfss
goto
incf
movf
movwf
movf
movwf
goto

RESTA16
;Llamamos al subprograma que hace la resta de dos bytes
STATUS,C ;Si carry queda a 1 es que el resultado es >= 0
UN_MIL
;si no, vamos a obtener las unidades de mil
BCD2
;si era positivo incrementamos decenas de mil y seguimos
RESTO_ALTO,W
;Paso el resultado al minuendo
MINU_ALTO
;en su parte alta
RESTO_BAJO,W
;y tambin en su parte baja
MINU_BAJO
RESTADM
;Volvemos a restar ya que el resultado es mayor de d'10000'

UN_MIL

0x03
SUSTRA_ALTO
0xE8
SUSTRA_BAJO

movlw
movwf
movlw
movwf

RESTAUM call
btfss
goto
movlw
addwf
movf
movwf
movf
movwf
goto

;Cargamos ahora mil en el sustraendo


;que cabe en dos bytes de parte alta
;y parte baja

RESTA16
;Llamamos al subprograma de resta de dos bytes
STATUS,C ;Si carry queda a 1 es que el resultado es >= 0
CENTENAS ;si no, vamos a las CENTENAS
0x10
;si era positivo incrementamos unidades de mil y seguimos
BCD1
RESTO_ALTO,W
;Cargo el resultado en el minuendo para repetir la resta
MINU_ALTO
RESTO_BAJO,W
MINU_BAJO
RESTAUM
;Volvemos a restar porque el resultado es mayor que d'1000'

CENTENAS
clrf
movlw
movwf

;Vamos a obtener las centenas


SUSTRA_ALTO
;Cargamos d'100'=0x0064 en el sustraendo
0x64
SUSTRA_BAJO

RESTACN call
btfss
goto
incf
movf
movwf
movf
movwf
goto

RESTA16
;Resta de dos bytes de nuevo
STATUS,C ;Si carry queda a 1 es que el resultado es >= 0
DECENAS
;si no, vamos a las DECENAS
BCD1
;si era positivo incrementamos centenas y seguimos
RESTO_ALTO,W
;Cargamos el resultado en el minuendo para otra resta
MINU_ALTO
RESTO_BAJO,W
MINU_BAJO
RESTACN
;Repetimos por ser el resultado mayor que d'100'

DECENAS movlw
subwf

0x0A
MINU_BAJO,W

btfss
goto
movwf
movlw
addwf
goto

;Cargamos diez en el sustraendo


;Y se lo restamos al minuendo, al ser ahora menor
;que d'100', cabe en un byte
STATUS,C ;Si carry queda a 1 es que el resultado es >= 0
FINAL
;si no, acabamos y vamos con las UNIDADES
MINU_BAJO
;Cargamos el resultado en el minuendo
0x10
;Incrementamos las decenas
BCD0
;si era positivo y seguimos
DECENAS

FINAL

movf
MINU_BAJO,W
;Lo que qued son ya unidades
addwf
BCD0,F
;que situamos en BCD0
return
;***************************************************************************************
; Subprograma que realiza la resta en 16 bits:
; Resta minuendo(16 bits) menos sustraendo(16 bits) y el resultado va al resto (16 bits)
;
(MINU_ALTO & MINU_BAJO)-(SUSTRA_ALTO & SUSTRA_BAJO) -> (RESTO_ALTO & RESTO_BAJO)
;***************************************************************************************
RESTA16 MOVF
SUSTRA_ALTO,W
;Cargamos parte alta del SUSTRAENDO en posicin AUXILIAR
MOVWF
AUXILIAR
MOVF
SUSTRA_BAJO,W
;Cargo la parte baja del sustraendo en W
SUBWF
MINU_BAJO,W
;y hago la resta de parte baja
BTFSS
STATUS,C ;observo cmo qued el Carry
INCF
AUXILIAR ;Si qued a 0 es que "debo" una a la parte
;alta del minuendo y corrijo sumando 1 a la parte alta
;del sustraendo
MOVWF
RESTO_BAJO
;Guardo la parte baja del resultado
MOVF
SUBWF

AUXILIAR,W
MINU_ALTO,W

;Cargo la parte alta del sustraendo en W


;y hago la resta de parte alta

MOVWF
RESTO_ALTO
;El resultado lo guardo en la parte alta del resto
RETURN
;********************************************************************************
END

EJERCICIO 3: Interface con Pantallas de Cristal Lquido (LCD) de


Caracteres Representacin del tiempo para un cronmetro digital
Se trata de realizar el diseo del programa encargado de realizar el
interface con una pantalla de cristal lquido del tipo matriz de puntos
que dispone de un driver HD44780 o compatible para implementar un
cronmetro digital que dispone de pulsadores de MARCHA y PARADA. En
caso de que ambos pulsadores se encuentren activados, debe prevalecer el
pulsador de MARCHA sobre el de PARADA. Si estando el cronmetro parado,
se acta por segunda vez sobre el pulsador de PARADA, se resetear la
cuenta de tiempo (se pondr a cero).

El crono representar en la primera lnea de la pantalla del LCD


Horas:Minutos:Segundos.Dcimas de Segundo y ser posible completar
hasta 24 horas de cuenta. Si se llegaran a completar las 24 horas, el crono
se reseteara y se parara. En la segunda lnea del LCD aparecer el estado
del cronmetro, con uno de los siguientes mensajes: Crono contando o
Crono Parado segn proceda. El diseo se basa en el empleo de un
microcontrolador PIC16F877 con un oscilador de 4MHz. El interface se
realizar con las 4 lneas ms altas de datos del LCD: DB7, DB6, DB5 y DB4
y las 3 lneas de control E, RS y R/W, segn se muestra en la figura.
Se facilitan tambin los ficheros que incluyen los subprogramas para
interface con el LCD.

Las CONEXIONES de entradas y salidas al microcontrolador podran ser las


siguientes:

A continuacin se adjunta un posible algoritmo para el programa


correspondiente a la solucin propuesta.
Un posible planteamiento
El programa principal consiste en un bucle donde se exploran
permanentemente el estado de los pulsadores de MARCHA y de PARADA, si
alguno de ellos est activado
Se utiliza TMR1 y el mdulo CCP1 en modo comparacin con evento
especial de disparo para realizar temporizaciones de 0,1 s mediante la
sucesiva generacin de interrupciones. Con cada interrupcin se modifican
las posiciones que almacenan Dcimas, Segundos, Minutos y Horas en BCD
y se envan al LCD como caracteres a representar. Al LCD slo se envan los
caracteres cuando se necesita cambiar la representacin y se envan todos,
aunque tambin podra ser posible situar el puntero de direcciones de la
DDRAM del LCD y enviar slo los que cambian.

El temporizador TMR1 se configurar en modo temporizador con un


prescaler de 8 y ser reseteado por el mdulo CCP1 cuando alcance el valor
de 16 bits que se haya cargado entre los registros CCPR1H y CCPR1L
Los registros del mdulo CCP1 deben cargarse por tanto con un valor tal que
0,1 s = 4/4MHz * 8 * CCPR1H_CCPR1L
de donde CCPR1 = 12500 (0x30D4), luego CCPR1H = 0x30 y CCPR1L =
0xD4
Para el envo de caracteres y comandos al LCD se utilizan los subprogramas
presentes en el fichero s2_lcd4b_p2p.asm ya que en este caso el interface
se realiza con 4 bits y se emplean las 4 lneas ms bajas del puerto D. El
fichero necesario que contiene los subprogramas se incluye en el cdigo
fuente total mediante la correspondiente directiva include.
Se distinguen tres estados posibles en el funcionamiento del sistema, con
las transiciones que se indican con el estado de los pulsadores

Algoritmo utilizado:
INICIALIZACIN
Puertos: PORTD de entrada en sus 4 lneas altas e inicialmente de salida
en sus 4 lneas ms bajas para enviar datos y comandos al LCD, aunque
ser de entrada en algunos intervalos para leer estado del LCD (flag BF por
ejemplo)
PORTA ser de salida en 3 de sus bits (RA1, RA2 y RA3) para manejar las
lneas de control del LCD (RS,R/W y E), son salidas permanentemente. Resto
de lneas del PORTA de entrada
Definimos todas entradas como digitales en el PORTA . Aunque RA1, RA2 y
RA3 vayan a ser lneas de salida, se van a utilizar instrucciones del tipo BSF
y BCF sobre ellas. Estas instrucciones leen primero todo el puerto y
vuelven a sacar valores: modifican el bit al que afecta la instruccin y el
resto de los bits vuelven a salir con el valor que se ha ledo. Si estn activas
las entradas como analgicas, stas sern ledas siempre como ceros
(vase esquema del PORTA) y saldrn siempre como tales ceros en los bits
del PORTA no afectados por la instruccin

Resto de los Puertos como entradas


Reseteamos por software el LCD por si la alimentacin no cumple con los
valores requeridos para asegurar el reset inicial.
Inicializamos el LCD: datos de 4 bits, las 2 lneas del LCD activas, display
activo, sin cursor, limpiamos DDRAM e incremento en escritura y lectura del
LCD
CCP1 en modo comparacin con evento especial de disparo
Carga de CCPR1H con 0x30 y CCPR1L con 0xD4
TMR1: modo temporizador, prescaler de 8 y parado al principio
Puesta a cero de TMR1H y TMR1L
INTERRUPCIONES: habilitamos las del mdulo CCP1
Variables del algoritmo a cero: DECIMAS, SEGUNDOS, MINUTOS Y HORAS
Activamos interrupciones globales y de perifricos (GIE y PEIE)
Llamamos al subprograma encargado de enviar los caracteres ASCII de lo
que queremos sacar en el LCD (SACATIEMPO) al principio
Llamamos a un subprograma (MENSAJE) que enva a la lnea 2 del LCD un
mensaje que mostrara Crono Parado, que es el estado inicial.
Registramos en ANTES_B el estado previo del PORTB con el pulsador libre
BUCLE PRINCIPAL
Llamamos a subprograma que realiza una espera de 50ms para evitar
muestreos demasiado prximos en los pulsadores que haran que los
rebotes fueran considerados como nuevas pulsaciones (ESPERA_50ms)
Exploramos el estado de RA4 (pulsador de marcha):
Si est pulsado, RA4==0 entonces
Se pone en marcha TMR1
Se marca ANTES_B a 1 (como libre)
Volvemos al principio del bucle sin mirar el otro pulsador (es
prioritario el de marcha)
Exploramos el estado de RB0 (pulsador de parada):
Si est pulsado, RB0== 0 entonces
Se comprueba cmo estaba antes el pulsador (ANTES_B)
Si antes no estaba pulsado (ANTES_B.0==1) entonces
Si el crono estaba parado (TMR1ON==0) entonces
Reseteamos tiempo total (HORAS, MINUTOS,)
Mostramos el tiempo (SACATIEMPO)
Se saca el mensaje de la segunda lnea (Crono Parado)
Se para el temporizador TMR1: TMR1ON=0
Guardamos el valor actual del PORTB en ANTES_B para la prxima
deteccin de cambio en la pulsacin de RB0

Volvemos al principio del bucle principal


PROGRAMA DE TRATAMIENTO DE LA INTERRUPCIN DE CCP1
Se comprueba que el flag CCP1IF est a 1
Salvaguarda del contexto (W y STATUS, PCLATH no es necesario)
Incremento de DECIMAS
Si hemos llegado a 10, ponemos a 0 DECIMAS e incrementamos
SEGUNDOS si no, vamos directamente a la salida del programa de
tratamiento
Se incrementa SEGUNDOS en una unidad
Se extraen los 4 bits ms bajos (unidades)
Si unidades=0x0A entonces sumamos 6 a SEGUNDOS (para hacer el
ajuste a BCD) si no, vamos directamente a la salida del programa de
tratamiento
Se extraen los 4 bits ms altos de SEGUNDOS (decenas de segundo)
Si hemos llegado a 6 entonces se pone a cero SEGUNDOS y se
incrementan los minutos (MINUTOS) si no, vamos directamente a la salida
del programa de tratamiento
Se extraen los 4 bits ms bajos de MINUTOS (unidades de minuto)
Si unidades=0x0A entonces se suma 6 a MINUTOS (para hacer el ajuste a
BCD) si no, vamos directamente a la salida del programa de tratamiento
Se extraen los 4 bits ms altos de MINUTOS (decenas de minuto)
Si se ha llegado a 6 entonces ponemos a cero MINUTOS y se incrementan
las horas (HORAS) si no, vamos directamente a la salida del programa de
tratamiento
Se extraen los 4 bits ms bajos de HORAS (unidades de hora)
Si unidades=0x0A entonces se suma 6 a HORAS (para hacer el ajuste a
BCD)
Salida del programa de tratamiento:
Se comparan las HORAS con 24 si las hemos alcanzado:
Ponemos HORAS a cero, paramos TMR1 y mostramos en la segunda
lnea el mensaje:
Crono parado
si no las hemos alcanzado:
Mostramos en la segunda lnea el mensaje: Crono contando
Llamamos al Subprograma que saca el tiempo total para actualizar el LCD
Se pone el flag de CCP1 a cero (CCP1IF=0)
Recuperacin del contexto
Retorno de interrupcin
SUBPROGRAMA SACATIEMPO

Se encarga de tomar los valores almacenados en DECIMAS, SEGUNDOS,


MINUTOS Y HORAS y enviarlos al LCD en formato ASCII, se intercalan
tambin caracteres de separacin : (dos puntos) entre horas y minutos y
entre minutos y horas y . (punto) entre segundos y dcimas
Se coloca el cursor en casa (esquina superior izquierda)
Enviamos 3 espacios en blanco para centrar en pantalla
Extraemos decenas de horas, le aadimos el ASCII del cero y lo enviamos
al LCD con el subprograma LCDPUTCHAR
Lo mismo con las unidades de horas
Enviamos el ASCII de :
Envo del ASCII de las decenas de minutos
Envo del ASCII de las unidades de minutos
Enviamos el ASCII de :
Envo del ASCII de las decenas de segundos
Envo del ASCII de las unidades de segundos
Enviamos el ASCII de .
Envo del ASCII de las dcimas de segundo
Retorno de subprograma
SUBPROGRAMA ESPERA_50ms
Se precarga TMR0 con d60 para que desborde al cabo de 50ms con un
prescaler de 256: 50 ms = 1s * 256 * (256 60)
Se pone a cero el flag de TMR0: T0IF
Espera a que T0IF ==1
Retorno de subprograma
SUBPROGRAMA MENSAJE
Sita el contador de direcciones de la DDRAM del LCD al principio de la
segunda lnea y va enviando al LCD los caracteres almacenados en una de
las dos tablas alternativas almacenadas en la memoria de programa. El final
de las tiras de caracteres guardadas en las tablas se identifican mediante el
carcter especial _.
En funcin del valor almacenado en la posicin TIRA se recogen los
caracteres de la tabla que indica Crono parado (si TIRA==0) bien de la
que dice: Crono contando (si TIRA==1).
Para recoger los caracteres se incrementa un puntero, que se carga en W
antes de hacer la llamada a la tabla. Volvemos de la tabla trayendo en W l
correspondiente carcter.
Para almacenar la tira de caracteres se emplea la directiva DT que va
situando sucesivas instrucciones RETLW con el cdigo ASCII de cada uno.

Anda mungkin juga menyukai