Está en la página 1de 70

Los Puertos Paralelos de

Entrada/Salida

1
3. Los Puertos Paralelos de Entrada/Salida
Los integrados PIC16F874 y PIC16F877 poseen 5 puertos de entrada/salida denominados
PORTA, PORTB, PORTC, PORTD y PORTE, mientras que el PIC16F873 y PIC16F876 poseen 3.
Estos puertos son totalmente programables, es decir, sus pines pueden ser configurados
para trabajar como entradas o como salidas a seleccin del programador.
3.1. El Puerto A (PORTA)

3.1.1. Registros asociados al Puerto A

El puerto A posee 6 pines bidireccionales. Los 3 registros asociados a este puerto son:

1. Registro PORTA (05H), que es el registro de estado del Puerto A. Cada uno de los 6 bits
menos significativos (RA5,...,RA0) de este registro estn asociados al p i n fsico
correspondiente del puerto. Al hacer una lectura este registro se lee el estado de todas los pines
del puerto. Todas las escrituras al registro son operaciones del tipo lee- modifica-escribe, es
decir, toda escritura al puerto implica que el estado de los pines es ledo, luego es modificado y
posteriormente se escribe al latch de datos del puerto.

2. Registro TRISA (85H). Cada bit de este registro configura la direccin en que fluye la
informacin del pin correspondiente del puerto A, as, para k=0,1,...,5:

Bit k de TRISA = 1 configura el pin RAk del puerto A como Entrada


Bit k de TRISA = 0 configura el pin RAk del puerto A como Salida

Todos los pines del puerto A poseen diodos de proteccin conectados a Vdd (contra altos
voltajes de entrada) y a Vss (contra voltajes negativos) adems, manejan niveles de entrada tipo
TTL y como salidas se comportan como drivers tipo CMOS. Excepto el pin RA4, e l cual
como entrada posee un Disparador Schmitt trigger y como salida es de Drenaje abierto, adems
RA4 slo posee un diodo de proteccin conectado a Vss.

3. El Registro ADCON1 (9FH). Los pines RA0, RA1, RA2, RA3 y RA5 estn
multiplexados con las entradas analgicas AN0,...,AN4, respectivamente; de manera que
antes de utilizarlos se debe configurar si sern usadas como entradas analgicas o como
entradas/salidas digitales. Para seleccionar la segunda opcin (entradas/salidas digitales) se
debe colocar en el nible menos significativa de este registro un 01102 (es decir, un 06h).

2
Registro ADCON1 (direccin 9Fh)

A continuacin se indica el registro ADCON1:

U-0 U-0 R/W-0 U-0 R/W-0 R/W-0 R/W-0 R/W-0


ADFM --- --- --- PCFG3 PCFG2 PCFG1 PCFG0
Bit 7 Bit 0

bit 3-0: PCFG3:PCFG0: bits de configuracin de los canales de entrada del convertidor A/D.
Se utilizan para configurar las patillas como E/S digital o como entrada analgica.

En las siguientes dos figuras se muestra el detalle de implementacin interna de los pines del
puerto A, mostrando la diferencia entre los pines RA4 y los dems pines del puerto A:

Pines RA0, RA1, RA2, RA3 y RA5 Pines RA4

3.1.2. Estado de lectura y escritura de un pin de I/O

El PIC puede ser implementado en diversas topologas de estado de escritura para el pin de I/O,
teniendo en cuenta que los pines de los puertos E/S tienen igual comportamiento o ligeramente difiere
uno del otro. Conociendo el funcionamiento de diversos estados de escritura del puerto, se puede
aprovechar de mejor manera las caractersticas y optimizar el proyecto.

1. Estado de lectura y escritura de los pines RA0, RA1, RA2, RA3 y RA5

El esquema para estos pines muestra el estado de escritura extrado del data sheet del Microchip.
Por ejemplo, se toma el pin RA0 para analizar el funcionamiento del estado de salida cuando el
mismo funciona como entrada o como salida:
3
a. Funcionamiento como Entrada

Para configurar el pin RA0 como entrada, se debe poner a 1 el bit 0 del registro TRISA:

bsf TRISA, 0

Esta instruccin determina una conmutacin a 1 del estado lgico del Flip Flop del latch D
indicado en el circuito con el nombre TRIS latch. Para otro pin de I/O existe uno de estos Flip
Flop y el estado lgico en que se mantiene depende estrictamente del estado lgico del bit
relativo al registro TRIS (en otras palabras, el mejor diseo de todos los bits del registro TRIS
es fsicamente realizable con un latch TRIS).

La salida Q del latch TRIS es conectada a la entrada de una compuerta lgica de tipo OR, esto
significa que independientemente del valor presente en la otra entrada, la salida de la compuerta
OR siempre estar en uno si una de sus entradas estn en uno. En esta condicin, el transistor P
no conduce manteniendo el pin RA0 desconectado del positivo de la alimentacin.

Del mismo modo la salida negativa Q del latch TRIS es conectada a la entrada de una
compuerta AND, en donde, la salida de sta estar siempre en 0 mientras una de sus entradas
valga 0. En esta condicin el transistor N no conduce manteniendo el pin RA0 desconectado de
la tierra. El estado lgico del pin RA0 depender exclusivamente del circuito externo al cual
estar conectado. Aplicando 0 o 5 volts al pin RA0, ser posible leer el estado presente del
circuito externo en la entrada del bloque representado por TTL input buffer y el latch de
entrada.

b. Funcionamiento como Salida

Para configurar el pin RA0 como salida, se debe colocar 0 en el bit 0 del registro TRISA con la
instruccin:

bcf TRISA, 0

Esta instruccin determina la conmutacin a cero de la salida Q del latch TRIS (a 1 si la salida
Q es negativa). En este estado el valor de la salida de las compuertas OR y AND dependen
exclusivamente del estado de salida del Q negado del latch de datos. Como para el latch TRIS,
el latch de datos depende del estado de un bit de un registro, particularmente del registro
PORTA. Su salida negativa ser enviada a la entrada de las dos compuertas lgicas OR y AND
que est directamente sobre la base del transistor P y N. Si ponemos en 0 el bit 0 del registro
PORTA con la instruccin:

bcf PORTA, 0

Se obtendr la conduccin del transistor N y por tanto ir a 0 el pin RA0. Si se coloca en 1 el bit
0 con la instruccin:

bsf PORTA, 0

Se obtendr la conduccin del transistor P y por tanto ir a +5 V el pin RA0. Con esta condicin
ser siempre posible revisar el valor enviado sobre el pin a travs del circuito de entrada.
4
2. Estado de Salida del pin RA4

Se analiza el funcionamiento del estado de salida del pin RA4 que es diferente de las otros pines de
I/O, en cuanto a la distribucin del pin en el PIC16C84 con el TOCKI, lo cual se analizar luego.

Se describe el esquema de bloques del estado de salida extrado del data sheet. La lgica de
conmutacin es substancialmente idntica al grupo de pines RA0 a RA3 con ausencia de la
compuerta OR y del transistor P, o de todos los circuitos que permiten una conexin a positivo del
pin RA4. Esto significa en trminos prcticos que cuando un pin RA4 est programado para salida,
podr asumir un nivel que depender del circuito externo, pues en realidad no est conectada al
positivo y s desconectada. Este tipo de circuito de salida se llama de colector abierto y es til
para aplicaciones en que es necesario compartir una misma ligacin con ms pines de salida,
porque se tiene la necesidad de colocar en alta impedancia un pin de salida y pudiendo as
reprogramarla como pin de entrada.

Si se quiere asegurar que el pin RA4 sea 1 se debe conectar externamente un resistor de PULL-UP,
ya sea un resistor conectado al positivo de alimentacin.

3.2. El Puerto B (PORTB)

3.2.1. Registros asociados al Puerto B

El puerto B es un puerto digital de 8 bits, todas sus pines son bidireccionales y trabaja en forma
similar al puerto A. Tiene tres registros asociados: el registro de datos PORTB, el registro de
direccin de los datos TRISB y el registro OPTION_REG.

1. Registro PORTB (06H, 106H). Los ocho bits que contiene reflejan directamente el estado de
los ocho pines del puerto B: RB0,...,RB7.

2. Registro TRISB (86H, 186H).- En forma similar a TRISA, al poner un 0 en un bit de TRISB
se configura el pin RB correspondiente como salida y al poner un 1 en un bit de TRISB se
configura el pin RB correspondiente como entrada.

3. Registro OPTION_REG (81H, 181H). El bit 7 de este registro, denominado RBPU es usado
para conectar/desconectar una resistencia pull-up conectada a cada pin RB. Poniendo un 0 en
este bit todas las resistencias se conectan. Para desconectar las resistencias pull-up se
debe poner este bit en 1, tambin se desconectan automticamente cuando e l pin
correspondiente es configurado como salida. Un Reset desconecta todas las resistencias.

REGISTRO OPTION u OPTION_REG (Direccin 81h, 181h)

A continuacin se indica el registro OPTION_REG, que puede ser ledo o escrito y que contiene
varios bits de control para configurar la asignacin del preescaler al TMR0 o al WDT, la
interrupcin externa, el TMR0 y las resistencias de pull-up del PORTB.

R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1 R/W-1


#RBPU INTED T0CS T0SE PSA PS2 PS1 PS0
Bit 7 Bit 0

5
Bit 7: #RBPU: Resistencia de Pull-up en el PORTB
1=Resistencia de Pull-up desactivada
0= Resistencia de Pull-up activada

Pines RB4, ... ,RB7. Estos cuatro pines del puerto B tienen la capacidad de generar una solicitud de
interrupcin a la CPU cuando estn configuradas como entradas. El estado de estos pines es
comparado con el ltimo estado que tenan durante la ltima lectura a PORTB, guardado en un
latch. Los bits que indican que hay una diferencia entre estos valores por cada pin estn
conectados a una puerta OR cuya salida activa el bit RBIF del registro INTCON solicitando
con esto una interrupcin. Esta interrupcin es especialmente til para despertar al dispositivo de
su estado de SLEEP cuando alguno de los cuatro pines es activado, por ejemplo, en respuesta a la
presin de una tecla.

Esta caracterstica de solicitud de interrupcin cuando se detecta un cambio junto con las
resistencias pull-up configurables para estos cuatro pines, los hacen ideales para el manejo de
teclados en dispositivos porttiles que requieren dormirse durante largos ratos para economizar
bateras y despertarse cuando una tecla es presionada.

En las siguientes figuras se muestra el alambrado interno de los pines del puerto B:

Pines RB0,...RB3 Pines RB4,...,RB7

3.2.2. Estado de salida de los pines del puerto B

1. Estado de salida de los pines RB0, RB1, RB2 y RB3

Para este grupo de pines permanece sustancialmente invariante la lgica de conmutacin, estas
disponen de un circuito WEAK PULL-UP que se activa cuando el pin es programado como
entrada.
6
La entrada del evento, como se explic anteriormente, el pin viene completamente desligado del
PIC. Un estado del pin depende entonces exclusivamente del circuito externo. S un circuito es del
tipo colector abierto o simplemente est constituido de un simple switche que cuando es
presionado, conecta a tierra la lnea de I/O, es necesario poner una resistencia del PULL-UP desde
el positivo para tomar cuando el switche se suelte y volver al nivel a una condicin lgica activa
sobre un pin de entrada. El circuito de WEAK PULL-UP evita el uso del resistor PULL-UP e
inhabilita que sea activado sobre el bit RBPU (0 habilita, 1 deshabilita) del registro OPTION.

La figura anterior representa un esquema de salida extrado del data sheet del Microchip. El pin
RB0 solo presenta una caracterstica especial, cuando est configurado como pin de entrada, puede
generar, en correspondencia un cambio de estado lgico, una interrupcin ya sea una interrupcin
inmediata del programa en ejecucin o una llamada a una subrutina especial denominada interrupt
handler, lo que se indicar ms adelante.

2. Estado de salida de los pines RB4, RB5, RB6 Y RB7

Un circuito de conmutacin de este grupo es muy similar al grupo de RB0 a RB3. Este pin dispone
tambin de un circuito de weak pull-up. Tambin tienen con respecto a los pines anteriores la
ventaja de poder revelar variaciones de estado sobre cualquier pin y generar una interrupcin, la
misma que se hablar ms adelante.

La figura representa un esquema de salida extrado del data sheet del Microchip. Donde, el bit
RBIF corresponde al registro INTCON.

3.3. El puerto C (PORTC)

3.3.1. Registros asociados al puerto C

El puerto C consta de 8 pines bidireccionales. Trabaja en forma similar a los dos puertos
anteriores y tiene asociados los registros:

1. Registro PORTC (07H).- Es el registro de datos cuyos 8 bits RC7,RC6,...,RC0 reflejan


directamente el valor lgico de los pines fsicos del puerto C.

2. Registro TRISC (87H).- Registro de control de direccin de los pines del puerto C.
Poniendo un 1 en un bit del registro TRISC se configura los pines correspondiente como entrada
y poniendo un 0 se configura la lnea correspondiente como salida.

Los pines del puerto C se encuentran multiplexados con varios pines controlados por otros
perifricos, cuando se habilita el pin del perifrico respectivo puede ser ignorada la configuracin
de TRISC, de hecho, algunos perifricos configuran e l p i n como salida mientras que otros la
configuran como entrada.

Cada entrada del puerto C posee un buffer con disparador trigger. Adems, cuando se selecciona la
funcin I2C, los pines PORTC<4,3> pueden ser configurados con niveles I2C o con niveles SMBus
mediante el bit CKE del registro SSPSTAT<6>, como se muestra en las figuras siguientes.

