Módulo visualizador LCD

INTRODUCCIÓN:

    Con este módulo, vamos a ser capaces de representar en una pantalla de cristal liquido, diversos mensajes de una manera cómoda y fácil.

    Distintos fabricantes ofrecen multitud de visualizadores de cristal líquido con los que se puede, de una forma fácil y económica, representar la información que genera cualquier sistema, desde sistemas empotrados hasta pequeños computadores. Estos dispositivos se pueden encontrar con características diversas, con 1, 2, 3 ó 4 líneas, de 16 hasta 40 caracteres por línea, con fuentes de 5x7 ó 5x10 puntos, etc. Normalmente, estos dispositivos van acompañados por un controlador interno, que se encargará de cumplir las órdenes que se le envíen, y un generador de caracteres para facilitar, desde el punto de vista del programador, la representación de éstos.

DESCRIPCIÓN:

     Aunque los visualizadores pueden variar en algunas de sus características, el controlador, o, más específicamente, el protocolo que se usa como interfaz entre éste y el sistema suele ser estándar. Todos ellos ofrecen un interfaz compatible con niveles TTL, donde la forma de conectarlo al sistema puede basarse en un esquema de bus de 4 o de 8 bits de datos más unas líneas de control. Aunque el interfaz de 4 bits implica el doble de tiempo en las operaciones con el visualizador, dado que para efectuar la escritura de un dato de 8 bits (código del carácter a representar) se tendrá que hacer en dos pasos, esto proporciona un ahorro en líneas nada despreciable.

    La tabla adjunta muestra el patillaje de un visualizador LCD. En ésta se puede ver, en primer lugar, las patillas destinadas a alimentar el visualizador, GND, +5v., y tensión de la pantalla o lo que se puede entender como el contraste. Tras estas líneas se pueden apreciar 3 de control y por último las ocho líneas del bus de datos. Como ya se ha citado, se pueden usar las ocho líneas de datos o bien diseñar un esquema basado en 4 bits donde se envía la información en dos pasos usando solo las 4 líneas de menor peso. 

Patilla Símbolo Función
1 VSS 0 v. (masa)
2 VCC +5v.
3 VEE Alimentación del cristal líquido (contraste)
4 RS Selección de registro
5 R/W Selección lectura/escritura
6 E Señal de habilitación
7 DB0 Bit 0 del dato
8 DB1 Bit 1 del dato
9 DB2 Bit 2 del dato
10 DB3 Bit 3 del dato
11 DB4 Bit 4 del dato
12 DB5 Bit 5 del dato
13 DB6 Bit 6 del dato
14 DB7 Bit 7 del dato

 Patillaje del LCD

    En cuanto a la tensión del cristal líquido, ésta puede variar en función del tipo de visualizador que se esté utilizando. En todos se busca que la diferencia entre la tensión de alimentación (VCC) y la del display (VEE) esté dentro de un rango. Por ejemplo, en el modelo LM041L se aconseja una tensión, para la diferencia (VCC - VEE) de entre 1.5 y 5.25V. En el modelo DMF633 de OPTREX el rango está entre -0.3 y 16.5 V; en el DMC20434 la tensión tiene que estar entre 0 y 6 V.

    Generalmente, en la mayoría de visualizadores, el esquema propuesto en el diseño hardware ofrece un correcto funcionamiento, donde se ajusta el potenciómetro según la visibilidad necesitada en el visualizador.

     Para la conexión a un puerto del µC (o a un 8255) usando un esquema de bus de 4 bits con lo que solo se necesitarán un total de 7 líneas, realizaremos el siguiente montaje.

Descarga Del Esquema Del Módulo Visualizador LCD

     La segunda opción es conectarlo al bus del sistema y efectuar la selección del dispositivo mediante una dirección. La Figura 3-16 muestra el esquema para un sistema basado en el microcontrolador 8x51 donde el visualizador estará situado en alguna posición dentro del espacio de memoria. Se usará parte del bus de direcciones para activar o no la entrada de selección del LCD (E) y las líneas bajas de éste, A0 y A1, para seleccionar las entradas RS y R/W. De esta forma se tendrá cuatro direcciones, como mínimo, ya que puede estar replicado, para tratar con el visualizador en función de las operaciones que se quieran realizar. Este esquema puede plantear problemas en el caso de frecuencias de reloj por encima de los 10 Mhz.

    Si se elige un interfaz basado en 4 bits, primero hay que transferir, para indicarle el número de líneas y fuente, los 4 bits altos del byte y seguidamente los 4 bajos. En general, tanto para comunicar datos u órdenes, si se opta por un interfaz de 4 bits, normalmente cuando se controle el visualizador mediante un puerto de E/S, y no como parte del bus del sistema, hay que enviar la información al display en grupos de 4 bits, mandando primero los cuatro bits altos del byte y seguidamente los bajos.

A modo de resumen este es el conjunto de instrucciones que admite el visualizador:
 

