En muchos casos, la señalización de estados de nuestros proyectos mediante diodos LED resulta insuficiente. Una alternativa muy profesional y económica (y de fácil implementación) es la utilización de displays LCD alfanuméricos.Continuando con la serie de notas dedicadas a aprender a programar microcontroladores, veremos las instrucciones que dispone el lenguaje de programación PIC BASIC orientadas al manejo de displays LCD.
Existen en el mercado una enorme variedad de pantallas de cristal liquido, de un precio accesible, con características comunes en cuanto a la interfaz y programación, gracias que la mayoría utiliza para comunicarse con el “exterior” el mismo chip de la empresa Hitachi, el HD44780. Esto hace posible que con un puñado de instrucciones podemos manejar desde un sencillo display de una línea de 8 caracteres hasta uno de 4 líneas con 80 caracteres.
El aspecto físico de estas pantallas se puede ver en las fotos que ilustran la nota, básicamente son una pequeña placa de circuito impreso con un par de integrados (tipo “gota”) pegados en una de sus caras, y la pantalla propiamente dicha en la otra, rodeada de una estructura metálica que la protege. Esta placa casi siempre dispone de agujeros para poder fijar el conjunto a un chasis o gabinete sin grandes complicaciones. Desde el punto de vista eléctrico, hay un conector (a veces solo agujeros metalizados donde soldar los cables) que tiene 14 pines en los que no poseen iluminación propia (backlite) o 16 en los que si la tienen.
Mediante las señales apropiadas enviadas y recibidas mediante este conector el display es capaz de representar caracteres, mostrar o esconder un cursor, borrar la pantalla, etc.
Descripción de los pines
Como mencionamos, la gran mayoría de los displays existentes en el mercado respetan la misma distribución de pines. Igualmente, antes de conectar nada, debemos asegurarnos de que así sea, para no dañar de forma permanente el LCD. Siempre es necesario tener a mano la “datasheet” (hoja de datos) del componente electrónico que queremos usar.
Veamos que función cumple cada uno de los pines de un display LCD genérico:
Pines 1,2 y 3: Estos pines están dedicados a la alimentación y contraste del LCD. Efectivamente, el pin 1 (VSS) es el que se debe conectar al negativo (masa) de la alimentación, y el pin 2 (Vdd/Vcc) es el que va unido al positivo (5 voltios). El pin 3 permite el ajuste del contraste del panel. Se puede unir al pin 1 mediante una resistencia de 220 ohms para obtener un contraste adecuado (pero fijo) o bien utilizar un potenciómetro o preset de 10 KOhm para variar el contraste a gusto.
Pines 4,5,6: Estos pines son de alguna manera los que controlan el funcionamiento del display. El pin 4, también llamado RS (Registration Select) es el que le indica al controlador interno del LCD que el valor presente en el bus de datos es un comando (cuando RS=0) o bien un carácter para representar (cuando RS=1).
El pin 5 (“R/W” por “Read/Write” o “Leer/Escribir”) permite decidir si queremos enviar datos al display (R/W=0) o bien nos interesa leer lo que el display tiene en su memoria o conocer su estado (R/W=1).
Por ultimo, el pin 6 (E por “Enable” o “habilitado”) es el que selecciona el display a utilizar. Es decir, podemos tener varios LCD conectados a un mismo bus de datos (pines 7-14) de control, y mediante E seleccionar cual es el que debe usarse en cada momento.
Pines 7, 8, 9, 10, 11, 12, 13, 14: Estos ocho pines son el “bus de datos” del controlador de la pantalla. Llamados DB0-DB7 son los encargados de recibir (o enviar) los comandos o datos desde o hacia el display. DB0 es el bit de menor peso y DB7 es el más significativo.
Por ultimo, los pines 15 y 16 son los que se utilizan para alimentar el (o los) LEDs de fondo de la pantalla, que brindan la iluminación (backlight). El pin 15 debe ser conectado a 5 voltios y el 16 al negativo o masa de la fuente. En estas condiciones, la luz de fondo esta encendida a 100% de su brillo. Nuevamente, se puede utilizar un potenciómetro o preset para ajustar el brillo. Como una nota curiosa, muy frecuentemente estos dos pines están ubicados ANTES del pin 1 (ver esquema). Debemos asegurarnos de cual es su posición consultando la hoja de datos del fabricante o la serigrafía que existe sobre la placa del LCD.
Estos displays soportan dos modos de trabajo: en uno de ellos reciben en DB0-DB7 los 8 bits del dato, y en el otro, llamado “modo de 4 bits” reciben los datos en dos mitades (nibbles) por los pines DB4-DB7, en dos pasos sucesivos. Si bien esto puede complicar ligeramente la programación en assembler, en PIC BASIC es completamente transparente, a la vez que supone un ahorro de 4 pines en el bus de datos, y esto en microcontroladores con pocos pines de I/O es muy útil.
A grandes rasgos, y a pesar de la simplicidad que brinda el disponer de un mismo integrado especializado en casi todos los modelos de displays, la escritura en estos es relativamente compleja, dado que se deben respetar protocolos de inicialización, tiempos entre envío de datos, etc., lo que hace bastante tediosa su programación en assembler. Pero PIC BASIC dispone de un juego de instrucciones especiales para manejar displays en modo “8 bits” y en modo “4 bits” que nos evitan toda esa complejidad. Veremos cuáles son y algunos ejemplos de uso. La próxima semana realizaremos un módulo para el PIC TRAINER y escribiremos varios programas de ejemplo.
El manejo de los LCD se hace mediante el uso de sentencias “DEFINE”, que le dicen al compilador a que pines del microcontrolador hemos conectado cada uno de los pines del LCD. La forma de la instrucción DEFINE es la siguiente:
Donde “parametro” es el nombre del parámetro al que le queremos asignar el “valor”. Los parámetros disponibles para el manejo de LCD alfanuméricos son los siguientes:
LCD_BITS: Define el número de bits de la interfaz de datos. Se pueden asignar valores de 4 u 8, siendo 4 el valor por defecto.
LCD_DREG: Define a que puerto del PIC tenemos conectado el port de datos del LCD. Los valores permitidos son PORTA, PORTB, PORTC, etc. Por defecto se asume PORTB.
LCD_DBIT: Define cual es el primer pin del puerto que usamos para enviar los datos al LCD cuando seleccionamos un bus de 4 bits. Solo puede ser el 0 (para los pines el 0, 1, 2 y 3) o 4 (para usar los pines 4, 5, 6 y 7). Por defecto se asume “4”, y esta instrucción se ignora para LCD_BITS = 8.
LCD_RSREG: Define a que puerto del PIC tenemos conectado el pin RS del LCD. Los valores permitidos son PORTA, PORTB, PORTC, etc. Por defecto se asume PORTB.
LCD_RSBIT: Define a que pin del puerto tenemos conectado el pin RS del LCD. Por defecto se asume “3”.
LCD_EREG: Define a que puerto del PIC tenemos conectado el pin E del LCD. Los valores permitidos son PORTA, PORTB, PORTC, etc. Por defecto se asume PORTB.
LCD_EBIT: Define a que pin del puerto tenemos conectado el pin E del LCD. Por defecto se asume “2”.
LCD_RWREG: Define a que puerto del PIC tenemos conectado el pin RW del LCD. Los valores permitidos son 0, PORTA, PORTB, PORTC, etc. Por defecto se asume “0”, que significa “no usamos el pin RW”.
LCD_RWBIT: Define a que pin del puerto tenemos conectado el pin RW del LCD. Por defecto se asume “0”, que significa “no usamos el pin RW”.
LCD_COMMANDUS: Define cuantos microsegundos demora la escritura de un comando en el display. Por defecto, este valor es de 5000. La mayoría de los LCD funcionan bien con un valor de 2000, lo que hace más rápidos nuestros programas.
LCD_DATAUS: Define cuantos microsegundos demora la escritura de un dato en el LCD. Por defecto, este valor es de 100.
LCD_INITMS: Define cuantos microsegundos demora la inicialización e la electrónica del LCD. Por defecto, este valor es de 100.
Luego, tenemos una serie de instrucciones que manejan el envío de comandos e instrucciones al display:
LCDINIT debe utilizarse antes de enviar cualquier comando o dato al LCD. La forma de esta instrucción es al siguiente:
Donde “n” es el tipo de cursor que queremos que muestre el display. “0” significa que el cursor estará oculto, “1” significa que el cursor parpadeara, “2” nos mostrara un cursor subrayado, y “3” un cursor subrayado y parpadeando.
LCDCMDOUT es la instrucción que envía comandos al LCD. Se emplea de la siguiente manera:
Donde “comando” es alguno de los siguientes:
LcdClear: Borra el contenido del LCD.
LcdHome: Lleva el cursor a la primera posición del primer renglón del LCD.
LcdLine2Home: Lleva el cursor a la primera posición del segundo renglón del LCD.
LcdLeft: Mueve el cursor una posición a la izquierda.
LcdRight: Mueve el cursor una posición a la derecha.
LcdShiftLeft: Desplaza el contenido del LCD una posición a la izquierda.
LcdShiftRight: Desplaza el contenido del LCD una posición a la derecha.
LcdLine1Clear: Borra la primera línea del LCD.
LcdLine2Clear: Borra la segunda línea del LCD.
LcdLine1Pos(x): Coloca el cursor en la posición “x” del primer renglón del LCD. “X” puede tener cualquier valor entre 1 y 40
LcdLine2Pos(x): Coloca el cursor en la posición “x” del segundo renglón del LCD. “X” puede tener cualquier valor entre 1 y 40
LCDOUT envía datos al display. Si son caracteres, simplemente los ponemos entre comillas a continuación del comando. Si se trata de mostrar el contenido de una variable, se escribe la variable (precedida por “#”) a continuación del comando. Si se necesitan imprimir varias variables, se pueden separar por “comas”.
A continuación, un par de ejemplos de cómo se utilizan todas estas instrucciones. El primero se encarga de mostrar un texto parpadeando en la primera línea del display. Intenten deducir como está conectado el LCD al PIC mirando las instrucciones “DEFINE” del principio del programa.
DEFINE LCD_BITS = 8
DEFINE LCD_DREG = PORTB
DEFINE LCD_DBIT = 0
DEFINE LCD_RSREG = PORTD
DEFINE LCD_RSBIT = 1
DEFINE LCD_EREG = PORTD
DEFINE LCD_EBIT = 3
DEFINE LCD_RWREG = PORTD
DEFINE LCD_RWBIT = 2
LCDINIT 0 ‘inicializo el LCD sin cursor.
loop:
LCDOUT “www.NeoTeo.com” ‘Muestra el texto…
WAITMS 1000 ‘Espero un segundo
LCDCMDOUT LcdClear ‘Borro el display
WAITMS 1000 ‘Espero un segundo
GOTO loop ‘Vuelvo a loop: para repetir indefinidamente.
El segundo ejemplo muestra como imprimir el contenido de una variable (“A”) en el LCD. Concretamente, se muestra un texto en el primer renglón, mientras que en el segundo se cuentan los números del 65535 al 0 en el segundo.
DEFINE LCD_BITS = 8
DEFINE LCD_DREG = PORTB
DEFINE LCD_DBIT = 0
DEFINE LCD_RSREG = PORTD
DEFINE LCD_RSBIT = 1
DEFINE LCD_EREG = PORTD
DEFINE LCD_EBIT = 3
DEFINE LCD_RWREG = PORTD
DEFINE LCD_RWBIT = 2
DIM A AS WORD
A = 65535
LCDINIT 3 ‘Cursor parpadeando
WAITMS 1000
loop:
LCDOUT “¡Estoy contando!” ‘Texto del primer renglón
LCDCMDOUT LcdLine2Home ‘Paso al Segundo renglón
LCDOUT #A ‘Muestro el valor de A
A = A – 1
WAITMS 250
LCDCMDOUT LcdClear ‘Limpio del display
GOTO loop
Esto es todo por hoy. La semana próxima veremos cómo implementar estos ejemplos en una placa de expansión para nuestro PIC TRAINER, y también como definir nuestros propios caracteres especiales. ¡Hasta la próxima!
Muy buen trabajo, me ha sido de gran ayuda, segui asi.
El lenguaje Basic es un lenguaje de alto nivel. Ya que Ustedes comienzan en cendiendo un simple diodo, no les parece que el leguaje a usar deberia de ser el lenguaje Ensamblador es decir con nemonicos, las 35 instruciiones del chip vaya, creo que para los que empiezan les seria mucho mas sencillo y tendrian muchos mas ejemplos de libre acquisicion. Por lo demas enhorabuena es un buen trabajo. solo tiene que explicar con claridad como se pueden fabricar circuitos impresos de doblecara, teniendo insoladora porsupuesto, es micaso Saludos.
El lenguaje Basic creo que no es el mas apropiado para comenzar, ya que Uds. comienzan encendiendo un diodo, creo que se deberia usar el lenguaje ensamblador, con nemonicos vaya con sus 35 instrucciones, ya que se dispone de muchos mas ejemplos en la red para personas que comienzan con los microcontroladores. Seria de mucha ayuda que expilicaran la fabricacion de C.I. de doblecara algo que funcione y siempredisponiendo de insoladora claro. Por lo demas buen trabajo Saludos.
Tengo el pbp 244, puedes indicarme por que no puedo simular una aplicacion que si corre en hardware real?
porque el simulador pbp de oshonsoft trababa a un tiempo muy lento para que puedas ver el movimiento de los registros dentro del microcontrolador. te recomiendo lko simules en proteus
Estimado Ariel Palazzesi, quisiera pedir si pueden publicar una entrega con el siguiente proyecto: Un cuadro de texto en VisualBasic, y que la PC envie texto escrito al PIC via RS232, y que el PIC muestre el texto en el LCD. Creo que es un proyecto muy interesante y agrupa varios temas en uno. Muchas Gracias.
Hola, me gustaria saber si el comando define sirve para mikrobasic, porque el programa no me lo toma y no aparece en la ayuda. Hay algún otro comando que pueda usar para definir las variables? Muchas Gracias!
Me parece excelente este tutorial sobre microcontroladores, estaba totalmente perdido en esto de los Pics, y con este tutorial he discipado todas mis dudas, no pense que fuera tan sencillo el programar estos dispositivos…!!!!!! Los felicito por este material tan bueno.
Muy bueno el tutorial, ¿como hago para acceder a los otros 6 anteriores?
Muy buenos los tutoriales. Como accedo a los anteriores?
Q… tal muy bueno el trabajo q realizas; ahora como puedo obtener todos los articulos correspondientes al presente trabajo???… gracias…
Exelente tutorial, he llegado a la entrega 7, ¿Donde encuentro las siguientes?
Mil gracias y Exitos.
excelente tutorial amigo! sabes necesito mandarle a escribir algo al display desde unos botones, es decir cuando presiono el boton 1 que mande un mensaje al display como por ejemplo "hola" y si presiono el segundo boton que aparezca en el display "Adios" estoy queriendo hacerlo pero la verdad no tengo idea de la programacion de pic pero quiero aprender utilizando un display de lcd, gracias amigo! si pudieras responderme te lo agradecezco enormemente
pues a mi el BASIC se me hace un lenguaje muy amigable, talvez porque es con el que comence… pero me parece que es el ideal pues al comenzar con el desde cero te adaptas y puedes hacer proyectos mas complejos, bueno ese es mi punto de vista.. xD
por otro lado gracias por el tutorial, has sido de gran ayuda para todos…
sigue asi!
enhorabuena…