En las siguientes figuras se muestra el alambrado interno de los pines del puerto B.
7
Pines 7, 6, 5, 2, 1 y 0 del puerto C Pines 4 y 3 del puerto C
3.3.2. Perifricos que estn multiplexados con los p i n e s del puerto C

En la siguiente tabla se resumen los p i n e s del puerto C y los de los perifricos que estn
multiplexados con ellos.

Nombre Funcin multiplexada


RC0/T1OSO/T1CKI Salida oscilatoria del Timer1/reloj de entrada del Timer 1
Entrada oscilatoria del Timer1/entrada de captura2 o salida de
RC1/T1OSI/CCP2 comparacin2 o salida PWM2
RC2/CCP1 Entrada de captura1 o salida de comparacin1 o salida PWM1
RC3/SCK/SCL Reloj para los modos de comunicacin serie sncrona SPI e I2C
RC4/SDI/SDA Dato de entrada (en modo SPI)/ Dato de entrada-salida (modo I2C)
RC5/SDO Dato de salida (en modo SPI)
RC6/TX/CK Pin de transmisin asncrona de la USART/reloj sncrono
RC7/RX/DT Pin de recepcin asncrona de la USART/dato sncrono

3.4. Los Puertos D y E

Estos dos puertos no se encuentran disponibles en los circuitos PIC16F873 y PIC16F876.


El puerto D es un puerto de 8 pines configurables como entradas o salidas mediante el registro
TRISD (88H) y cuyos pines pueden ser accedidos mediante el registro PORTD (08H). Cuando se
configuran como entradas stas poseen un disparador Schmitt trigger.
El Puerto D puede configurarse para trabajar simultneamente con sus 8 bits como un puerto
8
esclavo (Parallel Slave Port) de comunicacin paralela bidireccional con pines de protocolo
proporcionados por los tres pines del Puerto E, para ello se deber activar el bit PSPMODE
(TRISE<4>).
El Puerto E slo posee 3 pines configurables como entradas o salidas mediante el los 3 bits menos
significativos del registro TRISE (89H). Sus pines pueden ser accedidos mediante los 3 bits menos
significativos del registro PORTE (09H). Los pines del puerto E estn compartidos con el
convertidor analgico/digital, por ello, antes de usarlas debern ser configuradas como
entradas/salidas digitales o analgicas, segn se desee en forma similar a como se hizo con el
puerto A, usando el registro de configuracin ADCON1 (9FH).

3.5. Ejemplo 31

Entradas digitales. En este ejemplo se configura el pin RA5 del puerto A como salida conectado a
un LED, el cual se controla de acuerdo al estado de los pines RA0 y RA1 configurados como
entradas.

Hardware necesario. Como prcticamente en todos los programas para PIC, si no se conecta el
hardware adecuado no se puede ver ningn efecto al ejecutar el programa. En la siguiente
figura se muestra la conexin de los dos botones y el LED necesarios para probar el programa,
adems claro est de la circuitera de reloj necesaria.

En este programa el rebote generado por los switches no es problema, porque funciona correctamente
haya o no haya rebote.

9
1. Diagrama de Flujo:

INICIO

NO
RA0=1

SI

RA50

NO
RA1=1

SI

RA51

2. Cdigo en Assembler:

;*****************************************************************************
;* Ejemplo31.asm
;* Este programa Enciende un LED conectado a RA5 cuando se presiona un botn
;* conectado a RA1 y lo apaga cuando se presiona un botn conectado a RA0
;*****************************************************************************
PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877A.INC"

;Setup of PIC configuration flags


__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

;Reset Vector
org 0x00 ;Inicia en el vector de reset

;Inicializacin del puerto A:


BCF STATUS,RP0 ;
BSF STATUS,RP0 ;Selecciona Banco 1
MOVLW 0x06 ;Configura todas los pines de A
MOVWF ADCON1 ;como digitales
MOVLW 0x1F ;configura todas los pines de A como entradas
MOVWF TRISA ;y RA5 como salida

;Una vez inicializado el puerto, se procede leer los pines RA0 y RA1
BCF STATUS,RP0 ;regresa al banco 0
chRA0 BTFSS PORTA,0 ;checa si RA0=1
10
GOTO chRA1 ;si RA=0 salta a checar RA1
BCF PORTA,5 ;si RA0=1 apaga el LED
chRA1 BTFSS PORTA,1 ;checa si RA1=1
GOTO chRA0 ;si RA1=0 salta a checar RA0
BSF PORTA,5 ;si RA1=1 enciende el LED
GOTO chRA0

END

3.6. El efecto rebote y su eliminacin

En el momento de presionar un botn pulsador o cualquier conmutador electromecnico es inevitable


que se produzca un pequeo arco elctrico durante el breve instante en que las placas del contacto
se aproximan o se alejan de sus puntos de conexin, ya que las distancias microscpicas entre los
puntos a diferente potencial son suficientes para romper por un instante la resistividad del aire.
Este fenmeno se conoce como rebote (bounce) y se ilustra en la siguiente figura:

3.6.1. Duracin del rebote

La experiencia emprica indica que el periodo transitorio de un rebote depende entre otros factores,
de la calidad de los switches y de la rapidez de su accionamiento, pero a lo ms puede durar unos
20 milisegundos, En la siguiente figura se muestra un rebote real en los contactos de un
relevador capturado en la pantalla de un osciloscopio digital Fluke 123. (Obsrvese que el rebote
mostrado dur solamente 3 milisegundos).

11
3.6.2. Limpiado del rebote (debouncing)

El rebote generado por un switch no siempre es un problema, porque en algunas aplicaciones


puede funcionar correctamente haya o no haya rebote (como en el ejemplo 1). Sin embargo, Qu
pasara si se desea controlar el encendido y apagado del LED con un solo botn?. En este caso
s se debe contemplar el limpiado del rebote. (Siempre que a una sola tecla se le asigna dos o ms
funciones diferentes en un programa se deben considerar el efecto del rebote).

El rebote de un switch puede durar a lo ms unos 20 milisegundos, por lo que para el limpiado del
rebote se debe realizar una subrutina con una pausa de 20 mseg, la cual se desarrolla a continuacin.

I. Subrutina de pausa con un ciclo

La subrutina pau20ms simplemente realiza una pausa de 20 milisegundos. Se tiene dos formas de
implementacin de esta subrutina (suponiendo un reloj de 100 Khz):

a. Usando memoria de datos


1. Diagrama de Flujo:

12
pau20ms

WN
contW

contcont-1

NO
Z=1

SI

FIN

2. Cdigo en Assembler:
;* Subrutina de pausa que dura 20 milisegundos (usando memoria de datos)
;* (Supone un reloj de 100 Khz)
;**************************************************************************
;Define constantes
N EQU 0xA5
cont EQU 0x20
; inicia subrutina
pau20ms MOVLW N ;Carga dato que controla la duracin, W=N
MOVWF cont ;inicializa contador con el dato, cont=N
rep DECFSZ cont,1 ;Decrementa contador y escapa si cero, cont=cont-1
GOTO rep ;si no es cero, repite
RETURN ;regresa de esta subrutina

b. Sin usar memoria de datos

;* Subrutina de pausa que dura 20 milisegundos (sin usar memoria de datos)


;* (Supone un reloj de 100 Khz)
;**************************************************************************
;Define dato que controla la duracin
N EQU ???
;inicia subrutina
pau20ms MOVLW N ;Carga dato que controla la duracin
rep ADDLW 0xFF ;Le suma 1
BTFSS STATUS,2 ;Si es cero escapa
GOTO rep ;si no es cero, repite
RETURN ;regresa de esta subrutina

Clculo del valor de N

Para lograr que la duracin de la subrutina presentada sea de 20 milisegundos es


necesario elegir adecuadamente el valor de la constante N. Para ello se ejemplifica el clculo
13
en la primera de las dos versiones (a): A continuacin se repite el cdigo fuente de la
subrutina incluyendo entre parntesis el nmero de ciclos que dura cada instruccin:

pau20ms MOVLW N ;(1)


MOVWF cont ;(1)
rep DECFSZ cont,1 ;(1 si no escapa, 2 si escapa)
GOTO rep ;(2)
RETURN ;(2)

De manera que el nmero de ciclos de instruccin Tsub consumidos por la subrutina,


incluyendo los 2 ciclos de la llamada (CALL) sern:

Tsub = [2+1+1+(N-1)*(1+2)+2+2] ciclos

Lo cual se puede expresar en segundos como:

Tsub = (3N+5) Tcy


Donde Tcy es la duracin en segundos de un ciclo de instruccin. Despejando N tenemos:

N = (Tsub/Tcy 5)/3

Por ejemplo, suponiendo Tsub = 20 mseg y que se est usando un reloj de 100 Khz y (fcy =
fosc/4 = (100x103 Hz)/4 =25x103 Hz entonces Tcy = 1/(25x103) = 40x10-6 seg = 40 seg):
N = (20 mseg /40seg 5)/3
N = 165 = A5H

Observacin. La mxima duracin que se puede lograr con esta subrutina y con la frecuencia del
reloj de 100 Khz supuesta (Tcy = 40 seg), es cuando el ciclo se ejecute 256 veces, es decir con
un valor N=256, lo cual en el programa se logra con el valor inicial N=0:

Tsub = (3N+5) Tcy


Tsub = (3 x 256 + 5) x 40 x 10-6seg
Tsub = 30.92 mseg

As, si la frecuencia del reloj es mayor, por ejemplo, en el modo de oscilador interno se
tienen 4 Mhz, que da un Tcy=1seg, esta subrutina no podr proporcionar nunca los 20 mseg,
por lo que habr que realizar una pausa ms larga anidando dos ciclos.

II. Subrutina de pausa con dos ciclos anidados

La pausa pau20ms es demasiado corta, de manera que para frecuencias altas de reloj no puede
alcanzar ni siquiera los 20 mseg. A continuacin se muestra una pausa que puede dar tiempos
mucho ms largos usando ciclos anidados. A continuacin se va realizar una subrutina d20ms de
20 mseg con un reloj de 4 Mhz:

1. Diagrama de Flujo:

14
d20ms

WN
cont1W

WM
cont2W

cont2cont2-1

NO
Z=1

SI

cont1cont1-1

NO
Z=1

SI

FIN

2. Cdigo en Assembler:
;* Subrutina de pausa para frecuencias medias
;* (Adecuada para un reloj de 4 Mhz)
;**************************************************************************
;Define constantes para 20 milisegundos
N EQU 0x1A
M EQU 0x00
cont1 EQU 0x20
cont2 EQU 0x21
;inicia subrutina
d20ms MOVLW N ;(1) Carga dato N
MOVWF cont1 ;(1) inicializa contador1 ciclo externo
rep1 MOVLW M ;(1) Carga dato M
MOVWF cont2 ;(1) inicializa contador2 ciclo interno
rep2 DECFSZ cont2,1 ;(1,2)Decrementa contador2 y escapa si cero
GOTO rep2 ;(2) si no es cero, repite ciclo interno
DECFSZ cont1,1 ;(1,2)Decrementa contador1 y escapa si cero
GOTO rep1 ;(2) si no es cero repite ciclo externo
RETURN ;(2) regresa de esta subrutina

15
La duracin de esta subrutina en ciclos de reloj ser

Tsub = 2+1+1+N*[1+1+(M-1)*(1+2)+2+1+2]+1-2+2+2 ciclos

Lo cual se puede simplificar como sigue:

Tsub = [N*(3M+4)+7] Tcy


La mxima duracin de esta subrutina se obtiene para N=M=256, lo cual en el programa se logra
con los valores iniciales de N=M=0; entonces Tsub mximo = 197639 Tcy. Para una
frecuencia de 4 Mhz (Tcy = 1 seg), entonces Tsub mximo =0,197639 seg.

Si deseamos Tsub = 20 mseg, haciendo M=256, despejando N,

N = (Tsub/Tcy
7)/(3M+4)