Instrucción RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
Borrar pantalla 0 0 0 0 0 0 0 0 0 1
Cursor a origen 0 0 0 0 0 0 0 0 1 --
Modo de entrada 0 0 0 0 0 0 0 I/D S
Pantalla on/off 0 0 0 0 0 0 1 D C B
Desplazamiento de cursor/pantalla 0 0 0 0 0 1 S/C R/L --  --
Establecer modo de funcionamiento 0 0 0 0 1 DL N F -- --
Establecer dirección CGRAM 0 0 0 1 ACG
Establecer dirección DDRAM 0 0 1 ADD
BF/Lectura de dirección 0 1 BF AC
Escritura en CGRAM/DDRAM  1 0 Dato
Lectura en CGRAM/DDRAM 1 1 Dato

        

                                 Instrucciones del visualizador LCD

PCB:

Descarga Del Pcb Del Módulo Visualizador LCD

 

COMPONENTES: 

COMPONENTES

CANTIDAD
Conector Molex 2x5 Pines  1
Placa PCB 1 Cara( 117x 58)mm 1
Potenciometro 10k 1
Torretas Separadoras 10mm 4
Visualizador LCD Hitachi LM016L 1
Cable para conexiones

 

 

EJEMPLO:

(guardar)

     A continuación se presenta un conjunto de funciones que se encargan de controlar el visualizador conectado a un puerto del microcontrolador según la conexión hardware propuesta previamente. Obsérvese que en el listado se usa el bit BF para saber cuando se puede enviar información sin miedo a perdidas. Si se opta por una conexión a través de un puerto del 8255 no se puede hacer esto, pues seria necesario un cambio de "modo salida" a "modo entrada" que produciría una inicialización del 8255 con lo que el visualizador no funcionaría correctamente. En este caso, se pueden quitar los comentarios la parte correspondiente del listado que hace un simple retardo que, en la mayoría de los casos, garantiza que pase un tiempo suficiente entre las órdenes. Se recomienda que en cualquier diseño que el lector pueda realizar, se use del bit BF para comprobar el estado del dispositivo.

/* lcd.c */
#include <io51.h>
#include "lcd.h"
#ifndef LCDP
#define LCDP P1
#endif

void lcd_wait(void)
{
    unsigned char d;
    LCDP &= 0x0F;
    LCDP |= 0x2F;
    do
    {
        LCDP |= 0x10;
        d = LCDP;
        LCDP &= 0xEF;
        LCDP &= 0xEF; /* perder un poquito de tiempo */
        LCDP |= 0x10;
        LCDP &= 0xEF;
    }
    while (d & 0x08);
}

void lcd_envia(unsigned char d)
{
    /* int i; */
    LCDP &= 0xDF; /* sel. escritura, bit 5 */
    LCDP &= 0xF0; /* parte alta */
    LCDP |= d >> 4;
    LCDP |= 0x10; /* activa escrit., bit 4 */
    LCDP &= 0xEF; /* desact. escrit. */
    LCDP &= 0xF0; /* parte baja */
    LCDP |= d & 0x0F;
    LCDP |= 0x10; /* activa escrit., bit 4 */
    LCDP &= 0xEF; /* desact. escrit. */
    /* for(i=0;i<300;i++); */
    lcd_wait();
}

/* tomar el control del LCD y establecer condiciones iniciales */
void lcd_reset(void)
{
    unsigned int c;
    for (c=0;c<10000;c++);
    LCDP &= 0x40;
    LCDP |= 0x03;
    LCDP |= 0x10;
    LCDP &= 0xEF;
    for (c=0;c<1000;c++);
    LCDP |= 0x10;
    LCDP &= 0xEF;
    for (c=0;c<1000;c++);
    LCDP |= 0x10;
    LCDP &= 0xEF;
    for (c=0;c<1000;c++);
    lcd_envia(0x28); /* bus de 4 bits */
    lcd_envia(0x0C); /* cursor apagado */
    lcd_envia(0x06); /* lcd no desplazado */
    lcd_envia(0x01); /* limpiar pantalla */
}

/*situar el puntero de escritura en el lugar deseado del display*/
/*la coordenada superior izquierda es la 1,1 */
void lcd_gotoxy(unsigned char x, unsigned char y)
{
    unsigned char d;
    LCDP &= 0x7F;
    d = 0x80 + (y-1)*0x40 + x-1;
    lcd_envia(d);
}

/* escribir el caracter especificado a la posicion del cursor */
void lcd_caracter(unsigned char c)
{
    LCDP |= 0x80;
    lcd_envia(c);
}

/* escribir una cadena a partir de la posición del cursor */
void lcd_escribe(unsigned char *s)
{
    while(*s)
    {
        lcd_caracter(*s);
        s++;
    }
}

/* hacer visible el cursor con parpadeo */
void lcd_cursoron(void)
{
    LCDP &= 0x7F;
    lcd_envia(0x0F);
}

