Mostrando entradas con la etiqueta Hitachi 44780. Mostrar todas las entradas
Mostrando entradas con la etiqueta Hitachi 44780. Mostrar todas las entradas

Librería para el manejo de un módulo LCD en CCS C

Ya vimos Conexión y funciones de un módulo LCD y Control de un módulo LCD con PIC y CCS C, partiendo de esa base podemos seguir adelante y ¿por qué no directamente con ejemplos? Bueno, en esta ocasión les traigo una librería lista para operar con módulos LCD con buses de 4 u 8 bits, y conexión al PIC de modo serial o paralelo. Se trata de una librería que bauticé con el nombre, no muy creativo, de lcdgar.c.
Lo bueno que tiene esta librería es que para configurarla sólo hacen falta definir o no algunas macros, de modo que es bastante flexible y puede usarse de muchas maneras.
Aquí les presento el primer ejemplo, y es la forma mas rápida de configurar lcdgar, ya que es predeterminada, sin definir nada la librería se auto-configura.
#include <16f88.h>         // Tipo de PIC y declaraciones
#use delay(internal=8MHz)  // Usar delay con un reloj interno a 8 MHz
#Fuses INTRC_IO            // Oscilador interno
#Fuses PUT                 // Espera unos mS a que se estabilice la
                           // tensión antes de iniciar.
#Fuses BROWNOUT            // Si la tensión cae por debajo de un límite
                           // reinicia el PIC

// Defino la configuración para que LCDGAR establezca comunicación con
// el módulo LCD. Debe definirse toda la configuración antes
// de llamar a lcdgar.c

// Como se usará la configuración predeterminada no se definirá nada,
// y al llamar a  se autoconfigurará. Si deseamos cambiar
// dicha configuración aquí deberán aparecer todos los cambios.

#include <lcdgar.c>

void main(){

   init_LCD();       // Inicio el Módulo LCD

   locate(7,0);      // ubico el cursor en la columna 7 de la primer 
   print("HOLA");    // línea, escribe HOLA

   locate(6,1);      // ubico el cursor en la columna 6 de la segunda 
   print("MUNDO");   // fila y escribo MUNDO.
   
   do{               // Entra en un bucle infinito
   }while(true);
}
Con este código cargado en el PIC se puede controlar un módulo LCD con bus de 8 bits usando todo el puerto B para la comunicación PIC-LCD, el Pin A0 será el encargado de la señal ENABLE y el Pin A1 el encargado de la señal RS.
Si quisieramos, por ejemplo, en lugar del Puerto B, utilizar el Puerto C como bus de datos, deberíamos definir, antes de llamar a la librería mediante la directiva #INCLUDE, el macro Bus_Puerto_C:
#define Bus_Puerto_C
Ahora bien, se puede usar un shift register para controlar el LCD y de esa forma ahorrarnos pines del microcontrolador, en la entrada SHIFT REGISTER ¿que son y como se usan? puedes ver más sobre dichos integrados. En el caso del PIC16F877A y con sólo el display conectado no hace falta ahorrar, pero cuando se trata de una aplicación donde no nos quede muchos pines libres, es algo muy valioso, ya que pasaremos de requerir 10 pines en modo paralelo a sólo 4 en el modo serial y sólo el Pin que corresponde a la señal ENABLE debe ser exclusivo para el manejo del módulo, de modo que los demás pines podrán ser compartidos, inclusive los pines del shift register se podrían usar para, por ejemplo, controlar un teclado.
Para utilizar la líbreria en modo serial solo hace falta definir el macro "LCD_Serial" del siguiente modo:
#define LCD_Serial
Si queremos usar el bus de datos de 4 bits debemos definir, tambien antes de llamar a la librería, el macro "LCD_4Bits", mediante:
#define LCD_4Bits
Cabe destacar que cuando se utiliza el Bus de 4 bits, conexión paralela y está definido un puerto como bus, el dato se envía completo al puerto usado, pero el display LCD sólo reconoce los 4 MSB o sea <4:7>. Si no se desea escribir en todo el puerto cada vez que se utiliza el display, puede definir los 4 pines que serán los bits del bus al LCD del siguiente modo:
#define Bit0 Pin_X 
#define Bit1 Pin_X 
#define Bit2 Pin_X 
#define Bit3 Pin_X
Aquí puedes bajarte la última versión de la librería actualizada al día 6/11/2010 versión 1.03. Ahora disponible desde Dropbox