Sustituyendo valores obtenemos N= 25.89 ~ 1Ah. (debido a la aproximacin la subrutina


realmente dura 20.08 mseg.

Observacin. Hasta aqu se estn realizando pausas de duracin controlada por software, sin
embargo, lo ms adecuado para controlar tiempo de manera ms exacta es usar los timers
que se vern ms adelante.

III. Subrutina de pausa con ciclos anidados para tiempos largos

Para realizar la pausa de un segundo, d1seg, se puede hacer uso de la subrutina d20ms con su
mxima duracin Tsub = 0,197639 seg, teniendo los valores N=M=256 (con los valores
iniciales de N=M=0 en el programa). Para ello se implementa un tercer ciclo externo que repita
esta pausa p veces.

1. Diagrama de Flujo:

16
d1seg

Wp
cont3W

d20ms

cont3cont3-1

NO
Z=1

SI

FIN

2. Cdigo en Assembler:

;* Subrutina de pausa de 1 segundo


;**********************************************************************
p EQU 0x05
cont3 EQU 0x22
d1seg MOVLW p ;(1)carga duracin del ciclo
MOVWF cont3 ;(1)inicializa contador3
ciclo CALL d20ms ;(197639)pausa de 0.197639 seg con Fos=4Mh y M=N=256
DECFSZ cont3,1 ;(1,2)Decrementa y escapa si cero
GOTO ciclo ;(2)si no es cero repite
RETURN ;(2)si es cero retorna

La duracin de esta subrutina incluyendo la llamada ser

Tsub = [2+1+1+(p)*(197639+1+2)+1-2+2] ciclos


Es decir,
Tsub = [197642*p+5] Tcy

La mxima duracin de esta subrutina (para p =256), suponiendo un reloj de 4 Mhz (Tcy = 1
seg), se tiene un Tsubmximo=50,596357 seg. Sin embargo, si se desea un Tsub=1seg. Se
obtiene:
p = (Tsub/Tcy 5)/197642 = 5,059628 ~ 5

17
3.7. Ejemplo 2

En este ejemplo se usa slo el botn conectado al pin RA0 para controlar el encendido y
apagado del LED en el pin RA5, cuando se presiona el botn conectado a RA0 se enciende el LED
conectado en el pin RA5 y lo apaga cuando se presiona nuevamente el mismo botn y as
sucesivamente. Se incluye el limpiado del rebote con un reloj de 4Mhz.

Hardware necesario. En la siguiente figura se muestra la conexin del botn y el LED necesarios
para probar el programa.

1. Diagrama de Flujo:

Diagrama de flujo del Programa Principal:

INICIO

N0x1A
M0x00

NO
RA0=1

SI

d20ms

NO
RA0=1

SI

W0x20
RA5W XOR RA5

18
El diagrama de flujo de la Subrutina d20ms se realiza en el subtema Limpiado del rebote.

2. Cdigo en Assembler:

;**************************************************************************
;* Ejemplo32.asm
;* Este programa Enciende un LED conectado a RA5 cuando se presiona un botn
;* conectado a RA0 y lo apaga cuando se presiona nuevamente el mismo botn y
;* as sucesivamente.
;**************************************************************************
PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877A.INC"

;Setup of PIC configuration flags


__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

;Define constantes
N EQU 0x1A
M EQU 0x0

;Define variables
CBLOCK 0x20
cont1
cont2
ENDC

;Reset Vector
org 0x00 ;Inicia en el vector de reset

;Inicializacin del puerto A:


CLRF STATUS ;Selecciona Banco 0
BSF STATUS,RP0 ;Selecciona Banco 1
MOVLW 0x06 ;Configura todas las patitas de A
MOVWF ADCON1 ;como digitales
MOVLW 0x1F ;configura todas las patitas de A como entradas
MOVWF TRISA ;y RA5 como salida
BCF STATUS,RP0 ;regresa al banco 0

checa BTFSS PORTA,0 ;checa si RA0=1


GOTO checa ;si RA=0 checa de nuevo
CALL d20ms ;si RA0=1 espera 20 miliseg. A que pase el rebote
chec1 BTFSS PORTA,0 ;checa nuevamente si RA0=1
GOTO chec1 ;si RA1=0 falsa alarma, vuelve a checar
MOVLW 0x20 ;si RA0=1 seal vlida; carga mscara en W
XORWF PORTA,1 ;conmuta estado del LED
GOTO checa ;repite

;* Subrutina de pausa para frecuencias medias


;* (Adecuada para un reloj de 4 Mhz)
;**************************************************************************
19
;Define constantes para 20 milisegundos
;inicia subrutina
d20ms MOVLW N ;(1) Carga dato N
MOVWF cont1 ;(1) inicializa contador1 ciclo externo
rep1 MOVLW M ;(1) Carga dato M
MOVWF cont2 ;(1) inicializa contador2 ciclo interno
rep2 DECFSZ cont2,1 ;(1,2)Decrementa contador2 y escapa si cero
GOTO rep2 ;(2) si no es cero, repite ciclo interno
DECFSZ cont1,1 ;(1,2)Decrementa contador1 y escapa si cero
GOTO rep1 ;(2) si no es cero repite ciclo externo
RETURN ;(2) regresa de esta subrutina

END

3.8. Ejemplo 3

Luces secuenciales. En este ejemplo se realiza el encendido secuencial de 8 LEDs conectados a


RB0,...,RB7, es decir, se enciende RB0 durante un segundo, luego RB1 y as sucesivamente hasta
llegar a RB7 para recomenzar despus con RB0. (en un segundo dado slo un LED est prendido).

Hardware necesario. Slo se requieren los ocho LEDs conectados a los pines RBP0,...,RBP7,
como se muestra en la siguiente figura.

1. Diagrama de Flujo:

Diagrama de flujo del Programa Principal:

20
INICIO

N0x00
M0x00
p0x05
C0
PORTB0
RB01

d1seg

PORTBrota izq PORTB

SI
C=0

NO

RB01

C0

Los diagramas de flujo de la Subrutinas d1seg y d20ms se realiza en el subtema Limpiado del
rebote.

2. Cdigo en Assembler:

;**********************************************************************
;* Ejemplo33.asm
;* Este programa Enciende en secuencia (uno a la vez) 8 LEDs conectados
;* a los pines del puerto B
;**********************************************************************
PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877A.INC"

;Setup of PIC configuration flags


__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

;Define constantes Para 200 milisegundos


N EQU 0x0
M EQU 0x0

21
p EQU 0x05

;Define variables
CBLOCK 0x20
;Define variables para pausa de 200 mseg
cont1
cont2
;Define variable para pausa de 1 segundo
cont3
ENDC

;Reset Vector
org 0x00 ;Inicia en el vector de reset

;Inicializacin del puerto B:


CLRF STATUS ;Selecciona Banco 0
BSF STATUS,RP0 ;Selecciona Banco 1
CLRF TRISB ;Configura todas los pines de B como salidas

;Una vez inicializado el puerto, se procede a controlar los LEDs


BSF STATUS,RP0 ;Regresa al banco 0
BCF STATUS,C ;Limpia acarreo
CLRF PORTB ;Apaga todos los LEDs
BSF PORTB,0 ;enciende el LED RB0
ciclo CALL d1seg ;pausa de un segundo
RLF PORTB,1 ;Recorre posicin encendida a la izquierda
BTFSC STATUS,C
BSF PORTB,0
BCF STATUS,C
GOTO ciclo ;repite

;* Subrutina de pausa para tiempos largos


;* (Adecuada para un reloj de 4 Mhz)
;**************************************************************************
;inicia subrutina
d20ms MOVLW N ;(1) Carga dato N
MOVWF cont1 ;(1) inicializa contador1 ciclo externo
rep1 MOVLW M ;(1) Carga dato M
MOVWF cont2 ;(1) inicializa contador2 ciclo interno
rep2 DECFSZ cont2,1 ;(1,2)Decrementa contador2 y escapa si cero
GOTO rep2 ;(2) si no es cero, repite ciclo interno
DECFSZ cont1,1 ;(1,2)Decrementa contador1 y escapa si cero
GOTO rep1 ;(2) si no es cero repite ciclo externo
RETURN ;(2) regresa de esta subrutina

;* Subrutina de pausa de 1 segundo


;**********************************************************************
;inicia rutina
d1seg MOVLW p ;(1)carga duracin del ciclo
MOVWF cont3 ;(1)inicializa contador3
ciclo1 CALL d20ms ;(196868)pausa de 0.197639 seg
DECFSZ cont3,1 ;(1,2)Decrementa y escapa si cero
GOTO ciclo1 ;(2)si no es cero repite
RETURN ;(2)si es cero retorna

END

22
3.9. Ejemplo 4

Conexin de un teclado matricial

El presente ejemplo realiza el ingreso de datos numricos hexadecimales mediante un teclado de tipo
telefnico, controlando las 3 columnas con las salidas RB1, RB2 y RB3 y las 4 filas con las entradas
RB4, RB5, RB6 y RB7 con resistencias pull-up internas para evitar resistencias externas. Luego
mostrar el dato ingresado en el puerto C.

Una de las funciones ms comunes de un microcontrolador es la aceptacin de datos numricos o


alfanumricos suministrados por un operador mediante un teclado.

La mayora de los teclados estn organizados en forma matricial como un conjunto de switches en
las intersecciones de varios renglones y columnas conductoras como se muestra en la siguiente
figura que ejemplifica un teclado de tipo telefnico.

En la figura tambin se ilustra una conexin tpica con tres pines de entrada del puerto B que
controlan las columnas y cuatro pines de salida del mismo puerto que recogen la informacin de los
renglones.

Observacin. Es recomendable colocar un diodo de proteccin en cada pin de salida del


puerto para evitar que al activar ms de una columna a la vez se produzca un corto circuito.

Procedimiento de deteccin de teclas y codificacin. Para la deteccin y asignacin de


cdigo segn la tecla presionada se procede como sigue:

1. Deteccin. Se ponen en bajo todos las filas (cuidando que haya diodos de proteccin) y se
leen las columnas.

2. Si hay alguna columna activa se limpia el rebote, si es tecla vlida se pasa al paso 3, si
no es tecla vlida se asigna un cdigo de ninguna tecla presionada.

3. Codificacin. El puerto activa una fila a la vez colocando un cero lgico en el pin
correspondiente a la fila a activar.
23
4. Por cada fila activa se lee la informacin de columnas y dependiendo de la fila y la
columna activada (en bajo) se asigna el cdigo a la tecla de la interseccin.
1. Diagrama de Flujo:

Diagrama de flujo del Programa Principal:

INICIO

N0x1A
M0x00

initB

W0xFF
masqW

detect

masqW-masq

NO
Z=1

SI

codif

PORTCW

Diagrama de flujo de la Subrutina initB:

24
initB

STATUS0
PORTB0

TRISB0xF0
RBPU0

FIN

Diagrama de flujo de la Subrutina detec:

INICIO

PORTB0 A

NO NO
RB7=1 RB7=1

SI SI

NO NO
RB6=1 RB6=1

SI SI

NO NO
RB5=1 RB5=1

SI SI

NO NO
RB4=1 RB4=1

SI SI

W0x00 d20ms W0x00 W0xFF

FIN A FIN FIN

Diagrama de flujo de la Subrutina codif:


25
INICIO A B

W0xF7 W0xFB W0xFD


PORTBW PORTBW PORTBW

NO NO NO
RB7=1 RB7=1 RB7=1

SI W1 SI W2 SI W3

NO NO NO
RB6=1 RB6=1 RB6=1

SI SI SI
W4 W5 W6

NO NO NO
RB5=1 RB5=1 RB5=1

SI W7 SI W8 SI W9

NO NO NO
RB4=1 RB4=1 RB4=1

SI W* SI W0 SI W#

A B W0x00

FIN FIN FIN

El diagrama de flujo de la Subrutina d20ms se realiza en el subtema Limpiado del rebote.

2. Cdigo en Assembler:
;*********************************************************************
;* Ejemplo34.asm
;* Ingreso de datos numricos hexadecimales mediante un teclado de
;* tipo telefnico, controlando las 3 columnas con las salidas RB1,RB2 y RB3
;* y las 4 filas con las entradas RB4,RB5,RB6 y RB7 con resistencias pull-up
;* internas para evitar resistencias externas.
;* Luego mostrar el dato ingresado en el puerto C.
;*********************************************************************
PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877A.INC"

;Setup of PIC configuration flags


__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

;Define constantes para 20 milisegundos


N EQU 0x1A
M EQU 0x0

26
;Define variables
CBLOCK 0x20
;Define variables para pausa de 20 mseg
cont1
cont2
;Define variable para mascara 0xFF (tecla pulsada)
masq
ENDC

;Reset Vector
org 0x00 ;Inicia en el vector de reset

;Configura el puerto C como salida


CLRF STATUS ;Selecciona Banco 0
BSF STATUS,RP0 ;Selecciona Banco 1
MOVLW 0x00 ;configura puerto C como salidas
MOVWF TRISC ;
BCF STATUS,RP0 ;regresa al Banco 0

;Programa principal
CALL initB ;Llama a la subtutina initB
repite MOVLW 0xFF ;Almacena en W la mascara 0xFF
MOVWF masq ;Almacena en masq la mascara 0xFF
CALL detec ;Llama a la subtutina detect
SUBWF masq,1 ;
BTFSS STATUS,Z ;Resultado en W=0
GOTO repite ;Repite el proceso
CALL codif ;Llama a la subtutina codif
MOVWF PORTC ;Mueve la tecla presionada al puerto C
GOTO repite ;Repite el proceso

;Esta subrutina realiza la Inicializacin del puerto B:


;*********************************************************************

initB CLRF STATUS ;Selecciona Banco 0


CLRF PORTB ;Inicializa latches de datos de PORTB
BSF STATUS,RP0 ;Selecciona Banco 1
MOVLW 0xF0 ;configura RB7,...,RB4 como entradas
MOVWF TRISB ;y RB3,RB2,RB1 como salidas
BCF OPTION_REG,7 ;Conecta todas las resistencias Pull-Up
BCF STATUS,RP0 ;regresa al Banco 0
RETURN

;Esta subrutina realiza la Deteccin de tecla presionada: regresa W=0 si no hay


tecla
;presionada y W=0xFF si hay alguna tecla presionada
;*********************************************************************

detec CLRF PORTB ;activa las cuatro filas


BTFSS PORTB,7 ;lee rengln 1,2,3
GOTO rebo ;si tecla presionada limpia rebote
BTFSS PORTB,6 ;lee rengln 4,5,6
GOTO rebo ;si tecla presionada limpia rebote
BTFSS PORTB,5 ;lee rengln 7,8,9
GOTO rebo ;si tecla presionada limpia rebote
BTFSS PORTB,4 ;lee rengln *,0,#
GOTO rebo ;si tecla presionada limpia rebote
RETLW 0x0 ;no hubo tecla presionada retorna con w=0

rebo CALL d20ms ;pausa de 20 milisegundos

27
BTFSS PORTB,7 ;lee rengln 1,2,3
RETLW 0xFF ;tecla presionada, retorna con w=0xFF
BTFSS PORTB,6 ;lee rengln 4,5,6
RETLW 0xFF ;tecla presionada, retorna con w=0xFF
BTFSS PORTB,5 ;lee rengln 7,8,9
RETLW 0xFF ;tecla presionada, retorna con w=0xFF
BTFSS PORTB,4 ;lee rengln *,0,#
RETLW 0xFF ;tecla presionada, retorna con w=0xFF
RETLW 0x0 ;falsa alarma retorna con w=0

;* Esta subrutina realiza la codificacin del teclado tipo telefnico


;* retornando en W el cdigo ASCII de la tecla presionada,
;* regresa W=0 si no hubo tecla presionada
;*********************************************************************

; Se hace un barrido por columnas


codif ; Primera columna
MOVLW 0xF7 ;Activa la primera columna
MOVWF PORTB ;y activa la columna 1,4,7,*
BTFSS PORTB,7 ;Es la tecla 1?
RETLW '1' ;retorna cdigo del ?1?
BTFSS PORTB,6 ;Es la tecla 4?
RETLW '4' ;retorna cdigo del ?4?
BTFSS PORTB,5 ;Es la tecla 7?
RETLW '7' ;retorna cdigo del ?7?
BTFSS PORTB,4 ;Es la tecla *?
RETLW '*' ;Retorna cdigo del ?*?

; Segunda columna
MOVLW 0xFB ;Activa la segunda columna
MOVWF PORTB ;y activa la columna 2,5,8,0
BTFSS PORTB,7 ;Es la tecla 2?
RETLW '2' ;retorna cdigo del ?2?
BTFSS PORTB,6 ;Es la tecla 5?
RETLW '5' ;retorna cdigo del ?5?
BTFSS PORTB,5 ;Es la tecla 8?
RETLW '8' ;retorna cdigo del ?8?
BTFSS PORTB,4 ;Es la tecla 0?
RETLW '0' ;Retorna cdigo del ?0?

; Tercera columna
MOVLW 0xFD ;Activa la tercera columna
MOVWF PORTB ;y activa la columna 3,6,9,#
BTFSS PORTB,7 ;Es la tecla 3?
RETLW '3' ;retorna cdigo del ?3?
BTFSS PORTB,6 ;Es la tecla 6?
RETLW '6' ;retorna cdigo del ?6?
BTFSS PORTB,5 ;Es la tecla 9?
RETLW '9' ;retorna cdigo del ?9?
BTFSS PORTB,4 ;Es la tecla #?
RETLW '#' ;Retorna cdigo del ?#?
RETLW 0x00 ;falsa alarma, no hay tecla presionada

;* Subrutina de pausa para frecuencias medias


;* (Adecuada para un reloj de 4 Mhz)
;**************************************************************************
;inicia subrutina
d20ms MOVLW N ;(1) Carga dato N
MOVWF cont1 ;(1) inicializa contador1 ciclo externo
rep1 MOVLW M ;(1) Carga dato M

28
MOVWF cont2 ;(1) inicializa contador2 ciclo interno
rep2 DECFSZ cont2,1 ;(1,2)Decrementa contador2 y escapa si cero
GOTO rep2 ;(2) si no es cero, repite ciclo interno
DECFSZ cont1,1 ;(1,2)Decrementa contador1 y escapa si cero
GOTO rep1 ;(2) si no es cero repite ciclo externo
RETURN ;(2) regresa de esta subrutina

END

Observacin: La repeticin de cdigo se puede evitar utilizando direccionamiento indirecto dentro


de un ciclo, sin embargo, esto slo representa un ahorro de cdigo y de memoria para teclados de
mayor complejidad.

3.10. Ejemplo 5

Manejo de un Display de 7 segmentos

Un display de siete segmentos es un arreglo de 7 LEDs conectados como se muestra en la siguiente


figura:

Para este ejemplo se supone un display de nodo comn conectado al puerto C como se muestra a
continuacin:

El programa visualiza dgitos numricos hexadecimales en el display, de acuerdo a la codificacin


mostrada en la siguiente tabla.

Dato a b c d e f g Cdigo
29
0 0 0 0 0 0 0 1 01
1 1 0 0 1 1 1 1 4F
2 0 0 1 0 0 1 0 12
3 0 0 0 0 1 1 0 06
4 1 0 0 1 1 0 0 4C
5 0 1 0 0 1 0 0 24
6 0 1 0 0 0 0 0 20
7 0 0 0 1 1 1 1 0F
8 0 0 0 0 0 0 0 00
9 0 0 0 0 1 0 0 04
A 0 0 0 1 0 0 0 08
b 1 1 0 0 0 0 0 60
C 0 1 1 0 0 0 1 31
d 1 0 0 0 0 1 0 42
E 0 1 1 0 0 0 0 30
F 0 1 1 1 0 0 0 38

1. Diagrama de Flujo:

Diagrama de flujo del Programa Principal:

30
INICIO

N0x1A
M0x00
PORTB0x01
cont0

NO
RC7=1

SI

d20ms

NO
RC7=1

SI

contcont+1

codigo

POTCW

NO
RC7=0

SI

El diagrama de flujo de la Subrutina d20ms se presenta en el subtema Limpiado del rebote

Diagrama de flujo de la Subrutina cdigo:

31
codigo

W0x0F
WW AND cont
PCLW + PCL

Selecciona un
valor de acuerdo
a cont:
0: W0x01
1: W0x4F
2: W0x12
3: W0x06
4: W0x4C
5: W0x24
6: W0x20
7: W0x0F
8: W0x00
9: W0x04
10: W0x08
11: W0x60
12: W0x31
13: W0x42
14: W0x30
15: W0x38

FIN

2. Cdigo en Assembler:

;************************************************************************
;* Ejemplo35.asm
;* Este programa despliega un dgito hexadecimal en un display de nodo
;* comn conectado al puerto C. El dgito se incrementa en 1 cada vez que
;* se presiona un botn conectado al MSB del mismo puerto C
;************************************************************************
PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877A.INC"

;Setup of PIC configuration flags


__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

;Define constantes para 20 milisegundos


N EQU 0x1A
M EQU 0x0

;Define variables
CBLOCK 0x20
;Define variables contador
cont

32
;Define variables para pausa de 20 mseg
cont1
cont2
;Define variable para pausa de 1 segundo
cont3
ENDC

;Reset Vector
org 0x00 ;Inicia en el vector de reset

inic BSF STATUS,RP0 ;banco 1


MOVLW 0x80 ;Todos los bits del puerto C como salidas
MOVWF TRISC ;y el MSB como entrada
BCF STATUS,RP0 ;regresa al Banco 0

MOVLW 0x01 ;
MOVWF PORTC ;Despliega un cero. Codificado
CLRF cont ;Inicializa contador en cero
tecla BTFSS PORTC,7 ;checa botn si se ha presionado
GOTO tecla ;Si no se ha presionado espera
CALL d20ms ;pausa de 20 milisegundos
BTFSS PORTC,7 ;checa nuevamente el botn si esta presionado
GOTO tecla ;tecla falsa, espera de nuevo
INCF cont,1 ;tecla vlida, incrementa contador
CALL codigo ;obtiene cdigo para desplegar el contador
MOVWF PORTC ;despliega contador
suelta BTFSC PORTC,7 ;checa de nuevo el botn si se ha soltado
GOTO suelta ;si sigue presionado espera
GOTO tecla ;si ya se solt espera nueva presin.

;* Subrutina para determinar el codigo hexadecimal


;*
;**************************************************************************

codigo
MOVLW 0x0F ;carga mscara
ANDWF cont,0 ;enmascara el contador y lo deja en W
ADDWF PCL,1 ;Salta W instrucciones adelante
RETLW 0x01 ;cdigo del 0
RETLW 0x4F ;cdigo del 1
RETLW 0x12 ;cdigo del 2
RETLW 0x06 ;cdigo del 3
RETLW 0x4C ;cdigo del 4
RETLW 0x24 ;cdigo del 5
RETLW 0x20 ;cdigo del 6
RETLW 0x0F ;cdigo del 7
RETLW 0x00 ;cdigo del 8
RETLW 0x04 ;cdigo del 9

33
RETLW 0x08 ;cdigo de la A
RETLW 0x60 ;cdigo de la b
RETLW 0x31 ;cdigo de la C
RETLW 0x42 ;cdigo de la d
RETLW 0x30 ;cdigo de la E
RETLW 0x38 ;cdigo de la F

;* Subrutina de pausa para tiempos largos


;* (Adecuada para un reloj de 4 Mhz)
;**************************************************************************

;inicia subrutina
d20ms MOVLW N ;(1) Carga dato N
MOVWF cont1 ;(1) inicializa contador1 ciclo externo
rep1 MOVLW M ;(1) Carga dato M
MOVWF cont2 ;(1) inicializa contador2 ciclo interno
rep2 DECFSZ cont2,1 ;(1,2)Decrementa contador2 y escapa si cero
GOTO rep2 ;(2) si no es cero, repite ciclo interno
DECFSZ cont1,1 ;(1,2)Decrementa contador1 y escapa si cero
GOTO rep1 ;(2) si no es cero repite ciclo externo
RETURN ;(2) regresa de esta subrutina

END
Observacin: Una manera ms cmoda de escribir la lista de instrucciones RETLW al final del
programa anterior puede lograrse usando la directiva DT (Define Table) del ensamblador, la cual
nos permite definir una tabla de datos que ser sustituida por una lista de instrucciones RETLW; as,
la lista anterior puede quedar como sigue:

DT 0x01,0x4F,0x12,0x06,0x4C,0x24,0x3F,0x0F
DT 0x00,0x04,0x08,0x60,0x31,0x42,0x30,0x38

3.11. Pantalla LCD 162 con PIC (HD44780)

http://www.geekfactory.mx/tutoriales/tutoriales-pic/pantalla-lcd-16x2-con-pic-libreria/

por Jesus Ruben Santa Anna Zamudio | Ago 2, 2014 | Tutoriales PIC | 3 Comments

11.1. Descripcin:

Cuando los simples indicadores luminosos con led ya no son suficientes, habitualmente el siguiente
paso para todo programador es ir por una pantalla lcd 162. Se encuentra que existen mdulos LCD
que facilitan la interfaz con este perifrico. El estndar en la industria para estos mdulos con
controlador a bordo es el chipset HD44780 (y otros ms compatibles desarrollados a partir de este),
para los cuales se encuentra soporte en prcticamente cualquier plataforma: Arduino, PIC, AVR,
MSP430, etc.

La pantalla de cristal lquido o LCD (Liquid Crystal Display) es un dispositivo microControlado de


visualizacin grfico para la presentacin de caracteres, smbolos o incluso dibujos (en algunos
modelos), es este caso dispone de 2 filas y de 16 caracteres cada una y cada carcter dispone de una
34
matriz de 5x7 puntos (pixels), aunque los hay de otro nmero de filas y caracteres. Este dispositivo est
gobernado internamente por un microcontrolador y regula todos los parmetros de presentacin, este
modelo es el ms comnmente usado y esta informacin se basar en el manejo de este u otro LCD
compatible.

En la Figura 1 se muestra un LCD 2x16 que est compuesto por 2 lneas de 16 caracteres, con
iluminacin azul y letras color blanco.

Figura 1. LCD 2x16: est compuesto por 2 lneas de 16 caracteres

11.2. Gestin de un LCD

Se realizar la interface del PIC16F877 con un LCD (Liquid Crystal Display) compuesto por dos lneas
de 16 caracteres cada una. Los LCD ms comunes, disponen de una interface ideada por Hitachi y
adoptada como estndar por otros fabricantes. Esta interface hace que el LCD pueda ser conectado al
micro a travs de un bus de 4 u 8 lneas ms tres lneas de control y las de alimentacin.
En la Tabla 1 estn descriptas las funciones de cada lnea disponible del LCD. Las descripciones en
negrita, indican las lneas efectivamente utilizadas en la aplicacin de 4 bits de datos.

Tabla 1. Funciones de cada lnea disponible del LCD


Pin Nombre Funcin
1 GND Ground. GND (Tierra 0V)
2 VDD Power Supply. Alimentacin (+5 v)
3 LCD Liquid Crystal Driving Voltage. Ajuste del contraste (Se aplicada una tensin variable entre 0 y 5V)
4 RS# Register Select. Seleccin DATO/COMANDO (Es una lnea de control que se le indica al display si se est
enviando en el bus de datos un comando (RS=0) o un dato (RS=1))
5 R/W# Read, Write. Lectura o escritura en LCD (Es otra lnea de control que LE se indica al display si se est enviando
un dato (R/W=0) o leyendo un dato del display (R/W=1))
6 E Enable. Habilitacin (Esta lnea de control sirve para habilitar el display para que reciba un dato o
instrucciones a travs del bus (E=1))
7 DB0 Data Bus Line 0 - Bit menos significativo. Sobre estas lneas viajan los datos entre el micro y el display
8 DB1 Data Bus Line 1
9 DB2 Data Bus Line 2
10 DB3 Data Bus Line 3
11 DB4 Data Bus Line 4
12 DB5 Data Bus Line 5
13 DB6 Data Bus Line 6
14 DB7 Data Bus Line 7. Bit ms significativo
15 LED+ nodo de LED backlight
16 LED- Ctodo de LED backlight
Nota: # significa negado
35
Segn la operacin que se desee realizar en el mdulo LCD, los pines de control E, RS#, R/W# deben
tener un estado determinado. Adems, debe tener en el bus de datos un cdigo que indique un caracter
para mostrar en la pantalla o una instruccin de control para el display.

