Graphical LCD! Letras, números, imagens, gráficos...agora no seu projeto! Há alguns anos um GLCD era artigo de luxo, hoje com a commoditização dos componentes eletrônicos, é possível comprar com um punhado de dolares um de 128 X 64 pixels, lembrem-se que é gráfico, logo temos 8192 pixels (picture elements) para acender ou apagar, e assim formar a imagem que quisermos. Desse modo temos 1024 bytes (8192 / 8) disponíveis na memória ram do display. Para que isso funcione é preciso "gastar" alguns bits de seu microcontrolador: 8 bits de dados (P0, no nosso caso) e 4 bits de controle (E- enable, R/W - read/write, cs1 e cs2 - chip select, e finalmente RS ou DI que é o bit que seleciona se a porta de dados terá comandos para o GLCD ou dados, propriamente ditos.
A equipe do Solucionática usou nosso MCU 8051 para implementar esse projeto. Como é de praxe, fomos buscar um programa compatível com nosso hardware e após uma longa procura encontramos no excelente site Engineers Garage. O programa em C é muito simples e intuitivo...para quem conhece a fundo o GLCD! Mas, vamos estudar o programa e aos poucos vamos compreender o display. Primeiramente, vamos dar uma olhada no hardware. Como dá para perceber, há uma quantidade grande de fios, e um circuito auxiliar no protoboard, que é a parte responsável pelo ajuste do contraste do GLCD. Outro ponto importante é um fio roxo que foi acrescentado. Esse bit é o cs2.
Vamos explicar o funcionamento do programa que se encontra logo abaixo. A nossa versão tem algumas alterações para ficar compatível com a nossa IDE (MCU 8051). Uma delas é logo no começo (#include<8052.h>), pois o nosso microcontrolador é o AT80c52. Em seguida definimos a porta p0 como porta de dados e depois definimos rs (P2 bit 1); rw (P1, bit 5) etc.
O grande bloco que se segue é o mapeamento dos caracteres de A a F. O caractere A no formato 8X8, ou seja, uma matriz de 8 pixels de largura por 8 de altura, é dado por
unsigned char ar0[]={124,126,19,19,126,124,0,0}; onde os números estão em decimal. Tomando essa por exemplo, vamos ver como se "desenha" os caracteres no glcd.
65,127,127,65,99,62,28,0
Como dá para perceber, na primeira matriz, temos um "A" deitado. Dessa forma podemos gerar qualquer símbolo: "1" para o pixel ligado e "0" para desligado. Notem que efetivamente, dos 8 bits de largura, apenas 6 foram utilizados. Os outros dois são o espaço entre caracteres, para facilitar a leitura. Assim foi feito para se obter o B, C, D, E e F. nOTEM QUE Esse é o modo texto do display. Se quisermos mostrar um desenho, é melhor usar um aplicativo que converte um bitmap, por exemplo, em uma matrix de 1024 pontos. O programa mikroC tem um desses aplictivos:
Notem que carregamos um bitmap (arquivo de uma imagem em baixa resolução) e o programa gerou a linha de código pronta para ser usada no programa em C.
Continuando com análise do programa, observem que após a definição dos caracteres de A a F temos a primeira subrotina delay, que faz isso mesmo: delay. Em seguida é a subrotina ctrloff, que
/*Program to display simple text on Graphics LCD*/
/*Modified by Solucionatica in 23rd November 2014*/
#include<8052.h>
//#include<intrins.h>
#define dport P0
#define rs P2_1
#define rw P1_5
#define en P1_6
#define cs1 P2_0
#define cs2 P2_2
unsigned char c,z=0;
unsigned char ar0[]={124,126,19,19,126,124,0,0}; //A,8x8
unsigned char ar1[]={65,127,127,73,127,54,0,0}; //B,8x8
unsigned char ar2[]={28,62,99,65,65,99,34,0}; //C,8x8
unsigned char ar3[]={65,127,127,65,99,62,28,0}; //D,8x8
unsigned char ar4[]={65,127,127,73,93,65,99,0,}; //E,8x8
unsigned char ar5[]={ 65,127,127,73,29,1,3,0}; //F,8x8
unsigned char ar6[]={ 28,62,99,65,81,115,114,0}; //G,8x8
unsigned char ar7[]={127,127,8,8,127,127,0,0}; //H,8x8
unsigned char ar00[]={126,17,17,17,126}; //A,5x7
unsigned char ar11[]={127,73,73,73,54}; //B,5x7
unsigned char ar22[]={62,65,65,65,34}; //C,5x7
unsigned char ar33[]={127,65,65,34,28}; //D,5x7
unsigned char ar44[]={127,73,73,73,65}; //E,5x7
unsigned char ar55[]={127,9,9,1,1}; //F,5x7
unsigned char ar66[]={62,65,65,81,50}; //G,5x7
unsigned char ar77[]={127,8,8,8,127}; //H,5x7
void delay(unsigned int cnt)
{
while(--cnt);
}
void ctrloff()
{
rs=0;
rw=0;
en=0;
cs1=0;
cs2=0;
}
//Display on function
void displayon()
{
ctrloff();
dport=0x3f;
cs1=1;cs2=1;
rw=0;rs=0;
en=1;
delay(20);
en=0;
}
void setcolumn(unsigned char y)
{
if(y<64)
{
ctrloff();
c=y;
dport=0x40|(y&63); //0x40 represents Column 0
cs1=1;cs2=0;
rs=0;
rw=0;
en=1;
delay(20);
en=0;
}
else
{
c=y;
dport=0x40|((y-64)&63); //0x40 represents Column 0
cs2=1;cs1=0;
rs=0;
rw=0;
en=1;
delay(20);
en=0;
}
}
void setpage(unsigned char x)
{
ctrloff();
dport= 0xb8|x; //0xb8 represents Page 0
cs1=1;
cs2=1;
rs=0;
rw=0;
en=1;
delay(20);
en=0;
}
void lcddata(unsigned char *value,unsigned int limit)
{
unsigned int i;
for(i=0;i<limit;i++)
{
if(c<64)
{
dport=value[i];
cs1=1;cs2=0;
rs=1;
rw=0;
en=1;
delay(20);
en=0;
c++;
}
else
{
setcolumn(c);
dport=value[i];
cs2=1;cs1=0;
rs=1;
rw=0;
en=1;
delay(20);
en=0;
c++;
}
if(c>127)
return;
}
}
void clrlcd()
{
unsigned char i,j;
for (i=0;i < 8;i++)
{
setpage(i);
setcolumn(0);
for (j= 0 ;j < 128; j++)
lcddata(&z,1);
}
}
void main()
{
clrlcd();
while(1)
{
displayon();
setpage(0);
setcolumn(2);
lcddata(ar0,8);
setpage(1);
setcolumn(2);
lcddata(ar1,8);
setpage(2);
setcolumn(2);
lcddata(ar2,8);
setpage(3);
setcolumn(2);
lcddata(ar3,8);
setpage(4);
setcolumn(2);
lcddata(ar4,8);
setpage(5);
setcolumn(2);
lcddata(ar5,8);
setpage(6);
setcolumn(2);
lcddata(ar6,8);
setpage(7);
setcolumn(2);
lcddata(ar7,8);
setpage(0);
setcolumn(64);
lcddata(ar00,5);
setpage(1);
setcolumn(64);
lcddata(ar11,5);
setpage(2);
setcolumn(64);
lcddata(ar22,5);
setpage(3);
setcolumn(64);
lcddata(ar33,5);
setpage(4);
setcolumn(64);
lcddata(ar44,5);
setpage(5);
setcolumn(64);
lcddata(ar55,5);
setpage(6);
setcolumn(64);
lcddata(ar66,5);
setpage(7);
setcolumn(64);
lcddata(ar77,5);
}
}