Control de un módulo LCD con PIC y CCS C

Partiendo de saber la Conexión y funciones de un módulo LCD ahora veremos como se utiliza en la práctica. Para empezar aquí les dejo el diagrama de la conexión mas básica para poder comenzar a utilizar el display.

Conexión LCD a PIC16F84A

En el diagrama utilizamos el Pin 0 del puerto A para la señal Enable del display y el Pin 1 del mismo puerto para la señal RS.

R/W lo conectamos directamente a GND ya que en este proyecto no leeremos el estado del display en ningún momento.
El puerto B lo dedicaremos enteramente al bus de datos del LCD.

Todos los puertos que no utilizaremos, asi como el RESET del PIC, los conectamos a 5V por medio de un resistor.

Alimentamos todo a 5V por medio de una fuente que puede llegar a ser la Fuente de alimentación y cargador de baterías explicada en este blog y listo.

Pero falta algo, el programa o firmware que hace que el display haga algo... Para eso debemos crear el código, compilarlo y grabarlo en el PIC para que este lo ejecute, nosotros usaremos CCS C .

La rutina que hace esto sería esta:

#include <16f84a.h>
#use delay (clock=4000000)

#define E Pin_A0
#define RS Pin_A1

/*  Declaro las funciones antes de utilizarlas en main()
    para que sean reconocidas  */

void print(int c);
void Enviar(int8 Dato, int1 Comando);
void Iniciar_LCD(void);

//Comienzo del programa

void main(void){
   Iniciar_LCD();                // Inicio el Modulo
   print ("PICROBOT");           // Escribo PICROBOT en la pantalla
}
                                       
//Funciones

void print(int8 c){
   enviar (c,1);                 // Envio caracter c con RS a 1 (dato)
                                 // CCS C se encarga de enviar uno a uno
}                                // los caracteres contenidos en c
                                     
void Enviar(int8 Dato, int1 Comando){
   output_low(E);                // E en bajo
   output_b(Dato);               // Cargo el puerto B con Dato
   output_bit(RS,comando);       // Pongo RS en 0 o 1 dependiendo si es
                                 // un comando o dato lo que estoy
                                 // enviando
   output_high(E);               // E en alto
   delay_us(1);                  // Espero a estabilizar tensión
   output_low(E);                // E en bajo
   delay_us(40);                 // Espero 40 uS a que el LCD trabaje
                                 //
   if (Dato < 4) delay_us(1600); // Si envio un Home o un Clear display
                                 // espero otros 1600 uSegundos que
                                 // sumado a los 40 uS anteriores hacen
}                                // 1.64 mS que es lo que tardan estas
                                 // operaciones

void Iniciar_LCD(void){          //
   delay_ms(15);                 // Espero a que se estabilice
                                 // la tensión.
   
   enviar(0b00000001,0);         // Envio un CLEAR DISPLAY
                                 // (Borra la pantalla)
   
   delay_ms(5);                  // Espero 5 mS
   
   enviar(0b00111000,0);         // Envio un FUNCTION SET para bus de 8
                                 // bits, 2 lineas y caracteres de 5x7
                                 // pixeles.
   
   enviar(0b00001100,0);         // Envio un DISPLAY ON/OFF CONTROL
                                 // con pantalla encendida, Cursor
                                 //  apagado y si parpadear.
   
   enviar(0b00000110,0);         // Envio un ENTRY MODE SET con 
                                 // Incrementa cursor y desplaza cursor
}

Este programa introducido en el PIC conectado al circuito anterior hace que nuestro módulo muestre en pantalla la frase:

