Há um bocado de tempo fiz um firmware que fazia isso, a única diferença é que era usando um LPC2105 ao invés de AVR, mas a idéia é a mesma.
Aqui vai a rotina de inicialização do LCD:
- Código: Selecionar todos
void lcd_init(void)
{
int x, y; // Variavel usada no contador
unsigned char bits = 0x10; // Variavel que contem os bits que gerarao os caracteres na CGRAM
espera(0x001E8480); // Espero 40ms
lcd_write(0, 0x30);
espera(0x000320C8); // Espero 4.1ms
lcd_write(0, 0x30);
espera(0x00001388); // Espero 100us
lcd_write(0, 0x30);
lcd_busywait();
lcd_write(0, 0x38); // Configuro para N=1 (duas linhas), F=0 (5x8 dots)
lcd_busywait();
lcd_write(0, 0x08); // Display off, cursor off, blink off
lcd_busywait();
lcd_write(0, 0x01); // Limpa o display e move o cursor para a primeira posição
lcd_busywait();
lcd_write(0, 0x06); // Seta incremento e shift
lcd_busywait();
// Final da inicializacao do display
// Vou configurar os primeiros 5 caracteres da CGRAM para barras verticais, para
// poder usar em progress bar
// O primeiro caracter é feito de bits 0001.0000, o segundo de 0001.1000 ate 0001.1111
lcd_write(0, 0x40); // Configuro para iniciar gravacao na CGRAM
lcd_busywait();
// Vou fazer dois loops, sendo o externo para selecionar os 5 caracteres, o interno as 8 posicoes
// de memoria de cada caracter
for(x=0; x!=5; x++)
{
for(y=0; y!=8; y++)
{
lcd_write(1, bits);
lcd_busywait();
}
bits = bits >> 1;
bits = bits + 0x10;
}
// Vou escrever no sexto byte os bits para formar o simbolo de graus a ser usado na medicao de temperatura
// Resultado:
// .....OO.
// ....O..O
// ....O..O
// .....OO.
// ........
// ........
// ........
// ........
lcd_write(1, 0x06);
lcd_busywait();
lcd_write(1, 0x09);
lcd_busywait();
lcd_write(1, 0x09);
lcd_busywait();
lcd_write(1, 0x06);
lcd_busywait();
lcd_write(1, 0x00);
lcd_busywait();
lcd_write(1, 0x00);
lcd_busywait();
lcd_write(1, 0x00);
lcd_busywait();
lcd_write(1, 0x00);
lcd_busywait();
lcd_write(0, 0x0C); // Ligo display, sem cursor e sem blinking
lcd_busywait();
}
As rotinas usadas acima, a rotina espera() ficava travada alguns ciclos, para gerar um delay preciso.
A rotina lcd_write tinha o seguinte protótipo:
static void lcd_write(unsigned char comando, unsigned char valor)
No caso comando era um flag, se fosse 0 era um comando, se fosse 1 era um caracter (basicamente este flag colocava o pino RS em nivel alto ou baixo). valor era o valor escrito nos pinos D0 a D7 do display (eu estava usando o display com 8 bits porque tinha GPIO sobrando).
O comando lcd_busywait() trava esperando um flag de not_busy do display (eu usei o pino de RW no display porque tinha GPIO sobrando, e o tratamento do display fica bem mais espertinho).
A primeira parte da rotina faz o reset do display, conforme o datasheet dele manda fazer, sem tirar nem por.
Logo após a incialização, tem dois loops aninhados. O que este loop faz é criar 5 caracteres na CGRAM. Estes caracteres são símbolos para fazer um bargraph.
Cada caracter do display pode ter resolução de 5x8 pixels. Se pensar em linha e colunas, o primeiro caracter é (. é pixel apagado, 0 é pixel aceso):
- Código: Selecionar todos
0....
0....
0....
0....
0....
0....
0....
0....
Se observar que a variável bits é inicializada com 0x10, isso em binário corresponde a 0001.0000 (o ponto eu coloco só pra separar os nibbles, meu costume, mas é um byte inteiro). Para o display, na CGRAM os três bits mais significativos não servem para nada. Dessa forma, escrevendo 0x10 nos primeiros 8 bytes da CGRAM gera um caracter que é uma linha vertical na coluna mais da esquerda.
Na segunda iteração do loop externo, o valor 0x10 é rotacionado uma vez prá direita, resultando em 0x08, ou 0000.1000 e depois é somado com 0x10, que resulta em 0001.1000. Escrevendo mais 8 vezes no display, gera um caracter assim:
- Código: Selecionar todos
00...
00...
00...
00...
00...
00...
00...
00...
Ou seja, um caracter onde as duas colunas mais da esquerda estão acesas.
O loop faz isso mais três vezes, gerando caracteres com três, quatro e cinco colunas acesas.
Com estes caracteres, eu consegui fazer um bargrapha que crescia da esquerda para a direita. Supondo que quizesse fazer o bargrapha crescer de 0 até 15, seria assim:
1. apaga o display (isso representa zero)
2. escreve o caracter 0 (na tabela do display, os primeiros 8 caracteres são da CGRAM), isso coloca 1 barra no display
3. escreve o caracter 1, isso coloca duas barras no display
4. escreve o caracter 2
5. escreve o caracter 3
6. escreve o caracter 4
7. não faz nada. Isso porque não é possível ter 6 barras horizontais na tela. Eu optei assim, o bargraph não daria saltos nas colunas vazias
8. mudar o cursor para segunda posição do display, escreve o caracter 1
9. escreve o caracter 2
e assim por diante.
Na rotina, após a criação das barras do bargraph, eu crio o caracter do símbolo °. Essa parte não tem mistério.
Bom, é isso, se alguma parte não ficou clara, é só perguntar que eu tento ajudar.
Abraço
98% das vezes estou certo, e não estou nem aí pros outros 3%.