Para reducir al mximo las conexiones entre el micro y el LCD, se usar la modalidad de interconexin
de datos a 4 bit, usando slo las lneas DB4, DB5, DB6, DB7. Las lneas DB0, DB1, DB2 y DB3 no
sern usadas y sern conectadas a tierra.

Tampoco la lnea R/W# ser utilizada por lo que ser puesta a tierra. De este modo, quedar
seleccionado el modo escritura. En la prctica, slo se podr enviar datos al LCD pero no recibirlos.

a) La lnea Register Select (RS) y Enable (E) del LCD

Para poder visualizar una frase en el LCD, el PIC debe enviar una serie de comandos a travs del
bus de datos (lneas DB4 a DB7). Para hacer esto, son utilizadas dos lneas de control con las que
se comunica al LCD la operacin de transferencia que realizar el bus.

Las dos lneas de control son Register Select (pin 4) y Enable (pin 6) del LCD, las cuales se
describen a continuacin:

Con la lnea Register Select, el PIC indica al display que el dato presente en el bus es un
comando ( RS=0 ) o un dato a ser visualizado ( RS=1 ). A travs de los comandos, el PIC puede
indicar al LCD el tipo de operacin a realizar, como por ejemplo "limpiar pantalla". Con los
datos, el PIC puede enviar directamente los caracteres ASCII a ser visualizados.

