Una forma sencilla de saber lo que pasa en nuestro microcontrolador es
usar un LCD, mediante su uso podemos comprobar el estado de los
registros internos del micro, verificar el funcionamiento de la
electrónica y los programas que hagamos, por ejemplo si
queremos comprobar que la lectura de un ADC en nuestro programa es
correcta, pues no tenemos más opciones que usar un LCD o el
PC para poder visualizar lo que está leyendo el micro.
Un LCD es un dispositivo que muestra
caracteres alfanuméricos en una pantalla de varias
líneas, todo LCD lleva un microcontrolador interno que se
encarga de gobernar su funcionamiento (el más
común es el
Hitachi 44780), este microcontrolador tiene unos pines para comunicarse
con el mundo exterior y así poder realizar las distintas
operaciones sobre la pantalla del LCD, lo que hace que manejar la
pantalla sea muy sencillo y que merezca la pena añadirlo a
cualquier proyecto mientras se realiza.
Resumen LCD.
Esquema de un LCD.
El lcd dispone de los siguientes pines.
Los 3 primeros son de alimentación, usandose el 3 pin para
establecer el contraste del LCD en función de su nivel de
tensión mediante un divisor resistivo, la
conexión es la
siguiente:
Pines del 7 al 14: bus de datos, por donde mandaremos la
información al lcd.
Pines de control:
El pin 6: Enable habilita (1) o deshabilita (0) el módulo.
Encendiendolo y apagandolo le indicamos al lcd que vamos a realizar una
operación sobre él y éste pasa a leer
el resto de los pines para recibir la orden.
El pin 5: R/W indica si se va a hacer una operación de
escritura (0) o lectura (1).
El pin 4: RS selecciona el registro del LCD que vamos a usar, el LCD
tiene dos registros de 8 bits, un registro de instrucciones (0) y otro
de datos (1), seleccionando el de instrucciones indicamos al lcd
que lo que hay en el bus de datos (pines desde 7 a 14) es una
instrucción, y seleccionando el registro de datos indicamos
al
LCD que lo que tenemos en el bus de datos es un carácter
cuyo
destino es la DDRAM o la CGRAM que son las dos zonas de memoria del LCD.
Con los pines 4 y 5 tenemos las siguientes combinaciones.
00: mandomos un comando al LCD, como puede ser limpiar la pantalla o
situar el cursor en cierto punto de la pantalla. En el bus de datos
estará el código del comando a realizar.
01: cuando le damos una orden al lcd éste tarda un tiempo en
realizarla, por lo que hasta que no termine no le podemos mandar
ordenes nuevas, nos indica que está ocupado poniendo el pin
14 a
1 por lo que para poder leer este pin debemos poner RS a 0 y R/W a 1
(leer). Podemos evitar la lectura de este pin haciendo pausas de cierto
tiempo cada vez que mandamos una instrucción.
10 y 11: para leer o escribir datos en la DDRAM y CGRAM.
La DDRAM (Data Display RAM) es una zona de memoria donde se almacenan
los caracteres que se van a representar en la pantalla, su capacidad es
de 80x8 bits = 80 caracteres, 20 por línea. Cada vez que se
escribe un dato en ésta se apunta a la siguiente
posición.
Posición en memoria de cada carácter en la
pantalla.
Las posiciones de los caracteres en la memoria cuando se
usan 4 líneas de pantalla no son consecutivas, de la
línea 1 pasa a la línea 3, cosa que tendremos que
tener en cuenta si queremos escribir caracteres de manera secuencial.
En la CGRAM podemos dibujar nuestros propios caracteres, se pueden
almacenar hasta 4 de 5x10 puntos y hasta 8 de 5x8 puntos.
La CGROM genera los caracteres disponibles para representar en la
pantalla a partir de un código de 8 bits.
Cuando tengamos un 1 en el bit RS, los 8 bits del bus de datos
representarán uno de los caracteres siguientes.
Con un 0 en RS tendremos que mandar uno de los siguientes comandos por
los 8 bits del bus de datos.
Entry mode set: valor 0x06 para el desplazamiento normal a derechas.
Function Set:
DL=0 comunicación mediante 4
bits del bus de datos, a 1 mediante 8 bits.
F=1 Caracteres 5x10 puntos, 0 caracteres
5x8 puntos.
N= 1 pantalla de 4 líneas, 0
pantalla de 2 líneas.
Podemos tener un bus de datos de 8 bits usando los 8 pines disponibles
en el LCD para este fin, o un bus de datos de 4 bits dejando los bits
DB0 a DB3 sin conectar, si lo hacemos de esta forma tendremos que
mandar cada carácter e instrucción en dos partes.
Debido
a que tenemos un micro con muchos pines de I/0 se va a usar la
configuración de 8 bits que además de ser
más
rápida hace que la programación sea
más
fácil. Si tenemos un micro con pocos pines de I/0
necesitaremos
un mínimo de 6 pines para escribir en el LCD (RS, E y 4 de
datos).
Para inicializar el LCD lo debemos hacer de la siguiente forma mandando
las ordenes según nos indica con las opciones de
configuración que deseamos.
Tiempos señales escritura.
Programa para manejar un
LCD con la placa de Arduino.
Aunque aún no me he leído la
documentación que he reuinido del AVR y el compilador voy a
ir escribiendo código y ya me iré mirando las
cosas según las vaya necesitando, que así leerse
cientos de hojas de pdfs y datasheet se hace menos pesado...
Éste es el código para escribir en un LCD con la
placa
de Arduino Mega con WinAVR (si hay una opción libre hay que
usarla) que utilizaré en todos los programas siguientes para
verificar el correcto funcionamiento de los distintos componentes que
forman el proyecto del robot hexápodo.
Todo ésto ya
está hecho y hay librerias disponibles para un LCD (y bien
hechas..) por lo que no
tiene sentido reinventar la rueda, pero el fin no es crear algo que ya
está creado, si no aprender mientras se hace. Si el objetivo
fuese hacer un robot hexápodo pues podríamos
comprarlo
con toda la electrónica y programas ya hechos directamente.
El bit de Busy Flag no se usa, en su lugar se mete un retardo
después de enviar cada instrucción, lo
próximo son las interrupciones para los botones y el ADC
para manejar el potenciometro de la placa, y para eso si que hay que
leer x_x.
//Funciones para
escribir en un lcd.
//8 bits de bus de datos.
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#define Bus_Datos PORTA
#define Bus_Control PORTD
#define RS PORTD0
//Todos deben de pertenecer
al mismo puerto
#define RW PORTD1
#define E PORTD2
//Comandos para situar el cursor en inicio de líneas.
#define DDRA_LINEA1 0x80 //1000 0000
#define DDRA_LINEA2 0xC0 //1100 0000
#define DDRA_LINEA3 0x94 //1001 0100
#define DDRA_LINEA4 0xD4 //1101 0100
void inicializar();
//Funciones para escribir en el LCD
void lcd_inicializar();
void lcd_escribir_c(unsigned char caracter);
void lcd_escribir(unsigned char *cadena);
void posicionar_cursor(unsigned char x, unsigned char y);
void lcd_comando(unsigned char comando);
int main(void)
{
inicializar();
lcd_inicializar();
unsigned char
linea1[]=" www.jmnlab.com"; //Poner en la
Flash de programa las cadenas.
unsigned char linea2[]=" Proyecto
Hexapodo";
unsigned char linea3[]=" Prueba de LCD
4x20";
lcd_escribir(linea2);
//Escribo una cadena, empieza
en línea 1, carácter 1.
posicionar_cursor(2,1);
//Línea 2, primer carácter.
lcd_escribir(linea1);
posicionar_cursor(3,1);
lcd_escribir(linea3);
posicionar_cursor(4,5);
lcd_escribir_c('A');
//Escribir los caracteres uno a uno,
comprobación de su función correspondiente.
lcd_escribir_c('r');
lcd_escribir_c('d');
lcd_escribir_c('u');
lcd_escribir_c('i');
lcd_escribir_c('n');
lcd_escribir_c('o');
lcd_escribir_c(' ');
lcd_escribir_c('M');
lcd_escribir_c('e');
lcd_escribir_c('g');
lcd_escribir_c('a');