PICROBOT

En realidad lo único que hace es inicializar el LCD y mostrar el mensaje, se puede adaptar y hacer que muestre cualquier frase cambiando simplemente la palabra PICROBOT por lo que deseen en la línea:

print ("PICROBOT");

Hay que aclarar que para que funcione hay que respetar las comillas.

Pero si arman el circuito y graban el PIC con la rutina, verán que pueden modificar la frase, pero siempre aparecerá en la primer línea. Si volvemos a Conexión y funciones de un módulo LCD y consultamos dichas funciones, veremos que hay una que se llama SET DD RAM ADDRESS; La memoria DD RAM es la que contiene los caracteres que están en pantalla. De modo que esa función se llama Establecer la dirección de la DD RAM, o sea, que lo que hace es cambiar la posición donde se almacenará el próximo caracter, por lo tanto, lugar donde aparecerá en pantalla.

Para hacer que escriba donde queramos, antes de escribir, deberemos ejecutar un SET DD RAM ADDRESS. Continuando con nuestra rutina lo podemos hacer del siguiente modo:

void locate(x,y){
   int d=128;                // Cargo d con 128 (10000000) b7 a 1
   d+=y*64;                  // si y (linea) es 1 sumo 64 a d (11000000) b6 a 1
   d+=x;                     // a todo esto le sumo la posicion de x
   enviar (d,0);             // envio todo al display con RS a 0 (comando)
}

Entonces si, por ejemplo, queremos escribir Hola en la primer línea y Mundo en la segunda, el main() de nuestra rutina se vería así:

void main(void){
   Iniciar_LCD();             // Inicio el Módulo
   locate(6,0);               // Ubico el cursor en la columna 6
                              // de la primer línea
   print ("HOLA");            // Escribo HOLA
   locate(5,1);               // Ubico el cursor en la columna 5
                              // de la segunda línea
   print ("MUNDO");           // y escribo MUNDO
}

En un display de 16 caracteres x 2 líneas se verá centrada la frase HOLA MUNDO. Cabe destacar que antes de poder utilizar la función locate() se debe declarar mediante la sentencia:

void locate(x,y);

Luego podemos simplificar el borrado de la pantalla (CLEAR DISPLAY) con la función:

void cls(void){
   enviar (1,0);              // envio 00000001 (Clear display) 
}                             // con RS a 0 (comando)

Recuerden que CLEAR DISPLAY era 00000001 que es igual a 1 en decimal. De esta forma y previamente declarado cada vez que querramos borrar la pantalla introduciremos en el código la línea cls(); Por último en la entrada Librería para el manejo de un módulo LCD en CCS C encontrarás todas las funciones y la opción para descargarla.

Conexión y funciones de un módulo LCD

Una pantalla de cristal líquido o LCD (Liquid Cristal Display) es un dispositivo para la presentación de imagenes o caracteres. En este caso usaremos uno basado en el µControlador Hitachi 44780 o compatible, que muestra 16 o 20 caracteres en 1, 2 o 4 líneas. Las funciones de control son iguales para todos los modelos.

Conexionado:
PINNombreDirecciónFunción
01VssPGND
02VddPAlimentación a 5V
03VeePControl de contraste
04RSISelección de Registro / Dato
05RWISelección de Escritura / Lestura
06EIEnable / Disable
07 - 14D0 - D7I/OBus de datos
15 - 16A - KPCorresponden al ánodo y cátodo del backlight  (si el modelo lo tiene)

Bueno, la operacion del display es bastante sencilla ya que el µControlador interno, hace casi todo el trabajo, para comandarlo debemos saber como funcionan sus pines.

Para enviar un comando o un dato deberemos primero indicar que es lo que estamos enviando para eso se usa el pin RS, cuando este pin esta en 0 el LCD interpretará la información que esta prensente en sus pines D0 a D7 como un comando, si está en 1 significa que estamos enviandole un caracter, en cuyo caso se imprimira donde esté actualmente el cursor.