La lnea Enable habilita al LCD para leer el comando o el dato enviado en el bus por el PIC. El
PIC debe ocuparse de haber enviado en el bus de datos el comando o el dato correcto antes de
poner a 1 la seal Enable.

b) Mutiplexado sobre el bus de datos

Puesto que los comandos son datos de 8 bits Cmo es posible enviarlos al LCD si el bus de datos
dispone slo de 4 lneas?

En la prctica se usa la operacin de multiplexado, es decir, cada bit es descompuesto en dos


grupos de 4 bit y transmitidos por el bus de datos en secuencia. Son enviados primero los 4 bit
menos significativos seguidos de los 4 bit ms significativos.

En el ejemplo a desarrollar, todas las operaciones de transmisin de datos y comandos hacia el


LCD son seguidas de una serie de subrutinas, simplificando de esa manera la complejidad del
programa.

Los mdulos LCD responden a un conjunto especial de instrucciones, estas deben ser enviadas por el
microcontrolador o sistema de control al display, segn la operacin que se requiera. Se muestran en la
Tabla 2 el conjunto de instrucciones del mdulo LCD.

36
Tabla 2. Conjunto de instrucciones del mdulo LCD
Cdigo de Operacin Tiempo de
Instruccin Descripcin
RS R/W B7 B6 B5 B4 B3 B2 B1 B0 Ejecucin
Borra el contenido de la pantalla y
Clear display 0 0 0 0 0 0 0 0 0 1 retorna el cursor a la posicin home 1.52 ms
(direccin 0).
Retorna el cursor a la posicin
Home. Retorna tambin el rea de
Cursor home 0 0 0 0 0 0 0 0 1 * visin a la posicin inicial. El 1.52 ms
contenido de la DDRAM permanece
intacto.
Incrementar/Decrementar direccin
(I/D); Habilitar corrimiento de
Entry mode set 0 0 0 0 0 0 0 1 I/D S 37 s
pantalla (S). Estas operaciones se
realizan al leer o escribir datos
Enciende o apaga el display (D),
Display on/off
0 0 0 0 0 0 1 D C B Cursor encendido / apagado (C), 37 s
control
destello del cursor (blink) (B).
Selecciona entre desplazamiento de
pantalla o de cursor (S/C), selecciona
Cursor/display
0 0 0 0 0 1 S/C R/L * * la direccin de desplazamiento (R/L). 37 s
shift
El contenido de la DDRAM
permanece intacto.
Configurar en ancho de bus (4 u 8
Function set 0 0 0 0 1 DL N F * * bits) (DL), Nmero de lneas de 37 s
display (N), y tipo de fuente (F).
Escribe la direccin de CGRAM. Los
Set CGRAM Direccin generador de datos a almacenar en CGRAM pueden
0 0 0 1 37 s
address RAM ser enviados despus de esta
instruccin
Escribe la direccin de DDRAM. Los
Set DDRAM datos a almacenar en DDRAM pueden
0 0 1 Direccin de datos RAM 37 s
address ser enviados despus de esta
instruccin
Leer bandera Ocupado (Bussy Flag)
indicando si el controlador est
Read busy flag realizando alguna operacin interna o
&address 0 1 BF CGRAM/DDRAM address est listo para aceptar datos/comandos. 0 s
counter Lee la direccin CGRAM o DDRAM
(dependiendo de la instruccin
previa).
Write CGRAM Escribe datos a las memorias CGRAM
1 0 Escritura de Dato 37 s
orDDRAM o DDRAM.
Read from Lee datos desde las memorias
1 1 Lectura de Dato 37 s
CG/DDRAM CGRAM o DDRAM.

NOTA: ntese que el pin RS# debe tomar el valor 0 (cero) cuando lo que se va a enviar es una
instruccin de control y debe tomar el valor 1 (uno) cuando lo que se va a enviar es un dato.

En la Tabla 3 se muestra los nombres y significado de bits en instrucciones.

37
Tabla 3. Significado de las abreviaturas
SIGNIFICADO DE LAS ABREVIATURAS
(Nombres y significado de bits en instrucciones)
I/D 0 = disminuir el contador de direccin, 1 = incrementar el contador de direccin;

S 0 = Sin corrimiento de display, 1 = Con corrimiento de display;

D 0 = Display Apagado, 1 = Display Encendido;

C 0 = Cursor Apagado, 1 = Cursor Encendido;

B 0 = Parpadeo cursor Apagado, 1 = Parpadeo Cursor Encendido;

S/C 0 = Mover Cursor, 1 = Corrimiento de pantalla;

R/L 0 = Mover/Correr a la izquierda, 1 = Mover/Correr a la derecha;

DL 0 = Interfaz de 4 bits, 1 = Interfaz de 8 bits;

N 0 = 1 lnea, 1 = 2 lneas;

F 0 = 58 puntos, 1 = 510 puntos;

BF 0 = puede aceptar instruccin, 1 = operacin interna en progreso.

Nota: Cuando se va a cargar la direccin de la DDRAM donde se va a escribir el prximo caracter,


ntese que el D7 siempre es 1. Por lo tanto cuando se apunta a una direccin de memoria en el display
hay que considerar este 1 adicional. Se ver con ms detalle al describir el mapa de memoria del
mdulo LCD.

La interface entre el microcontrolador y el LCD se puede hacer con el bus de datos del PIC trabajando
a 4 u 8 bits. Las seales de control trabajan de la misma forma en cualquiera de los dos casos, la
diferencia se establece en el momento de iniciar el display, ya que existe una instruccin que permite
establecer dicha configuracin. O sea se tiene que avisarle al LCD que se va a operar en 8 o a 4 bits.

Los caracteres que se envan al display se almacenan en la memoria RAM del mdulo. Existen
posiciones de memoria RAM, cuyos datos son visibles en la pantalla y otras que no son visibles, estas
ltimas se pueden utilizar para guardar caracteres que luego se desplazan a la zona visible.

Es importante anotar que solo se pueden mostrar caracteres ASCII de 7bits, por lo tanto algunos
caracteres especiales no se pueden ver (es aconsejable tener a mano una tabla de caracteres ASCII para
conocer los datos que son prohibidos). Tambin se tiene la opcin de mostrar caracteres especiales
creados por el programador y almacenarlos en la memoria RAM que posee el mdulo.

11.3. Interfaz con Microcontrolador a 8 Bits

http://www.bolanosdj.com.ar/SOBRELCD/TEORIALCDV1.pdf

El HD44780 permite conectarse a travs de un bus de 4 u 8 bits. El modo de 4 bits permite usar solo 4
pines para el bus de datos, dndonos un total de 6 o 7 pines requeridos para la interfaz con el LCD,

38
mientras que el modo de 8 bits requiere 10 u 11 pines. El pin RW es el nico que puede omitirse si se
usa la pantalla en modo de solo escritura y deber conectarse a tierra si no se usa. En este caso el
microcontrolador no puede leer desde el chip controlador de pantalla, pero en la mayora de las
situaciones esto no es necesario.

11.3.1. Conexin bsica de una pantalla lcd 162 con una interface de 8 bits

Las conexiones para el modo de 8 bits son algo ms complicadas, ya que se requiere las 8 lneas de
datos activas. En este caso se utiliza los 8 bits del puerto B, aunque se puede usar cualquier
combinacin de pines. RA0 ahora funciona como seal de seleccin de registro (RS) y RA1 como
seal de habilitacin (E). En la Figura 2 se muestra las conexiones para el modo de 8 bits en un
PIC16F877.

Figura 2. Las conexiones para el modo de 8 bits en un PIC16F877

11.3.2. Configuracin de las instrucciones con una interface de 8 bits

Esta forma de manejo es la ms sencilla de programar, pero tiene la desventaja de utilizar 8 pines del
microcontrolador solo para el envo de datos y otros 2 pines para las seales de control.

En principio en la mayor parte de las aplicaciones se va requerir escribir en el LCD y rara vez leer en el
mismo, por lo tanto en este curso se dedicar exclusivamente a escribir en el LCD. Esto implica que el
pin de seleccin de lectura/escritura (R/W) se conectar siempre a tierra GND.

Si se utiliza el puerto B como bus de datos (manejar los pines D0 a D7 del LCD) y el puerto A se
encarga de manejar las seales de control (manejar los pines E y RS del LCD).

39
Se debe programar 2 subrutinas, una que se llama INSTRUC que ser invocada cuando se quiera enviar
una instruccin al mdulo LCD, por ejemplo limpiar pantalla, indicar una posicin de memoria, indicar
si se utiliza interfaz de 8 o 4 bits etc. Y otra subrutina que se llama ESCRIB que ser invocada cuando
se quiera escribir un dato para ser visualizado en el mdulo LCD.

Se configurar entonces todo el puerto B como salida al igual que los pines RA0 y RA1 del puerto A,
estando asignado cada pin del puerto como se indica a continuacin:

Pin PORTB RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
Pin LCD D7 D6 D5 D4 D3 D2 D1 D0

Pin PORTA RA5 RA4 RA3 RA2 RA1 RA0


Pin LCD E RS

RS = 1 DATO (o sea se va a escribir)


RS = 0 CONTROL (o sea se va a enviar un instruccin al mdulo LCD).

RECORDAR: Como solo se va a escribir en pantalla, el pin R/W vale siempre 0 (cero), as que se lo
conecta directamente a tierra.

Evidentemente se debe configurar el PORTB del PIC como salida, y en el PORTA los pines RA0 y
RA1 deben ser configurados como salidas. El resto de los pines del PORTA se puede configurar como
se desee. Recuerde que se est basando esta explicacin para interface de 8 bits.

Lo primero que hay que hacer es mandar una serie de instrucciones al mdulo LCD que constituyen la
configuracin del mismo. Luego recin se podr escribir el mensaje a presentar en pantalla.

11.3.3. Instrucciones muy importantes (son independientes a que se use interface de 4 u 8 bits)

ACTIVAR FUNCION (Instruccin)

Se informa el tipo de interfaz que se va a usar, 4 o 8 bits. La cantidad de lneas (1 o 2). La fuente de
caracter (5x8 dots o 5x10 dots).

RS R/W# D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 0 DL N F - -

DL = 0 interfaz de 4 bits.
DL = 1 interfaz de 8 bits.

N=0 se va a usar 1 sola lnea del display.


N=1 se van a usar 2 lneas del display.

F=0 fuente de caracter 5x8 dots.


F=1 fuente de caracter 5x10 dots.

Entonces si se enva al PORTB 30h

40
D7 D6 D5 D4 D3 D2 D1 D0
0 0 1 1 0 0 0 1

DL = 1 interfaz de 8 bits.
N=0 se va a usar 1 sola lnea del display.
F=0 fuente de caracter 5x8 dots.

Ahora se debe llamar a la subrutina INSTRU (esta subrutina debe ser creada por el programador, se le
puede dar el nombre que se quiera), la cual va a enviar 30h al PORTB, hacer RS=0 o sea le dice al
LCD que lo que va a recibir es una instruccin (RA0= 0 del PORTA) y E=1 o sea habilita al LCD
(RB1= 0 del PORTA), luego vuelve a hacer E=0 deshabilita.

ACTIVAR DISPLAY (Instruccin)

Configura el estado ON/OFF de todo el display, el estado del cursor y el parpadeo del caracter en la
posicin del cursor.

RS R/W# D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 0 0 1 D C B

RS se maneja con PORTA


RW# se conecta a tierra

Donde:

D=1 enciende pantalla (activar)


D=0 apaga pantalla (desactivar)

C=1 activar cursor


C=0 desactivar cursor

B=1 parpadea caracter sealado por el cursor


B=0 no parpadea caracter.

Por ejemplo, si envi 0Ch al PORTB

D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 1 1 0 0

Se est diciendo:

D=1 encienda la pantalla


C=0 desactivar cursor
B=0 no parpadeo del caracter

Ahora se debe llamar nuevamente a la subrutina INSTRU (esta subrutina debe ser creada por el
programador, se le puede dar el nombre que se quiera), la cual va a enviar 0Ch al PORTB, hacer RS=0
41
o sea le dice al LCD que lo que va a recibir es una instruccin (RA0=0 del PORTA) y E=1 o sea
habilita al LCD (RB1= 0 del PORTA), luego vuelve a hacer E=0 deshabilita.

BORRAR PANTALLA (Instruccin)

Limpia pantalla y retorna el cursor al inicio (direccin 00h del display).

RS R/W# D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 0 0 0 0 0 1

Se invoca la subrutina INSTRUC.

SELECCIONAR MODO (Instruccin)

Selecciona el modo de desplazamiento del display y se desplaza o no el cursor.

RS R/W# D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 0 0 0 1 ID S

S=0 display no se desplaza, dato fijo en pantalla.


S=1 display se desplaza.

ID = 1 incremento.
ID = 0 decremento.

En el ejemplo se enva al PORTB 06h.

D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 0 1 1 0

S=0 dato fijo en pantalla

NOTAR que los unos enviados a D2 y D1 carecen de sentido porque no hay desplazamiento.

Se invoca la subrutina INSTRUC.

Hasta aqu se han enviado las instrucciones previas para inicializar el mdulo LCD y dejarlo listo para
la escritura de datos en pantalla.

El envi de los datos se realiza por medio de los pines D0 a D7 del LCD, que se encuentran conectados
a los pines RB0 a RB7 del PORTB B del PIC. Por lo tanto los datos a escribir deben ser enviados a
travs del PORTB B.

Un dato se enva por medio de su cdigo ASCII, pero previamente se debe indicar al mdulo la
posicin de memoria en que deseo escribir el dato que se enviar a continuacin. Esto se hace por
medio de la instruccin DDRAM.

42
DDRAM (Instruccin)

Le informa al mdulo LCD la direccin de memoria en la cual se va almacenar el cdigo del dato que
se le enviar a continuacin.

RS R/W# D7 D6 D5 D4 D3 D2 D1 D0
0 0 1 Posicin de memoria a escribir dato

Luego se invoca a subrutina INSTRUC, ya que es una instruccin para el LCD.

NOTA: el 1 en D7 debe ir siempre.

Se aclara algo para no confundirse. Supngase que se desea escribir 'A' en la posicin de memoria 00h
del LCD.

Como se tiene que asegurar el 1 en el D7 se debe enviar al PORTB (recordar que D0 ... D7 del LCD
est conectado a RB0 ... RB7 del PORTB) en lugar de 00h el 80h, esto es para asegurar el 1 en el D7
(el 1 en D7 hace 00000000 se convierta en 10000000 o sea 80h).

As quedar en este caso:

D7 D6 D5 D4 D3 D2 D1 D0
1 0 0 0 0 0 0 0

Ahora que se le informa donde se va a escribir el dato, se debe enviarlo y aclararle que se est enviando
un dato, para lo cual se necesita una subrutina que justamente har esto y que se la llamar ESCRIB.

La secuencia de instrucciones sera as:

MOVLW 80h ;carga en W la direccin de memoria del LCD donde se va


almacenar el dato
CALL INSTRUC ;subrutina que gestiona la instruccin con el LCD, en este caso
que tome lo que se est enviando como una direccin de
memoria
MOVLW 'A' ;este es el dato a presentar en pantalla
CALL ESCRIB ;subrutina que gestiona el ingreso del dato al LCD a la posicin
de memoria antes enviada.

MAPA DE LA MEMORIA DEL MODULO LCD

En la Tabla 4. Se muestra el Mapa de la Memoria del Mdulo LCD (2 lneas x 16 caracteres).

43
Tabla 4. Mapa de la Memoria del Mdulo LCD (2 lneas x 16 caracteres)

00h 01h 02h 03h 04h 05h 06h 07h 08h 09h 0Ah 0Bh 0Ch 0Dh 0Eh 0Fh 10h --- 1Fh

40h 41h 42h 43h 44h 45h 46h 47h 48h 49h 4Ah 4B 4C 4D 4Eh 4Fh 50h --- 5Fh

rea no
rea visible visible - 16
posiciones

Como se haba mencionado anteriormente, al enviar una direccin hay que asegurar el 1 en D7

Por ejemplo:

D7 D6 D5 D4 D3 D2 D1 D0
1 0 0 0 0 0 0 0

De este modo se podra pensar en un mapa de memoria equivalente del mdulo LCD como muestra en
la Tabla 5, en el caso de solo utilizar la zona visible.

Tabla 5. Mapa de la Memoria del Mdulo LCD de la zona visible

80h 81h 82h 83h 84h 85h 86h 87h 88h 89h 8Ah 8Bh 8Ch 8Dh 8Eh 8Fh

C0h C1h C2h C3h C4h C5h C6h C7h C8h C9h CAh CB CC CD CEh CFh

Ejemplo 6

A continuacin se transcribe la solucin completa al ejemplo de escribir en el display el mensaje


'HOLA MUNDO'. Se recomienda observar con detalle las subrutinas INSTRUC y ESCRIB que operan
con interfaz de 4 bit. Se utiliza PIC16F84.

El circuito con interface de 8 bits en Proteus se muestra en la Figura 3.

44
LCD1
LCD16x2

VDD
VSS

VEE

RW
RS

D0
D1
D2
D3
D4
D5
D6
D7
E
1
2
3

4
5
6

7
8
9
10
11
12
13
14
BOXER
13 33
OSC1/CLKIN RB0/INT
14 34
OSC2/CLKOUT RB1
X1 1 35
MCLR/Vpp/THV RB2
36
RB3/PGM
2 37
RA0/AN0 RB4
3 38
RA1/AN1 RB5
20Mhz R1 4
RA2/AN2/VREF- RB6/PGC
39
10k 5 40
RA3/AN3/VREF+ RB7/PGD
C2 C1 6
RA4/T0CKI
22p 22p 7 15
RA5/AN4/SS RC0/T1OSO/T1CKI
16
RC1/T1OSI/CCP2
8 17
RE0/AN5/RD RC2/CCP1 VDD
9 18
RE1/AN6/WR RC3/SCK/SCL
10 23
VDD RE2/AN7/CS RC4/SDI/SDA
24
RC5/SDO
25
RC6/TX/CK
26
RC7/RX/DT
19
RD0/PSP0
20
RD1/PSP1
21
RD2/PSP2
22
RD3/PSP3
27
RD4/PSP4
28
RD5/PSP5
29
RD6/PSP6
30
RD7/PSP7
PIC16F877

Figura 3. Circuito en Proteus con interface de 8 bits

;muestra en LCD - HOLA MUNDO en interfase de 8 bits

processor 16f877
include <p16f877.inc>

;Define variables
cblock 0x20
temp5
endc

org 00
inicio
bsf STATUS,5 ;se posiciona en banco1
clrf TRISB ;define el PORTB como salida
clrf TRISA ;define el PORTA como salida
movlw 06h ; carga w con literal 06h
movwf ADCON1; carga ADCON1 con w = 06h para entradas digitales
bcf STATUS,5

;-------inicializacion del LCD--------

;------------Una instruccion-----------
movlw 30h; carga w con literal 30h
;la intrucc asociada dice: interface de datos de 8 bits y se va a usar
;1 linea - corresponde a la intruccion ACTIVAR FUNCION
call instruc; enviaremos este valor al PORTB y por lo tanto al LCD

45
;------------otra instruccion-----------
movlw 06h; carga w con literal 06h
;la intrucc asociada dice: dato fijo en pantalla- corresponde a la intruccion
;SELECCIONAR MODO
call instruc; enviaremos este valor al PORTB y por lo tanto al LCD

;------------otra instruccion-----------
movlw 0Ch; carga w con literal 0Ch
;la intrucc asociada dice: encienda la pantalla y desactive el cursor-
;corresponde a la intruccion ENCENDER O APAGAR PANTALLA
call instruc; enviaremos este valor al PORTB y por lo tanto al LCD

;------------otra instruccion-----------
movlw 01h; carga w con literal 01h
;la intrucc asociada dice: BORRAR PANTALLA
call instruc; enviaremos este valor al portb y por lo tanto al LCD

;----fin inicializacion del LCD-----

;---escritura de datos---------------
movlw 80h; se indica posicion de memoria del LCD en que quiere
; escibir el dato
call instruc
movlw " "; este es dato - al estar entre comillas se le indica al
; compilador que el dato requerido es el valor ASCII del
; caracter
call escrib

;repito con el resto de los datos

movlw 81h;
call instruc
movlw "H";
call escrib

movlw 82h;
call instruc
movlw "O";
call escrib

movlw 83h;
call instruc
movlw "L";
call escrib

movlw 84h;
call instruc
movlw "A";
call escrib

movlw 85h;
call instruc
movlw " ";
call escrib

movlw 86h;
call instruc
movlw "M";
call escrib

46
movlw 87h;
call instruc
movlw "U";
call escrib

movlw 88h;
call instruc
movlw "N";
call escrib

movlw 89h;
call instruc
movlw "D";
call escrib

movlw 8Ah;
call instruc
movlw "O";
call escrib

movlw 8Bh;
call instruc
movlw ".";
call escrib

movlw 8Ch;
call instruc
movlw ".";
call escrib
;---fin escritura de datos-----------

;--------SUBRUTINAS-------------

;----------------------------------------
;Subrutina que manda una instruccion al LCD
instruc
bcf PORTA,0 ; hace 0 el bit 0 del PORTA o sea hace RS=0 - Le dice
; al LCD que es una intruccion lo que va a recibir
bsf PORTA,1 ; hace 1 el bit 1 del PORTA - O sea E=1 habilita LCD
movwf PORTB; carga contenido de w en PORTB
call retardo
bcf PORTA,1; hace 0 el bit 1 del PORTA - O sea E=0 habilita LCD
call retardo
return

;----------------------------------------
;Subrutina que manda un dato al LCD
escrib
bsf PORTA,0 ; hace 1 el bit 0 del PORTA o sea hace RS=1 - Le dice
; al LCD que es es un dato lo que va a recibir
bsf PORTA,1 ; hace 1 el bit 1 del PORTA - O sea E=1 habilita LCD
movwf PORTB; carga contenido de w en PORTB
call retardo
bcf PORTA,1; hace 0 el bit 1 del PORTA - O sea E=0 habilita LCD
call retardo
return

;----------------------------------------
;Subrutina retardo
retardo
47
movlw 0ffh; carga literal 0ffh en w
movwf temp5; mueve contenido de w a temp5
decr
decfsz temp5,1 ; decrementa temp5 y guarda resultado en temp5- salta
; la intruccion siguiente si temp es igual a cero
goto decr
return

;--------FIN SUBRUTINAS--------

end

Ejemplo 7 (Otra Aplicacin con interface de 8 bits)

Realizar una aplicacin que muestre el siguiente mensaje en el lcd 2x16, en forma repetida, con un
tiempo de muestreo de 1 seg:

Hello World! Primera columna


Im OpenBoxer Segunda columna

1. Diagrama de Conexiones

Figura 4. muestra las conexiones para el modo de 8 bits en un PIC16F877

Figura 4. Las conexiones para el modo de 8 bits en un PIC16F877

2. El cdigo es el siguiente:
48
processor 16F877
include <P16F877.INC>

;Variables para DELAY


cblock 0x30
val1
val2
endc

org 0 ;Vector de RESET

;Configuracin de puertos
clrf PORTB ;Limpia PORTB
clrf PORTD ;Limpia PORTD
bsf STATUS, RP0
bcf STATUS, RP1 ;Selecciona el banco 1
clrf TRISB ;Configura PORTB como salida
clrf TRISD ;Configura PORTD como salida
bcf STATUS,RP0 ;Regresa al banco 0

START_LCD:
call INICIA_LCD ;Configura el LCD
call M1 ;Muestra Mensaje
call LINEA2 ;Configura lnea 2
call M2 ;Muestra Mensaje
goto START_LCD

;Mensaje a enviar
M1:
movlw 'H' ;Mueve 'H' a W
movwf PORTB ;Mueve lo que hay en W a PORTB
call ENVIA ;Imprime en LCD
movlw 'e'
movwf PORTB
call ENVIA
movlw 'l'
movwf PORTB
call ENVIA
movlw 'l'
movwf PORTB
call ENVIA
movlw 'o'
movwf PORTB
call ENVIA
movlw ' '
movwf PORTB
call ENVIA
movlw 'W'
movwf PORTB
call ENVIA
movlw 'o'
movwf PORTB
call ENVIA
movlw 'r'
movwf PORTB
call ENVIA
movlw 'l'
movwf PORTB
call ENVIA
movlw 'd'
49
movwf PORTB
call ENVIA
movlw '!'
movwf PORTB
call ENVIA
return
M2:
movlw 'I' ;Mueve 'I' a W
movwf PORTB ;Mueve lo que hay en W a PORTB
call ENVIA ;Imprime en LCD
movlw 'm'
movwf PORTB
call ENVIA
movlw ' '
movwf PORTB
call ENVIA
movlw 'O'
movwf PORTB
call ENVIA
movlw 'p'
movwf PORTB
call ENVIA
movlw 'e'
movwf PORTB
call ENVIA
movlw 'n'
movwf PORTB
call ENVIA
movlw 'B'
movwf PORTB
call ENVIA
movlw 'o'
movwf PORTB
call ENVIA
movlw 'x'
movwf PORTB
call ENVIA
movlw 'e'
movwf PORTB
call ENVIA
movlw 'r'
movwf PORTB
call ENVIA
return

;Subrutina para inicializar el lcd


