Cuando los simples indicadores luminosos con led ya no son suficientes, habitualmente el siguiente paso para todo programador es ir por una pantalla lcd 16×2. Llegados a este punto, encontramos que existen módulos LCD que facilitan la interfaz con este periférico. El estándar en la industria para estos módulos con “controlador a bordo” es el chipset HD44780 (y otros más compatibles desarrollados a partir de este), para los cuales encontramos soporte en prácticamente cualquier plataforma: Arduino, PIC, AVR, MSP430, etc.
En esta entrada introducimos la librería de control altamente portable a cualquier microcontrolador, la cual puede ser utilizada tanto para PIC, como AVR y prácticamente cualquier otro microcontrolador o computadora embebida que se nos ocurra.
Nuestra foto de portada para el artículo muestra módulos LCD con iluminación azul y letras color blanco.
Conexiones básicas de una pantalla lcd 16×2
El HD44780 permite conectarse a través de un bus de 4 u 8 bits. El modo de 4 bits permite usar solo 4 pines para el bus de datos, dándonos un total de 6 o 7 pines requeridos para la interfaz con el LCD, 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 mayoría de las situaciones esto no es necesario y nuestra librería no implementa aun esta funcionalidad.
Notese que todas estas configuraciones son ilustrarivas, la pantalla se puede conectar a cualquier combinación de pines posible, ya que nuestra librería soporta usar cualquier pin como parte del bus de datos y señales de control.
Diagrama para modo de 4 bits
Las conexiones para el módo de 4 bits en un PIC16F88 se muestran a continuación. Se utilizan los primeros 4 bits del puerto A (RA0-RA3) como bus de datos. RB0 como señal de habilitación (E) y RB1 como señal de selección de registro (RS).
Diagrama para modo de 8 bits
Las conexiones para el módo de 8 bits son algo más complicadas, ya que requerimos las 8 lineas de datos activas. En este caso utilizaremos los 8 bits del puerto B, aunque se puede usar cualquier combinación de pines con nuestra librería. RA0 ahora funciona como señal de selección de registro (RS) y RA1 como señal de habilitación (E).
Comandos del controlador HD44780
Para conocer un poco mejor los comandos soportados por la librería para la pantalla lcd 16×2, es necesario estudiar el juego de instrucciones soportadas por el chip controlador de pantalla, el cual se resume en la siguiente tabla que hemos traducido de la hoja de datos. La mayoría de los comandos listados pueden ser ejecutados llamando a una función en C de nuestra librería.
Instrucción | Código de Operación | Descripción | Tiempo de Ejecución | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
RS | R/W | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | |||
Clear display | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | Borra el contenido de la pantalla y retorna el cursor a la posición “home” (dirección 0). | 1.52 ms |
Cursor home | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | * | Retorna el cursor a la posición “Home”. Retorna también el área de visión a la posición inicial. El contenido de la DDRAM permanece intacto. | 1.52 ms |
Entry mode set | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S | Incrementar/Decrementar dirección (I/D); Habilitar corrimiento de pantalla (S). Estas operaciones se realizan al leer o escribir datos | 37 μs |
Display on/off control | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B | Enciende o apaga el display (D), Cursor encendido / apagado (C), destello del cursor (blink) (B). | 37 μs |
Cursor/display shift | 0 | 0 | 0 | 0 | 0 | 1 | S/C | R/L | * | * | Selecciona entre desplazamiento de pantalla o de cursor (S/C), selecciona la dirección de desplazamiento (R/L). El contenido de la DDRAM permanece intacto. | 37 μs |
Function set | 0 | 0 | 0 | 0 | 1 | DL | N | F | * | * | Configurar en ancho de bus (4 u 8 bits) (DL),Numero de lineas de display (N), y tipo de fuente (F). | 37 μs |
Set CGRAM address | 0 | 0 | 0 | 1 | CGRAM address | Escribe la dirección de CGRAM. Los datos a almacenar en CGRAM pueden ser enviados después de esta instrucción | 37 μs | |||||
Set DDRAM address | 0 | 0 | 1 | DDRAM address | Escribe la dirección de DDRAM. Los datos a almacenar en DDRAM pueden ser enviados después de esta instrucción | 37 μs | ||||||
Read busy flag &address counter | 0 | 1 | BF | CGRAM/DDRAM address | Leer bandera “Ocupado” (Bussy Flag) indicando si el controlador está realizando alguna operación interna o esta listo para aceptar datos/comandos. Lee la dirección CGRAM o DDRAM (dependiendo de la instrucción previa). | 0 μs | ||||||
Write CGRAM orDDRAM | 1 | 0 | Write Data | Escribe datos a las memorias CGRAM o DDRAM. | 37 μs | |||||||
Read from CG/DDRAM | 1 | 1 | Read Data | Lee datos desde las memorias CGRAM o DDRAM. | 37 μs | |||||||
Nombres y significado de de bits en instrucciones I/D – 0 = disminuir el contador de dirección, 1 = incrementar el contador de dirección; 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 linea, 1 = 2 lineas; F – 0 = 5×8 puntos, 1 = 5×10 puntos; BF – 0 = puede aceptar instrucción, 1 = operación interna en progreso. |
Librería para pantalla de 16×2 con PIC
Nuestra librería para pantalla lcd 16×2 se encuentra alojada en Github. La librería es capaz de controlar una pantalla conectada en cualquier combinación de pines del microcontrolador. Además es bastante fácil llevar esta librería a otros microcontroladores PIC de mejor desempleño y también a microcontroladores de otras marcas (Atmel, TI MSP430, etc). De igual forma, el código esta pensado para admitir distintas capas de abstracción de hardware para el acceso a pines de entrada/salida en situaciones en las que esto no sea tan sencillo como lo es en un microcontrolador (abordaremos esto en otra entrada futura sobre la conexión de una pantalla a un Raspberry Pi).
La librería para pantalla lcd 16×2 puede encontrarse en el siguiente repositorio que puedes clocar o bien descargar los archivos de la librería en formato ZIP.
https://github.com/geekfactory/LCD
Para obtener la ultima versión de la librería podemos usar git con el siguiente comando:
1 | git clone --recursive https://github.com/geekfactory/LCD.git |
La librería básica para el PIC consiste en 4 archivos de código fuente:
- LCD.h – Contiene la declaración y documentación de las funciones (prototipos).
- LCD.c – Definición del funcionamiento de las funciones de usuario (API) de la pantalla LCD.
- LCD-PIC16.h – Configuración específica para la LCD en la arquitectura del microcontrolador PIC.
- LCD-PIC16.c – Definición de las funciones específicas para acceso a los pines de I/O en el PIC16.
Como ya dijimos, a veces utilizamos esta librería en otros microcontroladores, por esta razón puedes encontrar otros archivos en github, pero estos 4 son los que se requieren para trabajar en cualquier proyecto con PIC.
Configuración de los pines en la librería
Para adecuar la librería para pantalla lcd 16×2 a nuestro circuito hay que editar el archivo LCD-PIC16.h. Dentro de este, encontramos las definiciones de los pines utilizados en la interfaz con el controlador de pantalla. En este caso definimos un bus de 4 bits en la parte baja del puerto A (RA0 – RA3) y lineas de control RS y E en los pines RB1 y RB0 respectivamente. Esto corresponde a la ilustración del modo de 4 bits que se encuentra arriba en esta página.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /** * Definitions for common control lines */ #define LCD_PIN_RS PORTBbits.RB1 #define LCD_TRIS_RS TRISBbits.TRISB1 #define LCD_PIN_E PORTBbits.RB0 #define LCD_TRIS_E TRISBbits.TRISB0 /** * Configuration example for 4 bit mode */ #define LCD_TRIS_D4 TRISAbits.TRISA0 #define LCD_TRIS_D5 TRISAbits.TRISA1 #define LCD_TRIS_D6 TRISAbits.TRISA2 #define LCD_TRIS_D7 TRISAbits.TRISA3 #define LCD_PIN_D4 PORTAbits.RA0 #define LCD_PIN_D5 PORTAbits.RA1 #define LCD_PIN_D6 PORTAbits.RA2 #define LCD_PIN_D7 PORTAbits.RA3 |
Para utilizar la librería con un bus de 8 bits, es necesario definir los pines restantes del bus de datos: LCD_PIN_D0 a LCD_PIN_D3.
Escribir caracteres a la pantalla
Cada uno de los caracteres que escribimos a la pantalla son almacenados en una ubicación en la memoria RAM apuntada por la dirección del cursor. Cuando escribimos un carácter, el código ASCII correspondiente a este, se almacena en la memoria interna conocida como Display Data RAM o DDRAM. Para escribir caracteres a la DDRAM utilizamos las funciones lcd_write() y lcd_puts(), que escriben un caracter y una cadena, respectivamente.
1 2 3 4 5 6 | // Podemos mover el cursor a donde deseamos comenzar a escribir lcd_goto( 0, 0 ); // Enviamos texto a la pantalla (DDRAM) lcd_puts( "Hola Mundo" ); // Enviar un solo caracter (signo de admiracion) lcd_write("!"); |
Definir nuestros propios caracteres personalizados en una pantalla lcd 16×2
El controlador HD44780 en la pantalla lcd 16×2 nos permite también definir caracteres especiales definidos por el usuario (hasta 8 caracteres). Cuando deseamos escribir un carácter personalizado, el mapa de bits que lo compone se almacenan en otro segmento de memoria independiente conocida como Character Generator RAM o simplemente CGRAM. Cada carácter se define como un grupo de 8 bytes que se envían a la memoria CGRAM. Por ejemplo, podemos crear un ícono con una carita feliz de la siguiente forma:
En lenguaje C podemos declarar un array con el caracter personalizado que mostramos en la figura anterior de la siguiente manera:
1 2 3 4 5 6 7 8 9 10 11 | // Caracter personalizado carita feliz :) const char smile[8] = { 0b00000000, 0b00001010, 0b00001010, 0b00001010, 0b00000000, 0b00010001, 0b00001110, 0b00000000, }; |
Para usar el caracter, es necesario transferirlo al controlador de pantalla mediante la función lcd_create_char() y luego mostrarlo en pantalla enviando el código correspondiente al caracter con la función lcd_write(). El código para mostrar el carácter que acabamos de crear quedaría de la siguiente manera:
1 2 3 4 5 6 7 8 | // Cargar el caracter a CGRAM // El primer parámetro es el código del caracter (0 - 7) // El segundo es el apuntador a donde se guarda el bitmap (el array declarado anteriormente) lcd_create_char(0, smile); // Borrar la pantalla despues de terminar de escribir a CGRAM lcd_clear(); // Escribir el código de carita feliz (número 0 de 7) lcd_write(0); |
Ejemplo completo MPLAB pantalla LCD 16×2
En el programa de ejemplo aplicamos lo aprendido para iniciar la pantalla, mostrar letras, mover el cursor y escribir caracteres personalizados. Dentro del repositorio de Github podemos encontrar el proyecto demo para MPLAB X listo para compilarse para un PIC16F88 pero que podemos utilizar fácilmente con cualquier microcontrolador de la familia PIC16F.
El programa requiere un PIC16F88 con cristal de 4 Mhz conectado en los pines correspondientes y la pantalla conectada como se muestra en la ilustración de “Modo de 4 bits” mostrada más arriba.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | #define CONFIG_TIMING_MAIN_CLOCK 1000000 #include <xc.h> // Encabezado para el compilador XC8 #include "../LCD.h" /* Device specific configuration */ #pragma config FOSC = XT // Oscillator Selection bits (XT oscillator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR) #pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled) #pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EE Memory Code Protection bit (Code protection off) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off) #pragma config CCPMX = RB0 // CCP1 Pin Selection bit (CCP1 function on RB0) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled) #pragma config IESO = OFF // Internal External Switchover bit (Internal External Switchover mode disabled) // Declaration of custom characters const char arrowr[8] = { 0b00001000, 0b00000100, 0b00000010, 0b00011111, 0b00000010, 0b00000100, 0b00001000, 0b00000000, }; const char arrowu[8] = { 0b00000100, 0b00001110, 0b00010101, 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00000000, }; const char arrowd[8] = { 0b00000100, 0b00000100, 0b00000100, 0b00000100, 0b00010101, 0b00001110, 0b00000100, 0b00000000, }; const char arrowl[8] = { 0b00000010, 0b00000100, 0b00001000, 0b00011111, 0b00001000, 0b00000100, 0b00000010, 0b00000000, }; void main() { int i; ANSEL = 0x00; TRISA = 0xFF; TRISB = 0x7F; // Initialize lcd driver lcd_init(0, 16, 2); // Load characters to CGRAM lcd_create_char(0, arrowr); lcd_create_char(1, arrowu); lcd_create_char(2, arrowl); lcd_create_char(3, arrowd); // Clear screen to end write to character generator lcd_clear(); // Turn on display lcd_on(); // Display message on the first row lcd_puts(" geekfactory.mx "); // Move cursor to the fourth column on second line lcd_goto(3, 1); // Print a message there lcd_puts("Hello World"); // Mover cursor to the sixteenth column on second row lcd_goto(15, 1); // Main loop for (;;) { for (i = 0; i < 4; i++) { // 1 Hz led blink delay_ms(500); // Toggle pin RB7 PORTB ^= 0x80; // Write custom defined character code (can be 0-7) lcd_write(i); // Goto the last visible position on the screen lcd_goto(50, 50); } } } |
Resultado del programa de prueba
Al cargar y ejecutar de manera exitosa el programa de prueba en el microcontrolador, deberíamos ver en nuestra pantalla algo como lo siguiente:
Si no aparece nada en la pantalla o solamente aparecen caracteres que no se reconocen, procederemos a revisar cada uno de los siguientes aspectos del montaje:
- Revisar el potenciometro de contraste: cambiar de posición hasta que logremos ver algo
- Revisar que las señales E y RS estén conectadas en los pines adecuados
- Revisar las conexiones en el bus de datos, revisar que los pines coincidan con los definidos en el programa
- Revisar la velocidad de reloj, si el controlador no puede recibir correctamente algunos comandos podría causar que la información no se muestre correctamente.
Tips y trucos para el uso de esta librería
Revisa la ayuda incluida
Te recomendamos aprovechar al máximo el apoyo de la documentación incluida. Si estamos acostumbrados a trabajar con MPLAB X siempre podemos oprimir las teclas “CTRL + Espacio” para acceder a la función de autocompletado. Esta función nos muestra una ventana sobre nuestro editor de texto donde podemos observar la documentación de la librería. Esto incluye las funciones disponibles e información sobre los parámetros que reciben. La ventana de autocompletado tiene la siguiente apariencia:
Use caracteres personalizados
La librería viene con funciones que permiten definir caracteres especiales. En el ejemplo de la librería hemos definido 4 caracteres personalizados (flechas) que aparecen durante el programa de demostración. Sin embargo, la creatividad de cada persona permitirá crear caracteres que pueden utilizarse como iconos para los más diversos usos.
Aporta tus ideas y correcciones
Nuestra librería de LCD esta alojada en github. Cualquier persona puede realizar correcciones o mejoras al código fuente y aportarlas al repositorio. Alguien en nuestro equipo revisará los cambios propuestos y los integrará al código principal en caso de ser necesario.
Descargas y enlaces relacionados
- Descarga de la hoja de datos de la pantalla en nuestra tienda virtual
- Descarga de la hoja de datos del controlador HD44780 original
- Compra tus pantallas LCD en nuestra tienda virtual
Conclusión
En este artículo, sentamos las bases para que puedas incluir de manera sencilla pantallas LCD de 16×2 caracteres en tus diseños con microcontroladores PIC. Nosotros lo hacemos habitualmente y encontrarás muchos ejemplos que funcionan con esta librería dentro de nuestro sitio web.
Como ya dijimos, te invitamos a crear una cuenta en Github y a mejorar la librería y aportar cualquier mejora que creas conveniente. Será un placer también recibir tus comentarios a través de este medio o mediante correo electrónico.
Por ultimo, te invitamos a comprar tus pantallas LCD en nuestra tienda virtual para ayudarnos a seguir desarrollando ejemplos, software y tecnología.