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.
- Vista trasera de un LCD 2×16 típico.
- Hermoso: un LCD de 4 lineas de 40 caracteres, color azul.
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.
- Los pines de un display LCD genérico.
- De esa forma podemos controlar el contraste del LCD.
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!
- Veremos como definir nuestros propios caracteres.
- Estos LCD son ideales para modding.