INICIA_LCD:
bcf PORTD,0 ; RS=0 MODO INSTRUCCION
movlw 0x01 ; El comando 0x01 limpia la pantalla en el LCD
movwf PORTB
call COMANDO ; Se da de alta el comando
movlw 0x0C ; Selecciona la primera lnea
movwf PORTB
call COMANDO ; Se da de alta el comando
movlw 0x3C ; Se configura el cursor
movwf PORTB
call COMANDO ; Se da de alta el comando
bsf PORTD, 0 ; RS=1 MODO DATO
return

50
;Subrutina para enviar comandos
COMANDO:
bsf PORTD,1 ; Pone ENABLE en 1
call DELAY ; Tiempo de espera
call DELAY
bcf PORTD, 1 ; ENABLE=0
call DELAY
return

;Subrutina para enviar un dato


ENVIA:
bsf PORTD,0 ; RS=1 MODO DATO
call COMANDO ; Se da de alta el comando
return

;Configuracin Lneal 2 LCD


LINEA2:
bcf PORTD, 0 ; RS=0 MODO INSTRUCCION
movlw 0xc0 ; Selecciona lnea 2 en el LCD
movwf PORTB
call COMANDO ; Se da de alta el comando
return

; Subrutina de retardo
DELAY:
movlw 0xFF
movwf val2
ciclo:
movlw 0xFF
movwf val1
ciclo2:
decfsz val1,1
goto ciclo2
decfsz val2,1
goto ciclo
return
END

11.4. Manejo del Lcd con Interfaz de 4 Bits

11.4.1. Conexin bsica de una pantalla lcd 162 con una interface de 4 bits

Las conexiones para el modo de 4 bits en un PIC16F877 se muestran en la Figura 5. Se utilizan los
primeros 4 bits del puerto A (RA0-RA3) como bus de datos. RB0 como seal de habilitacin (E) y
RB1 como seal de seleccin de registro (RS).

51
Figura 5. Las conexiones para el modo de 4 bits en un PIC16F877

11.4.2. Configuracin de las instrucciones con una interface de 4 bits

Es el caso ms utilizado para aprovechar los puertos del PIC. Dejando disponibles pines de los mismos
para otras funciones.

Por ejemplo si se usa el PORTB:

RB4 RB5 RB6 RB7 respectivamente conectados a D4 D5 D6 D7

RB0 RB1 a RS y E respectivamente

RW va a tierra

Las subrutinas INSTRUC y ESCRIB sern diferentes que para el caso de interfaz de 8 bits. Estas
enviaran primero los 4bit MSB y luego los 4 bits LSB.

Ejemplo 8

El programa presenta los siguientes mensajes en el LCD con interfaz de 4 bits:

(C) DJB_2009 Primera fila


E Segunda fila

Repite los siguientes mensajes:

Limpia la pantalla
52
(C) DJB_2009 Primera fila

Limpia la pantalla
RECREO Primera fila

Limpia la pantalla
ALARMA Primera fila

El circuito con interface de 4 bits en Proteus se muestra en la Figura 6.

LCD1
LCD16x2

VDD
VSS

VEE

RW
RS

D0
D1
D2
D3
D4
D5
D6
D7
E
1
2
3

4
5
6

7
8
9
10
11
12
13
14
BOXER
13 33
OSC1/CLKIN RB0/INT
14 34
OSC2/CLKOUT RB1
X1 1 35
MCLR/Vpp/THV RB2
36
RB3/PGM
R1 2
RA0/AN0 RB4
37
10k 3 38
RA1/AN1 RB5
4 39
20Mhz RA2/AN2/VREF- RB6/PGC
5 40
RA3/AN3/VREF+ RB7/PGD
C2 C1 6
RA4/T0CKI
22p 22p 7 15
RA5/AN4/SS RC0/T1OSO/T1CKI
16
RC1/T1OSI/CCP2
8 17
VDD RE0/AN5/RD RC2/CCP1 VDD
9 18
RE1/AN6/WR RC3/SCK/SCL
10 23
RE2/AN7/CS RC4/SDI/SDA
24
RC5/SDO
25
RC6/TX/CK
26
RC7/RX/DT
19
RD0/PSP0
20
RD1/PSP1
21
RD2/PSP2
22
RD3/PSP3
27
RD4/PSP4
28
RD5/PSP5
29
RD6/PSP6
30
RD7/PSP7
PIC16F877

Figura 6. Circuito en Proteus con interface de 4 bits

;muestra en LCD -MENSAJES en interface de 4 bits, se usara 4 bits MSB del


;PORTB para envio de datos a 4bits - RB4 RB5 RB6 RB7 respectivamente
;conectados ;a D4 D5 D6 D7 y RB0 RB1 a RS y E ;respectivamente- RW va a tierra.
;---------------------------------------------------------------------

processor 16f877
include <p16f877.inc>

;Comienza listado de registros de proposito general empleados en este


;programa
;Define variables
cblock 0x20
;--------------registros de subrutina retardo-------------
temp5
;--------------registros de subrutina INSTRUC/ESCRIB---------
aux
;------------- registros de subrutina espera y larga--------
tempo1
tempo2
53
tempo3
endc
;--------Fin del listado de registros de proposito general empleados en este

;------INICIO programa principal-----

org 00
inicio
bsf STATUS,5 ;se posiciona en banco1
clrf TRISB ;define el PORTB como salida
movlw b'00001100'
movwf TRISA
movlw 06h ; carga w con literal 06h
movwf ADCON1; carga ADCON1 con w = 06h para entradas digitales

bcf STATUS,5; se posiciona en banco 0

call lcd; se llama subrutina de inicializacion del LCD

call copyright; escribe copyright


call largaespera

mostrar
btfsc PORTA,2 ; si en el pin 2 del PORTA hay un 0 entonces muestra
; mensaje1-alternado con mensaje3
goto frase2
call mensaje1
call espera
frase2
btfsc PORTA,3 ; si en el pin 3 del PORTA hay un 0 entonces muestra
; mensaje2-alternado con mensaje3
goto frase3
call mensaje2
call espera
frase3
call copyright ; si recibe un 0 en pines 2 y 3 de PORTA muestra
; mensaje3
call espera
goto mostrar

;---fin programa principal-----------

;--------SUBRUTINAS-------------

;-------Subrutina LCD ------------------------------------


;esta subrutina inicia la pantalla LCD
;esta subrutina no utiliza registros de proposito general
lcd
;------------una instruccion-----------
movlw 02h; carga w con literal 02h RB1=1 o sea E=1 habilito LCD
call instruc; enviaremos este valor al PORTB y por lo tanto al LCD

;------------otra instruccion-----------
movlw 28h; carga w con literal 28h
;la intrucc asociada dice: interfase de datos de 4 bits y se va a usar 2
;lineas - corresponde a la intruccion ACTIVAR FUNCION
call instruc; enviaremos este valor al PORTB y por lo tanto al LCD

;------------otra instruccion-----------
movlw 06h; carga w con literal 06h
54
;la intrucc asociada dice: dato fijo en pantalla- corresponde a la intruccion
;SELECCIONAR MODO
call instruc; enviaremos este valor al PORTB y por lo tanto al LCD

;------------otra instruccion-----------
movlw 0Ch; carga w con literal 0Ch
;la intrucc asociada dice: encienda la pantalla y desactive el
;cursor- corresponde a la intruccion ENCENDER O APAGAR PANTALLA
call instruc; enviaremos este valor al PORTB y por lo tanto al LCD

;------------otra instruccion-----------
movlw 01h; carga w con literal 01h
;la intrucc asociada dice: BORRAR PANTALLA
call instruc; enviaremos este valor al PORTB y por lo tanto al LCD

return
;-------Fin Subrutina LCD --------

;--------------------Subrutina INSTRC/ESCRIB-------------------------
;Subrutina que manda una instruccion o dato al LCD
;Esta subrutina utiliza el registro de proposito general aux
instruc
bcf PORTB,0; RB0=0 o sea RS=0 es una instruccion para LCD
goto dato2
escrib
bsf PORTB,0; RB0=1 o sea RS=1 es una dato para LCD

dato2
;lo que se va hacer es para no alterar el contenido de los 4 bit menos
;significativos del PORTB
movwf aux; guarda contenido de w en aux
movlw 0fh; carga 00001111 en w
andwf PORTB,1 ; AND entre w=00001111 y PORTB y guarda resultado en
; PORTB
;lo que se termino de hacer es para no alterar el contenido de los 4 bit
;menos significativos dell PORTB

movf aux,0; carga aux en w


andlw b'11110000'; AND entre literal 11110000 y w en el cual esta
; copiado aux (guarda el resultdado en w)
iorwf PORTB,1; OR entre w y PORTB - guarda resultado en PORTB
bsf PORTB,1; RB1=1 o sea E=1 habilito LCD
call retardo
bcf PORTB,1; RB1=E=0 deshabilita LCD
call retardo
;---termin envio 4 bit MSB-------

;---comienza el envio de 4 bit LSB---


movlw 0fh; carga 00001111 en w
andwf PORTB,1 ; AND entre w=00001111 y PORTB - guarda resultado en
; PORTB
swapf aux,0; intercambia NIBLES de aux y lo guarda en w
andlw b'11110000'; AND entre literal 11110000 y w en el cual esta
; copiado aux con los NIBLES intercambiados
;(guarda el resultdado en w)
iorwf PORTB,1; OR entre w y PORTB - guarda resultado en PORTB
;lo que se termino de hacer es para no alterar el contenido de los 4 bit
;menos significativos dell PORTB

bsf PORTB,1; RB1=1 o sea E=1 habilito LCD


55
call retardo
call retardo
bcf PORTB,1; RB1=E=0 deshabilita LCD
call retardo
;---termino el envio de lo 4bit LSB---

return
;---------Fin subrutina que manda instruccion o dato al LCD------

;------------------Fin Subrutina INSTRC/ESCRIB------------------------


;----------------Subrutina retardo----------------------------------
;Esta subrutina utiliza el registro de proposito general temp5
retardo
movlw 0ffh; carga literal 0ffh en w
movwf temp5; mueve contenido de w a temp5
decr
decfsz temp5,1 ; decrementa temp5 y guarda resultado en temp5- salta
; la intruccion siguiente si temp5 es igual a cero
goto decr
movlw 0ffh; carga literal 0ffh en w
movwf temp5; mueve contenido de w a temp5
decr2
decfsz temp5,1 ; decrementa temp5 y guarda resultado en temp5- salta
; la intruccion siguiente si temp5 es igual a cero
goto decr2
return
;---------------- Fin Subrutina retardo----------------------------------

;----------Subrutina largaespera - -----------------------


largaespera
;Escribe una E en display para indicar larga espera
movlw 0CFh;
call instruc
movlw "E";
call escrib
;Termino de escribir la E

retardo4
incf tempo1,1
retardo5
incf tempo2,1
retardo6
incf tempo3,1
btfss tempo3,7
goto retardo6
clrf tempo3
btfss tempo2,7
goto retardo5
clrf tempo2
btfss tempo1,7
goto retardo4
clrf tempo1

;Llama reiteradas veces a subrutina espera -para incrementar espera


;Tanto como subrutina espera y largaespera utilizan los mismos registros de
;proposito general
call espera
call espera
; Termino de llamar reiteradas veces a subrutina espera

56
;Limpia la E en display que escribio al principio
movlw 0CFh;
call instruc
movlw " ";
call escrib
;Termino de limpiar la E

return
;-----Fin subrutina largaespera-----------------------

;----------Subrutina espera -( Retardo general)--------


;Esta subrutina utiliza los registros de proposito general- temp1-temp2-temp3
;Son los mismos que utiliza la subrutina largaespera
espera nop
retardo1
incf tempo1,1
retardo2
incf tempo2,1
retardo3
incf tempo3,1
btfss tempo3,6
goto retardo3
clrf tempo3
btfss tempo2,5
goto retardo2
clrf tempo2
btfss tempo1,4
goto retardo1
clrf tempo1
return
;-------------------Fin subrutina espera------------

;---Subrutina copyright-----------
copyright
movlw 01h
; call instruc; borrar pantalla

movlw 80h; se indica posicion de memoria del LCD en que quiere


; escibir el dato
call instruc
movlw "("; este es el primer caracter del mensaje - al estar entre
; comillas se le indica al compilador que el dato requerido
; es el valor ASCII del caracter
call escrib

;repito con el resto de los caracteres


movlw 81h;
call instruc
movlw "c";
call escrib

movlw 82h;
call instruc
movlw ")";
call escrib

movlw 83h;
call instruc
movlw " ";
call escrib
57
movlw 84h;
call instruc
movlw "D";
call escrib

movlw 85h;
call instruc
movlw "J";
call escrib

movlw 86h;
call instruc
movlw "B";
call escrib

movlw 87h;
call instruc
movlw "-";
call escrib

movlw 88h;
call instruc
movlw "2";
call escrib

movlw 89h;
call instruc
movlw "0";
call escrib

movlw 8Ah;
call instruc
movlw "0";
call escrib

movlw 8Bh;
call instruc
movlw "9";
call escrib

call espera
call espera
call espera
call espera

return
;---Fin subrutina copyright-----------------------------------------------

;---Subrutina mensaje1-----------
mensaje1
movlw 01h
; call instruc; borrar pantalla

movlw 80h; se indica posicion de memoria del LCD en que quiere


; escibir el dato
call instruc
movlw "R"; este es el primer caracter del mensaje - al estar entre
; comillas se le indica al compilador que el dato requerido
58
; es el valor ASCII del caracter
call escrib

;repito con el resto de los caracteres


movlw 81h;
call instruc
movlw "E";
call escrib

movlw 82h;
call instruc
movlw "C";
call escrib

movlw 83h;
call instruc
movlw "R";
call escrib

movlw 84h;
call instruc
movlw "E";
call escrib

movlw 85h;
call instruc
movlw "O";
call escrib

movlw 86h;
call instruc
movlw ".";
call escrib

movlw 87h;
call instruc
movlw ".";
call escrib

movlw 88h;
call instruc
movlw ".";
call escrib

movlw 89h;
call instruc
movlw ".";
call escrib

movlw 8Ah;
call instruc
movlw ".";
call escrib

movlw 8Bh;
call instruc
movlw ".";
call escrib

59
call espera
call espera
call espera
call espera

return
;---Fin subrutina mensaje1-----------------------------------------------

;---Subrutina mensaje2-----------
mensaje2
movlw 01h
; call instruc; borrar pantalla

movlw 80h; se indica posicion de memoria del LCD en que quiere


; escibir el dato
call instruc
movlw "A"; este es el primer caracter del mensaje - al estar entre
; comillas se le indica al compilador que el dato requerido
; es el valor ASCII del caracter
call escrib

;repito con el resto de los caracteres


movlw 81h;
call instruc
movlw "L";
call escrib

movlw 82h;
call instruc
movlw "A";
call escrib

movlw 83h;
call instruc
movlw "R";
call escrib

movlw 84h;
call instruc
movlw "M";
call escrib

movlw 85h;
call instruc
movlw "A";
call escrib

movlw 86h;
call instruc
movlw ".";
call escrib

movlw 87h;
call instruc
movlw ".";
call escrib

movlw 88h;
call instruc
movlw ".";
60
call escrib

movlw 89h;
call instruc
movlw ".";
call escrib

movlw 8Ah;
call instruc
movlw ".";
call escrib

movlw 8Bh;
call instruc
movlw ".";
call escrib

call espera
call espera
call espera
call espera

return
;---Fin subrutina mensaje2-----------------------------------------------

;--------FIN SUBRUTINAS-------------

end

Ejemplo 9 (Otra Aplicacin con interface de 4 bits)

Ejemplo para la Gestin de un LCD.

Mostrar en el LCD la siguiente leyenda:

HELLO WORD!_

NOTA: Si no se logra ver nada en el LCD, tal vez, sea necesario regular el contraste del LCD a
travs de R2 conectado al pin 3 del LCD.

El circuito a ser utilizado para comprender mejor las explicaciones de la Gestin de un LCD, se
presenta en la Figura 7:

61
Figura 7. Circuito de la Gestin de un LCD

1. Diagrama de Flujo:
Diagrama de flujo del Programa Principal:

62
INICIO

RS2
E3
DB44
DB55
DB66
DB77

LcdInit

W10H

LcdLocate

WH

LcdSendData

.
.

W!

LcdSendData

Los diagramas de flujo de las subrutinas de este programa no se presentan, pero en la Tabla 5 se
describen brevemente las Subrutinas de gestin del LCD.

Tabla 5. Subrutinas de gestin del LCD


Subrutina Funcin
LcdInit Se ocupa de inicializar el display y de limpiar la pantalla. Debe ser llamada una sola vez y antes de cualquier otra
subrutina.

No requiere paso de parmetros.


LcdClear Limpia el contenido de pantalla y reposiciona el cursor en la primera fila y primera columna.

No requiere paso de parmetros.

63
LcdLocate Posiciona arbitrariamente el cursor dentro del rea visible del display.

Necesita el valor de fila y columna para posicionar el cursor en el registro W. Los bits desde D0 a D3 contienen
el valor de columna (eje Y) y los bits desde D4 a D7 los valores de filas (eje X). La numeracin de las filas parte
de cero hacia arriba, la de columna parte de cero hacia la derecha.
LcdSendData Enva el carcter ASCII al LCD a ser visualizado en la posicin donde se encuentra el cursor.

Requiere cargar en el registro W el valor ASCII del carcter.


LcdSendCommand Enva un comando al LCD. Los comandos reconocidos por el LCD, estn especificados en la hoja de datos del
mismo.

Requiere cargar en el registro W el valor de 8 bit del comando a enviar.


LcdSendByte Esta funcin, es usada internamente por las dems y se ocupa de efectuar el deslizamiento de los datos y comando
de 8 bit en el bus de datos de 4 bit.

2. Cdigo en Assembler:

El cdigo de este ejemplo se muestra a continuacin:

;**************************************************
;
; LCD.ASM
;
;**************************************************

PROCESSOR 16F877
RADIX DEC
INCLUDE "P16F877.INC"

__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

;LCD Control lines


LCD_RS equ 2 ;Register Select
LCD_E equ 3 ;Enable

;LCD data line bus


LCD_DB4 equ 4 ;LCD data line DB4
LCD_DB5 equ 5 ;LCD data line DB5
LCD_DB6 equ 6 ;LCD data line DB6
LCD_DB7 equ 7 ;LCD data line DB7

ORG 20H
tmpLcdRegister res 2
msDelayCounter res 2

Start
bsf STATUS,RP0 ;Swap to register bank 1

movlw 00000011B ; Set as output just the LCD's lines


movwf TRISB

bcf STATUS,RP0 ;Swap to register bank 0

;LCD inizialization
call LcdInit

;Locate LCD cursor on row 0, col 0


movlw 10H
64
call LcdLocate

;Shows "HELLO WORLD" string on LCD


movlw 'H'
call LcdSendData
movlw 'E'
call LcdSendData
movlw 'L'
call LcdSendData
movlw 'L'
call LcdSendData
movlw 'O'
call LcdSendData
movlw ' '
call LcdSendData
movlw 'W'
call LcdSendData
movlw 'O'
call LcdSendData
movlw 'R'
call LcdSendData
movlw 'L'
call LcdSendData
movlw 'D'
call LcdSendData
movlw ' '
call LcdSendData
movlw '!'
call LcdSendData

foreverLoop
goto foreverLoop

;**********************************************************************
; Delay subroutine
; W = Requested delay time in ms (clock = 4MHz)
;**********************************************************************

msDelay
movwf msDelayCounter+1
clrf msDelayCounter+0

; 1 ms (about) internal loop


msDelayLoop
nop
decfsz msDelayCounter+0,F
goto msDelayLoop
nop

decfsz msDelayCounter+1,F
goto msDelayLoop

return

;**********************************************************************
; Init LCD
; This subroutine must be called before each other lcd subroutine
;**********************************************************************

65
LcdInit
movlw 30 ;Wait 30 ms
call msDelay

;****************
; Reset sequence
;****************

bcf PORTB,LCD_RS ;Set LCD command mode

;Send a reset sequence to LCD


bsf PORTB,LCD_DB4
bsf PORTB,LCD_DB5
bcf PORTB,LCD_DB6
bcf PORTB,LCD_DB7

bsf PORTB,LCD_E ;Enables LCD


movlw 5 ;Wait 5 ms
call msDelay
bcf PORTB,LCD_E ;Disables LCD
movlw 1 ;Wait 1ms
call msDelay

bsf PORTB,LCD_E ;Enables LCD


movlw 1 ;Wait 1ms
call msDelay
bcf PORTB,LCD_E ;Disables LCD
movlw 1 ;Wait 1ms
call msDelay

bsf PORTB,LCD_E ;Enables E


movlw 1 ;Wait 1ms
call msDelay
bcf PORTB,LCD_E ;Disables E
movlw 1 ;Wait 1ms
call msDelay

bcf PORTB,LCD_DB4
bsf PORTB,LCD_DB5
bcf PORTB,LCD_DB6
bcf PORTB,LCD_DB7

bsf PORTB,LCD_E ;Enables LCD


movlw 1 ;Wait 1ms
call msDelay
bcf PORTB,LCD_E ;Disabled LCD
movlw 1 ;Wait 1ms
call msDelay

;Set 4 bit data bus length


movlw 28H;
call LcdSendCommand

;Entry mode set, increment, no shift


movlw 06H;
call LcdSendCommand

;Display ON, Curson ON, Blink OFF


movlw 0EH

66
call LcdSendCommand

;Clear display
call LcdClear

return

;**********************************************************************
; Clear LCD
;**********************************************************************

LcdClear
;Clear display
movlw 01H
call LcdSendCommand

movlw 2 ;Wait 2 ms
call msDelay

;DD RAM address set 1st digit


movlw 80H;
call LcdSendCommand

return

;**********************************************************************
; Locate cursor on LCD
; W = D7-D4 row, D3-D0 col
;**********************************************************************

LcdLocate
movwf tmpLcdRegister+0

movlw 80H
movwf tmpLcdRegister+1

movf tmpLcdRegister+0,W
andlw 0FH
iorwf tmpLcdRegister+1,F

btfsc tmpLcdRegister+0,4
bsf tmpLcdRegister+1,6

movf tmpLcdRegister+1,W
call LcdSendCommand

return

;**********************************************************************
; Send a data to LCD
;**********************************************************************

LcdSendData
bsf PORTB,LCD_RS
call LcdSendByte
return

;**********************************************************************
; Send a command to LCD

67
;**********************************************************************

LcdSendCommand
bcf PORTB,LCD_RS
call LcdSendByte
return

;**********************************************************************
; Send a byte to LCD by 4 bit data bus
;**********************************************************************

LcdSendByte
;Save value to send
movwf tmpLcdRegister

;Send highter four bits


bcf PORTB,LCD_DB4
bcf PORTB,LCD_DB5
bcf PORTB,LCD_DB6
bcf PORTB,LCD_DB7

btfsc tmpLcdRegister,4
bsf PORTB,LCD_DB4
btfsc tmpLcdRegister,5
bsf PORTB,LCD_DB5
btfsc tmpLcdRegister,6
bsf PORTB,LCD_DB6
btfsc tmpLcdRegister,7
bsf PORTB,LCD_DB7

bsf PORTB,LCD_E ;Enables LCD


movlw 1 ;Wait 1ms
call msDelay
bcf PORTB,LCD_E ;Disabled LCD
movlw 1 ;Wait 1ms
call msDelay

;Send lower four bits


bcf PORTB,LCD_DB4
bcf PORTB,LCD_DB5
bcf PORTB,LCD_DB6
bcf PORTB,LCD_DB7

btfsc tmpLcdRegister,0
bsf PORTB,LCD_DB4
btfsc tmpLcdRegister,1
bsf PORTB,LCD_DB5
btfsc tmpLcdRegister,2
bsf PORTB,LCD_DB6
btfsc tmpLcdRegister,3
bsf PORTB,LCD_DB7

bsf PORTB,LCD_E ;Enables LCD


movlw 1 ;Wait 1ms
call msDelay
bcf PORTB,LCD_E ;Disabled LCD
movlw 1 ;Wait 1ms
call msDelay

68
return

END

Anlisis del programa fuente

En la primera parte, estn definidas algunas constantes:

;LCD Control lines


LCD_RS equ 2 ;Register Select
LCD_E equ 3 ;Enable

;LCD data line bus


LCD_DB4 equ 4 ;LCD data line DB4
LCD_DB5 equ 5 ;LCD data line DB5
LCD_DB6 equ 6 ;LCD data line DB6
LCD_DB7 equ 7 ;LCD data line DB7

Estas constantes definen la asociacin entre las lneas del PIC (todas conectadas al PortB) y las lneas
del LCD. Cada definicin en particular, ser usada en las subrutinas de gestin del LCD en lugar de
cada nmero de identificacin de las lneas de I/O.

tmpLcdRegister res 2
msDelayCounter res 2

Seguidamente, se reserva el espacio para dos registros: tmpLcdRegister, usado por la subrutina de
gestin del LCD y msDelayCounter usada por la subrutina msDelay que generan los retardos por
sofware de 1 ms para el contenido del registro W. Estas subrutinas son usadas siempre por las
subrutinas de gestin para generar las temporizaciones requeridas durante la transmisin de datos y
comandos.

Sigue la definicin de las lneas de conexin entre el PIC y el LCD y luego se arriba a la primera
subrutina que interesa:

call LcdInit

LcdInit es una subrutina que debe ser llamada solamente una vez en el inicio del programa y antes de
cualquier otra subrutina de gestin. Ella se ocupa de efectuar todas las operaciones necesarias para
inicializar correctamente el LCD y permite que las funciones sucesivas operen correctamente.

Con las instrucciones:

movlw 00H
call LcdLocate

se posiciona el cursor del display en la primera fila y en la primera columna de la pantalla. Los
caracteres enviados sucesivamente, sern visualizados a partir de esta posicin. Los cuatro bits ms
significativos del valor cargado en el registro W con la instruccin:

movlw 00H

69
Contienen el nmero de fila donde se quiere posicionar el cursor, los cuatro bits menos significativos,
contienen el nmero de columna.

Cambiando el valor en el registro W, se obtiene posicionamientos diferentes. Con el valor 10H, por
ejemplo, se obtiene:

HELLO WORD!_

Con el valor 12H, se obtiene:


HELLO WORD!_

A esta altura, para visualizar cada carcter de la frase, se usan las siguientes instrucciones:

movlw 'H'
call LcdSendData

Y as sucesivamente para cada letra a ser visualizada. El incremento de la posicin del cursor, se hace
automticamente.

Mayor informacin sobre el uso de los LCDs, puede obtenerse de la hoja de datos que el fabricante
debe proveer.

70

También podría gustarte