/* ocultar el cursor */
void lcd_cursoroff(void)
{
    LCDP &= 0x7F;
    lcd_envia(0x0C);
}

/* borrar la pantalla */
void lcd_clrscr(void)
{
    LCDP &= 0x7F;
    lcd_envia(0x01);
}

void lcd_rincon(void)
{
    LCDP &= 0x7F;
    lcd_envia(0x02);
}

/* crear un nuevo caracter con codigo de 0 a 8 (o 16) */
/* el puntero debera asignarse a una cadena de 8 caracteres */
void lcd_creacaracter(unsigned char c, unsigned char *p)
{
    unsigned char i;
    LCDP &= 0x7F;
    lcd_envia(0x40|(c*8));
    for (i=0;i<8;i++)
    {
        LCDP |= 0x80;
        lcd_envia(*p);
        p++;
    }
    LCDP &= 0x7F;
    lcd_envia(0x80);
}

/* lcd.h */
void lcd_reset(void);
void lcd_gotoxy(unsigned char x, unsigned char y);
void lcd_escribe(unsigned char *s);
void lcd_cursoron(void);
void lcd_clrscr(void);
void lcd_cursoroff(void);
void lcd_creacaracter(unsigned char c, unsigned char *p);
void lcd_caracter(unsigned char c);

/* testlcd.c */
#include "lcd.h"
unsigned char enye[]={0x0E,0x00,0x16,0x19,0x11,0x11,0x11,0x00};
unsigned char cor1[]={0x00,0x00,0x0A,0x0E,0x04,0x00,0x00,0x00};
unsigned char cor2[]={0x00,0x0A,0x1F,0x1F,0x0E,0x04,0x00,0x00};
unsigned char barra[]={0x00,0x10,0x08,0x04,0x02,0x01,0x00,0x00};

void retardo(long i);
void rueda(void)
{
    static unsigned char x=0;
    x = (x + 1) % 4;
    lcd_gotoxy(8,1);
    switch(x) {
    case 0:
                lcd_caracter('-');
                break;
    case 1:
                lcd_caracter(3);
                break;
    case 2:
                lcd_caracter('|');
                break;
    case 3:
                lcd_caracter('/');
                break;
    }
}

void main(void)
{
    int i;
    lcd_reset();
    lcd_creacaracter(1,enye);
    lcd_creacaracter(0,cor1);
    lcd_creacaracter(2,cor2);
    lcd_creacaracter(3,barra);
    lcd_gotoxy(3,1);
    lcd_escribe("Hola, Mundo");
    lcd_gotoxy(3,2);
    lcd_escribe("Estoy vivo");
    retardo(20000);
    lcd_clrscr();
    lcd_escribe("El cursor -> ");
    lcd_cursoron();
    retardo(20000);
    lcd_clrscr();
    lcd_escribe("Los caracteres:");
    lcd_cursoroff();
    for (i=32;i<=255;i++)
    {
        retardo(1000);
        lcd_gotoxy(16,1);
        lcd_caracter(i);
    }
    retardo(20000);
    lcd_cursoroff();
    lcd_clrscr();
    lcd_escribe("UN SIMBOLO NUEVO");
    lcd_gotoxy(1,2);
    lcd_escribe("El ni\x1o es \x1o\x1o");
    retardo(20000);
    lcd_clrscr();
    while(1)
    {
        rueda();
        lcd_gotoxy(8,2);
        lcd_caracter(2);
        rueda(); retardo(500);
        rueda(); retardo(500);
        rueda(); retardo(500);
        rueda(); retardo(500);
        lcd_gotoxy(8,2);
        lcd_caracter(0);
        rueda(); retardo(500);
    }
}

void retardo(long i)
{
    while (i--);
}
 

    El software, unido a un hardware adecuado, es la mejor herramienta para sacar el máximo partido al µC sin mucho esfuerzo. El display LCD permite representar información escrita sin muchas dificultades, aunque para representar valores númericos se necesitará un pequeño esfuerzo adicional. Sin embargo, la capacidad del LCD se puede explotar mejor si se domina un poco el lenguaje C. Por ejemplo, la función printf es capaz de representar en la salida estándar cadenas de caracteres, números, etc. con el formato que se quiera. En el fondo de la función printf (y todas las que saquen información por la salidad estándar) está la función putchar, que es la que realmente escribe los caracteres en la salida. Es posible reescribir putchar para que printf funcione y envie su salida al LCD. Los siguientes programas lo ilustran.

/* putlcd.c */
#include <stdio.h>
#include "lcd.h"

int putchar(int val)
{
    lcd_caracter(val);
    return (val);
}
 

/* printlcd */
#include "lcd.h"
#include <stdio.h>

void retardo(long i)
{
    while(i--);
}

void main(void)
{
    int i;
    lcd_reset();
    while(1)
    {
        for(i=0;i<9999;i++)
        {
            lcd_clrscr();
            lcd_gotoxy(3,1);
            printf("Cuenta: %d",i);
            retardo(500);
        }
    }
}