Asimismo en lugar de enviar información puede llegar el momento en que queramos leer algo de su memoria, para eso se utiliza el pin R/W, en 0 el LCD estará en modo escritura y en 1 en modo lectura.

El pin E es el que le indica al display que ejecute la operación que estamos enviandole, cuando este pin esta en 0 cualquier modificación que hagamos en sus otros pines será ignorada. Entonces la forma de proceder será asi:


- Se colocan los pines RS en 1 o 0 dependiendo si vamos a enviar un caracter o una dirección.

- R/W a 0 si queremos enviar un caracter o un comando y en 1 si queremos leer algun dato del display.

- Ponemos D0 a D7 Con el valor del caracter que queremos imprimir, o con el comando que deseamos ejecutar en el display ( si R/W es 1 estos pines se convertiran en salidas y solo podremos leer el estado)

- Por ultimo se pone en alto el pin E y el display ejecutará la función.

Ahora bien, como ya comenté por ahi, el R/W no lo usaremos, ya que como nosotros escribiremos en el display no necesitaremos obtener ninguna información de el, para hacer esto basta con conectar el pin 5 (R/W) directamente a GND y el LCD estará siempre en modo escritura.

El funcionamiente se resumiría asi: RS nos servirá para indicarle al LCD si lo que le estamos mandando es un comando o un caracter; D0 a D7 para enviarle el dato o el comando y E para que lo ejecute.

Para enviar un caracter simplemente ponemos RS en 1 y el valor binario del caracter en los pines D0 a D7E y aparecerá nuestro caracter en pantalla. luego pasamos a 1 el pin.

Impresión de caracteres.

Pero esto solo nos permite escribir un caracter al lado de otro, para seleccionar donde escribir, borrar pantalla etc debemos hacer el mismo procedimiento pero con el pin RS en 0 y los pines D0 a D7 con el valor del comando correspondiente a la operación que queramos hacer:

CLEAR DISPLAY Borra el contenido de la pantalla.

HOMEColoca el cursor en el primer espacio de la primera línea sin modificar el contenido de la pantalla.

ENTRY MODE SETEspecifica el modo en que se imprimiran los caracteres. 

I/D = 0 Incrementa el cursor 
I/D=1 Decrementa el cursor  
S=0 Desplaza el cursor
S=1 Desplaza el display

DISPLAY ON/OFF CONTROL Control de encendido y apagado de la pantalla.

D=0 Pantalla apagado
D=1 Pantalla encendida
C=0 Oculta el cursor
C=1 Muestra el cursor
B=0 Cursor estático
B=1 Cursor parpadeante

CURSOR OR DISPLAY SHIFT Mueve el display o el cursor.

S/C=0 Mueve el cursor
S/C=1 Mueve el display
R/L=0 Mueve a la derecha
R/L=1 Mueve a la izquierda

FUNCTION SET Establece el bus de datos, cantidad de líneas y modo de caracteres.

DL=0 Bus de datos de 4 bits (D4 a D7)
DL=1 Bus de datos de 8 bits (D0 a D7)  
N=0 LCD de 1 línea  
N=1 LCD de 2 líneas
F=0 Caracteres de 5 x 7 pixeles
F=1 caracteres de 5 x 10 pixeles

SET CG RAM ADDRESS

Ingresando de este modo la dirección de la CG RAM, indica que cuando usemos el comando para escribir en el display, lo que enviaremos serán caracteres personalizados, se necesitan 7 instrucciones por caracter.

SET DD RAM ADDRESS

Cuando escribimos en el display lo que en realidad estamos diciendole al módulo que haga es almacenar X caracter en Y posición de memoria, con este comando indicamos en que lugar de la DD RAM se guardará el próximo caracter que enviemos. 80-8F corresponde a la memoria para la primera linea y C0-CF a la segunda.

Lo siguiente que nos queda es mostrar las rutinas para hacer todo esto, y eso lo pueden ver en este apartado: Control de un módulo LCD con PIC y CCS C


Tal vez le interese: