Professional Documents
Culture Documents
Engenharia Elétrica
6º / 7° Semestre
ÍNDICE..........................................................................................................................................................................2
INTRODUÇÃO..............................................................................................................................................................5
Capítulo 1 - O LCD ALFA-NUMÉRICO ........................................................................................................................9
Figura 1: Display 08X02 sem back-light.........................................................................................................9
Figura 2: Display 16X01 sem back-light.........................................................................................................9
Figura 3: Display 16X02 com back-light.........................................................................................................9
Figura 4: Display 16X04 com back-light.......................................................................................................10
Figura 5: Display 20X01 sem back-light.......................................................................................................10
Figura 6: Display 20X02 sem back-light.......................................................................................................10
Figura 7: Display 20X04 com back-light.......................................................................................................10
Parte 1 - Os caracteres .......................................................................................................................................11
Figura 8: O padrão de cada célula de um display 5X7 (em mm).................................................................11
Parte 2 - Conexões..............................................................................................................................................12
Tabela 1: Descrição das funções dos pinos do LCD ...................................................................................12
Figura 9: Controle de contraste de um LCD ................................................................................................13
Parte 3 - Comandos do LCD ...............................................................................................................................14
Figura 10: LCD 16X02 energizado, mas não inicializado. ...........................................................................14
Tabela 2: Instruções para inicialização e configuração do LCD ..................................................................14
Tabela 3: Configurações possíveis para o LCD ..........................................................................................15
Parte 4 - Tabelas de Caracteres .........................................................................................................................17
Tabela 4: Os caracteres do ROM Code A00 ...............................................................................................17
Tabela 5: Os caracteres do ROM Code A02 ...............................................................................................18
Parte 5 - Endereçamento ....................................................................................................................................19
Figura 11: Endereçamento direto para um LCD 16X02...............................................................................19
Figura 12: Endereçamento com deslocamento para um LCD 16X02 .........................................................19
Figura 13: Endereçamentos com deslocamento para diversos LCDs.........................................................20
Parte 6 - Rotacionando o LCD ............................................................................................................................20
Parte 7 - A CGRAM – Caracteres definidos pelo usuário ...................................................................................20
Figura 14: O modelo do caractere na CG RAM...........................................................................................21
Figura 15: Criando um robô na CG RAM.....................................................................................................21
Figura 16: O robô, traduzido em bits............................................................................................................21
Parte 8 - Transferência em 8 bits ........................................................................................................................23
Figura 17: Inicializando em 8 vias................................................................................................................23
Parte 9 - Transferência em 4 bits ........................................................................................................................24
Figura 18: Inicializando em 4 vias................................................................................................................25
Parte 10 - Timing .................................................................................................................................................26
Figura 19: Diagrama de temporização para o LCD .....................................................................................26
6: Diagrama de temporização real para o LCD............................................................................................27
Capítulo 2 - O HARDWARE .......................................................................................................................................31
Figura 20: Esquemático para a placa de testes de LCD .............................................................................31
Figura 21: PCI lado dos componentes.........................................................................................................32
Figura 22: PCI lado da solda (trilhas)...........................................................................................................32
Figura 23: Placa de testes conectada ao McPlus via conector ICSP..........................................................32
Capítulo 3 - O SOFTWARE ........................................................................................................................................35
Parte 1 – Comunicação em 8 vias pela McLAB2 ................................................................................................35
Parte 2 – Comunicação em 4 vias pela McLAB2 ................................................................................................38
Definição de constantes ...............................................................................................................................38
Rotina de envio de um “nibble” ....................................................................................................................38
Rotina de envio de um Byte .........................................................................................................................39
Função para Limpar o LCD..........................................................................................................................39
Inicialização do LCD.....................................................................................................................................40
Parte 3 – Comunicação em 4 vias pela placa de testes .....................................................................................42
Definição de constantes ...............................................................................................................................42
Outras alterações .........................................................................................................................................42
Exercício 1 – Inicializando o LCD e “Olá Mundo”.......................................................................................................45
McLAB2 ...............................................................................................................................................................45
Figura 24: Fluxograma para a placa McLAB2 .............................................................................................45
Placa de testes ....................................................................................................................................................50
Figura 25: Fluxograma para a placa de testes ............................................................................................50
Exercício 2 – A função PRINTF() ...............................................................................................................................57
McLAB2 ...............................................................................................................................................................58
Tutorial LCD em 4 vias 2
Figura 26: Fluxograma para a placa McLAB2 .............................................................................................58
Placa de testes ....................................................................................................................................................63
Figura 27: Fluxograma para a placa de testes ............................................................................................63
Exercício 3 – Rotacionando o display ........................................................................................................................71
McLAB2 ...............................................................................................................................................................72
Placa de testes ....................................................................................................................................................76
Exercício 4 – Criando caracteres................................................................................................................................83
Figura 28: Fluxograma para o exemplo 4 ....................................................................................................83
McLAB2 ...............................................................................................................................................................84
Placa de testes ....................................................................................................................................................89
Exercício 5 – Uma pequena animação.......................................................................................................................97
Figura 29: Fluxograma para a animação nas placas McLAB2 e de testes .................................................97
McLAB2 ...............................................................................................................................................................98
Placa de testes ..................................................................................................................................................103
CONSIDERAÇÕES FINAIS......................................................................................................................................111
Estes caracteres são conhecidos como 5X7, uma vez que a linha inferior é normalmente
reservada para o cursor. Existem também displays que possuem 11 pixels de altura. Os
caracteres deste LCD são conhecidos como 5X10 e tem a vantagem de que não existe a
distância entre a primeira e a segunda linha. Os caracteres podem parecer contíguos.
O pino 4 (RS) é o Seletor de Registros. Resumindo, quando este pino está em nível
lógico baixo (0), os dados enviados para o LCD são tratados como comandos e os dados lidos
do LCD indicam o seu estado atual (status). Quando este pino está em nível lógico alto (1), os
dados são tratados como caracteres, tanto para leitura como para escrita.
Para indicar se os dados serão lidos ou escritos no LCD, existe o pino 5 (R/W) que
controla exatamente se a operação em andamento será de leitura (quando estivem em nível
lógico alto - 1) ou gravação (quando estiver em nível lógico baixo - 0).
O pino 6 (E) é a linha de habilitação para os comandos do LCD. É utilizado para iniciar a
transferência de comandos ou caracteres entre o módulo e as linhas de dados. Quando estiver
escrevendo para o display, os dados serão transmitidos apenas a partir de uma transição de
high para low (H -> L) deste sinal. No entanto, para ler informações do display, as informações
estarão disponíveis imediatamente após uma transição L -> H e permanecerá lá até que o sinal
volte para o nível lógico baixo (0) novamente.
Os pinos 7 a 14 fazem parte do barramentos de dados. Ele trabalha com os oito sinais
em paralelo ou ainda pode trabalhar com um barramento de 4 vias (normalmente D4 a D7),
mas os dados devem ser transmitidos em dois pacotes. Cada pacote de quatro bits é
conhecido como "nibble". Este é um excelente recurso para minimizar o uso de pinos de I/O do
microcontrolador, mas ocupa um pouco mais de memória. A decisão de utilizar 8 vias ou 4 vias
é exclusiva do desenvolvedor do projeto.
Ao ligar o LCD na alimentação, a primeira linha fica toda preenchida (veja foto abaixo).
Para que ele fique operacional, precisamos inicializá-lo, passando diversas informações de
configuração. Para isso, existem alguns parâmetros que precisam ser definidos. A tabela 2 a
seguir mostra quais são estes comandos.
Ciclos
Instrução RS RW D7 D6 D5 D4 D3 D2 D1 D0 Descrição de
Clock
NOP 0 0 0 0 0 0 0 0 0 0 Sem efeito 0
Como parte integrante do controlador que o LCD utiliza, há uma tabela de caracteres
pré-programados que estão prontos para uso imediato. Com isso, todo o trabalho de definir
pixel por pixel para os caracteres foi eliminado. Mas há uma desvantagem. Como a maioria dos
LCDs são produzidos na Ásia, ele vem com um conjunto de caracteres específicos. A figura a
seguir mostra a tabela existente na maioria dos LCDs. Ela é conhecida como ROM Code A00.
Parte 5 - Endereçamento
Após ligarmos o LCD e o iniciarmos, o cursor irá para a primeira posição que é a 0x00
(primeira linha x primeira coluna). De acordo com que vamos inputando dados nele, o cursor irá
deslocar para as posições seguintes. Este auto-incremento é uma facilidade muito
interessante, pois dispensa especificar cada posição para cada caractere em separado,
economizando (e muito) em linhas de códigos necessárias.
fMas, e se quisermos escrever em um ponto específico do LCD?
Neste caso, podemos especificar exatamente qual é o endereço que o cursor deverá
estar para exibir o caractere desejado. Este dado será passado para o LCD pelas mesmas vias
de dados que passamos um caractere, só que dessa vez será um comando. De acordo com a
Tabela 2, para entrarmos com um comando para setar um endereço na DDRAM do LCD
precisaremos ter o pino RS e RW em nível lógico baixo e o bit mais significativo precisa estar
obrigatoriamente em nível lógico alto. Com isso podemos endereçar até 128 posições e, ao
passar o endereço, deveremos somar este bit, ou seja, precisaremos somar o valor 0x80 ao
endereço desejado.
Para ilustrar, o endereçamento de um display LCD 16X02 é o seguinte:
Como devemos, obrigatoriamente fazer com que o bit mais significativo do endereço
seja 1, o valor que devemos passar para o LCD obedece à figura abaixo:
Independente do tamanho do LCD existem sempre 80 posições por linha que podem ser
usadas. Como não existem posições suficientes no mostrador do LCD, o texto é rotacionado ou
deslocado, tanto para a direita como para a esquerda. Portanto este processo deve ser feito
cuidadosamente para que não haja confusões durante o endereçamento.
Este modo também será estudado durante os exercícios.
Figura 21: PCI lado dos componentes Figura 22: PCI lado da solda (trilhas)
O conector ICSP foi dimensionado para utilizar diretamente com os programadores
McFlash e McPlus, evitando assim que o PIC tenha que ser retirado do circuito para ser
programado.
Outro detalhe diz respeito ao regulador de tensão LM7805 que pode ser substituído pelo
78L05, devido ao baixo consumo do circuito.
Todos os componentes estão detalhados tanto no esquemático quanto no desenho da
PCI – Lado dos componentes, são facilmente encontrados no mercado e são de baixo custo.
A foto abaixo mostra a placa conectada diretamente no McPlus.
Como este protótipo não utiliza oscilador ou ressonador externo, apenas o interno
calibrado à 4MHz, utilizou-se o pino CLOCKOUT para realizar aferições para calibragem.
O PIC aqui utilizado foi o 16F628A.
Este é o código necessário para exibir uma mensagem no LCD, utilizando o PORTD do
PIC16F877A da placa McLAB2
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* VERSÃO : 1.0 *
* DATA : 23/09/2005 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Este exemplo foi elaborado para explicar o funcionamento do módulo de LCD.
// Foi utilizado um barramento de 8 vias de comunicação pelo PORTD
Como parte didática, a codificação foi dividida em várias partes que serão detalhadas a
seguir. Observe que todas estas rotinas partem do princípio que o pino R/W do LCD está
aterrado, garantindo sempre nível lógico “0”, ou seja, poderemos apenas enviar informações
(apenas escrita). As características de leitura do LCD ficam bloqueadas. Por isso, não
poderemos verificar o STATUS BIT para saber quando ele estará pronto para processar outra
informação. Devido a estes fatores, devemos nos basear no tempo mínimo par cada operação,
estabelecida na Tabela 6.
O fato de termos aterrado o pino R/W não é uma deficiência no protótipo e sim uma
característica da maioria dos projetos comerciais.
Definição de constantes
Antes de começarmos a programação propriamente dita, precisamos informar quais são
os pinos de I/O que serão utilizados pelo nosso LCD. Este procedimento faz com que a
portabilidade entre os códigos e entre LCDs seja maximizada. Estas são as linhas que
devemos incluir em nosso programa principal, juntamente com outras constantes internas:
/********************************************************************************/
/* Envio de Byte para o LCD */
/********************************************************************************/
//Esta rotina irá enviar um dado ou um comando para o LCD conforme abaixo:
// ENDEREÇO = 0 -> a variável DADO será uma instrução
// ENDEREÇO = 1 -> a variável DADO será um caractere
void envia_byte_lcd(boolean endereco, int dado)
{
output_bit(lcd_rs,endereco); // Seta o bit RS para instrução ou caractere
delay_us(100); // Aguarda 100 us para estabilizar o pino do LCD
output_low(lcd_enable); // Desativa a linha ENABLE
envia_nibble_lcd(dado>>4); // Envia a parte ALTA do dado/comando
envia_nibble_lcd(dado & 0x0f);// Limpa a parte ALTA e envia a parte BAIXA do
// dado/comando
delay_us(40); // Aguarda 40us para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/********************************************************************************/
/* Função para limpar o LCD */
/********************************************************************************/
//
void limpa_lcd()
{
envia_byte_lcd(0,0x01); // Envia instrução para limpar o LCD
delay_ms(2); // Aguarda 2ms para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
Inicialização do LCD
A seguir, temos o código para inicializar um LCD em 4 vias. A primeira ação da rotina é
forçar todas as linhas para o nível lógico “0”. O passo seguinte é aguardar 15ms para
estabilizar o LCD, após ser energizado. Até este ponto, é o mesmo procedimento para os
modos de 8 e 4 vias. Após este ponto, precisamos mandar as informações para inicialização
básica do LCD que consiste em enviar três vezes o “nibble” 0x03, ou enviar o byte 0x30. Para
efeito de economia de código e utilizando a característica de que a rotina envia_nibble_lcd()
trabalha com o “nibble” inferior, será melhor enviarmos o comando 0x03. Repare que devemos
aguardar um tempo para estabilizar o LCD. Como este é um procedimento executado apenas 1
vez em todo o ciclo do PIC e verificando que o tempo determinado na maioria dos data sheets
são inferiores ou muito próximos a 5ms, adotou-se este valor como intervalo mínimo entre as
fases iniciais de configuração, onde devemos enviar 3 comando 0x03. Após isso, vamos enviar
o “nibble” para posicionar o cursor para a posição inicial e, ainda seguindo a Tabela 6,
devemos aguardar de 40us a 4,1ms . Por padrão foi adotado 1ms. Aqui também cabe a
observação de que, se o display apresentar instabilidades, este tempo deve ser alterado. Em
seguida é enviado o “nibble” 0x20 que indica que o LCD será configurado para 4 vias de dados,
e 1 linha com matriz de 7X5 com cursor. Este valor pode ser alterado a fim de realizar testes,
conforme descrito nas Tabelas 2 e 3. Repare que para este último comando, é necessário
enviar um byte completo e não apenas um “nibble”.
Estes são os procedimentos iniciais e obrigatoriamente deve seguir esta seqüência. A
partir deste ponto podemos entrar com as configurações constantes nas Tabelas 2 e 3 em
qualquer ordem. É importante salientar também que as instruções constantes a partir deste
ponto, assim como a de posicionamento do cursor (CURSOR HOME) podem ser utilizadas em
qualquer ponto do programa e não apenas na inicialização do LCD. Com isso fica fácil
implementar, por exemplo, uma rotina do tipo “backspace”.
Os comando seguintes enviam um byte completo (e não apenas um “nibble”) para as
configurações de controle do display (Display control) e para os deslocamentos desejados
(Entry Mode Set).
Sempre use as Tabelas 2 e 3 como referência.
E para finalizar, existe o comando RETURN para retornar ao ponto onde a rotina foi
chamada. Novamente esta é uma boa prática, mas este comando pode ser retirado, uma vez a
função sempre retorna ao ponto onde foi chamada.
Para configurar a placa de testes sugerida neste documento, basta alterar as definições
das constantes declaradas no início do programa. Com isto fica muito fácil visualizar quão
poderosa é esta rotina. Ela pode ser implementada em qualquer projeto que você estiver
desenvolvendo.
Definição de constantes
Antes de começarmos a programação propriamente dita, precisamos informar quais são
os pinos de I/O que serão utilizados pelo nosso LCD. Este procedimento faz com que a
portabilidade entre os códigos e entre LCDs seja maximizada. Estas são as linhas que
devemos incluir em nosso programa principal, juntamente com outras constantes internas:
#define lcd_enable pin_b5 // pino enable do LCD
#define lcd_rs pin_b4 // pino rs do LCD
#define lcd_db4 pin_b0 // pino de dados d4 do LCD
#define lcd_db5 pin_b1 // pino de dados d5 do LCD
#define lcd_db6 pin_b2 // pino de dados d6 do LCD
#define lcd_db7 pin_b3 // pino de dados d7 do LCD
Outras alterações
É obvio que, além destas configurações, o tipo de processador, fuses, declaração e
inicialização de PORTs e TRIS, assim como as configurações básicas do microcontrolador
deverão ser adequados, uma vez que utilizamos o PIC16F628A ao invés do PIC16F877A
existente na McLAB2.
Isso ficará bem claro ao comparar os dois códigos referentes a um mesmo exercício.
McLAB2
O fluxograma necessário para realizar este primeiro exercício é exibido na figura abaixo:
Início
Define Microcontrolador
Configura o PIC:
Reseta PORTs
Configura TRIS
Inicializa o LCD
Escreve na tela
Final
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Primeiro teste de LCD em 4 vias - Olá Mundo
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição do PIC utilizado *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <16f877a.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#fuses XT,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP,NOCPD,NOWRT
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use delay(clock=4000000)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Estas são as definições dos pinos que o LCD utiliza.
// Definem quais pinos do PIC controlarão os pinos do LCD
#define lcd_enable pin_e1 // pino enable do LCD
#define lcd_rs pin_e0 // pino rs do LCD
#define lcd_db4 pin_d4 // pino de dados d4 do LCD
#define lcd_db5 pin_d5 // pino de dados d5 do LCD
#define lcd_db6 pin_d6 // pino de dados d6 do LCD
#define lcd_db7 pin_d7 // pino de dados d7 do LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a) // Inicialização rápida dos Pinos de I/O
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
/***************************************************************************/
/* Rotinas para o LCD */
/***************************************************************************/
Tutorial LCD em 4 vias 46
//Este é o bloco com as rotinas necessárias para manipular o LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de "Nibble" para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina lê o "Nibble" inferior de uma variável e envia para o LCD.
void envia_nibble_lcd(int dado)
{
//Carrega as vias de dados (pinos) do LCD de acordo com o nibble lido
output_bit(lcd_db4, bit_test(dado,0)); //Carrega DB4 do LCD com o bit DADO<0>
output_bit(lcd_db5, bit_test(dado,1)); //Carrega DB5 do LCD com o bit DADO<1>
output_bit(lcd_db6, bit_test(dado,2)); //Carrega DB6 do LCD com o bit DADO<2>
output_bit(lcd_db7, bit_test(dado,3)); //Carrega DB7 do LCD com o bit DADO<3>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de Byte para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina irá enviar um dado ou um comando para o LCD conforme abaixo:
// ENDEREÇO = 0 -> a variável DADO será uma instrução
// ENDEREÇO = 1 -> a variável DADO será um caractere
void envia_byte_lcd(boolean endereco, int dado)
{
output_bit(lcd_rs,endereco);// Seta o bit RS para instrução ou caractere
delay_us(100); // Aguarda 100 us para estabilizar o pino do LCD
output_low(lcd_enable); // Desativa a linha ENABLE
envia_nibble_lcd(dado>>4); // Envia a parte ALTA do dado/coamndo
envia_nibble_lcd(dado & 0x0f);// Limpa a parte ALTA e envia a parte BAIXA do
// dado/comando
delay_us(40); // Aguarda 40us para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de caractere para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina serve apenas como uma forma mais fácil de escrever um caractere
// no display. Ela pode ser eliminada e ao invés dela usaremos diretamente a
// função envia_byte_lcd(1,"<caractere a ser mostrado no lcd>"); ou
// envia_byte_lcd(1,<código do caractere a ser mostrado no lcd>);
void escreve_lcd(char c)
// envia caractere para o display
{
envia_byte_lcd(1,c);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como esta operação pode ser muito utilizada, transformando-a em função
// faz cvom que o código compilado seja menor.
void limpa_lcd()
{
envia_byte_lcd(0,0x01); // Envia instrução para limpar o LCD
delay_ms(2); // Aguarda 2ms para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
Tutorial LCD em 4 vias 47
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Inicializa o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void inicializa_lcd()
{
output_low(lcd_db4); // Garante que o pino DB4 estão em 0 (low)
output_low(lcd_db5); // Garante que o pino DB5 estão em 0 (low)
output_low(lcd_db6); // Garante que o pino DB6 estão em 0 (low)
output_low(lcd_db7); // Garante que o pino DB7 estão em 0 (low)
output_low(lcd_rs); // Garante que o pino RS estão em 0 (low)
output_low(lcd_enable);// Garante que o pino ENABLE estão em 0 (low)
delay_ms(15); // Aguarda 15ms para estabilizar o LCD
/***************************************************************************/
/* Final das rotinas para o LCD */
/***************************************************************************/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Pic *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
main()
{
// Configura o PIC
setup_adc_ports(no_analogs);
// Reseta portas
porta = 0;
portb = 0;
portc = 0;
portd = 0;
porte = 0;
// configura os tris
set_tris_a(0b00111111); // configuração da direção dos pinos de I/O
set_tris_b(0b11111111);
set_tris_c(0b11111111);
set_tris_d(0b00001111);
set_tris_e(0b11111100);
// Inicializa o LCD
inicializa_lcd();
//Escreve tela
escreve_lcd("O");
escreve_lcd("l");
escreve_lcd("a");
escreve_lcd(" ");
Tutorial LCD em 4 vias 48
escreve_lcd("M");
escreve_lcd("u");
escreve_lcd("n");
escreve_lcd("d");
escreve_lcd("o");
escreve_lcd("!");
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como não há outra execução, a rotina principal fica vazia
while (true)
{
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
}
O fluxograma necessário para realizar este primeiro exercício é exibido na figura abaixo:
Início
Define Microcontrolador
Configura o PIC:
Reseta PORTs
Configura TRIS
Inicializa o LCD
Escreve na tela
Final
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Primeiro teste de LCD em 4 vias - Olá Mundo
//
//
//
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição do PIC utilizado *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <16f628a.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#fuses INTRC,NOWDT,PUT,MCLR,NOBROWNOUT,NOLVP
#ROM 0x07ff = {0} //Calibragem do oscilador interno
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use delay(clock=4000000)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Estas são as definições dos pinos que o LCD utiliza.
// Definem quais pinos do PIC controlarão os pinos do LCD
#define lcd_enable pin_b5 // pino enable do LCD
#define lcd_rs pin_b4 // pino rs do LCD
#define lcd_db4 pin_b0 // pino de dados d4 do LCD
#define lcd_db5 pin_b1 // pino de dados d5 do LCD
#define lcd_db6 pin_b2 // pino de dados d6 do LCD
#define lcd_db7 pin_b3 // pino de dados d7 do LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a) // Inicialização rápida dos Pinos de I/O
#use fast_io(b)
/***************************************************************************/
/* Rotinas para o LCD */
/***************************************************************************/
Tutorial LCD em 4 vias 51
//Este é o bloco com as rotinas necessárias para manipular o LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de "Nibble" para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina lê o "Nibble" inferior de uma variável e envia para o LCD.
void envia_nibble_lcd(int dado)
{
//Carrega as vias de dados (pinos) do LCD de acordo com o nibble lido
output_bit(lcd_db4, bit_test(dado,0)); //Carrega DB4 do LCD com o bit DADO<0>
output_bit(lcd_db5, bit_test(dado,1)); //Carrega DB5 do LCD com o bit DADO<1>
output_bit(lcd_db6, bit_test(dado,2)); //Carrega DB6 do LCD com o bit DADO<2>
output_bit(lcd_db7, bit_test(dado,3)); //Carrega DB7 do LCD com o bit DADO<3>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de Byte para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina irá enviar um dado ou um comando para o LCD conforme abaixo:
// ENDEREÇO = 0 -> a variável DADO será uma instrução
// ENDEREÇO = 1 -> a variável DADO será um caractere
void envia_byte_lcd(boolean endereco, int dado)
{
output_bit(lcd_rs,endereco); // Seta o bit RS para instrução ou caractere
delay_us(100); // Aguarda 100 us para estabilizar o pino do LCD
output_low(lcd_enable); // Desativa a linha ENABLE
envia_nibble_lcd(dado>>4); // Envia a parte ALTA do dado/comando
envia_nibble_lcd(dado & 0x0f);// Limpa a parte ALTA e envia a parte BAIXA do
// dado/comando
delay_us(40); // Aguarda 40us para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de caractere para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina serve apenas como uma forma mais fácil de escrever um caractere
// no display. Ela pode ser eliminada e ao invés dela usaremos diretamente a
// função envia_byte_lcd(1,"<caractere a ser mostrado no LCD>"); ou
// envia_byte_lcd(1,<código do caractere a ser mostrado no LCD>);
void escreve_lcd(char c)
// envia caractere para o display
{
envia_byte_lcd(1,c);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como esta operação pode ser muito utilizada, transformando-a em função
// faz com que o código compilado seja menor.
void limpa_lcd()
{
envia_byte_lcd(0,0x01); // Envia instrução para limpar o LCD
delay_ms(2); // Aguarda 2ms para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/***************************************************************************/
/* Final das rotinas para o LCD */
/***************************************************************************/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do PIC *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
main()
{
// Reseta portas
porta = 0;
portb = 0;
// configura os tris
set_tris_a(0b00111111); // configuração da direção dos pinos de I/O
set_tris_b(0b11000000);
// Inicializa o LCD
inicializa_lcd();
//Escreve tela
escreve_lcd("O");
escreve_lcd("l");
escreve_lcd("a");
escreve_lcd(" ");
escreve_lcd("M");
escreve_lcd("u");
escreve_lcd("n");
escreve_lcd("d");
escreve_lcd("o");
escreve_lcd("!");
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
Tutorial LCD em 4 vias 53
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como não há outra execução, a rotina principal fica vazia
while (true)
{
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
}
Repare que neste programa exemplo, o uso de memória foi ROM=15% e RAM=3% -
6%. Esta observação é importante para que possamos comparar com os outros exercícios.
Início
Define Microcontrolador
Configura o PIC:
Reseta PORTs
Configura TRIS
Inicializa o LCD
Escreve na tela
Final
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Segundo teste de LCD em 4 vias - Olá Mundo utilizando a função PRINTF()
//
//
//
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição do PIC utilizado *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <16f877a.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#fuses XT,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP,NOCPD,NOWRT
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use delay(clock=4000000)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Estas são as definições dos pinos que o LCD utiliza.
// Definem quais pinos do PIC controlarão os pinos do LCD
#define lcd_enable pin_e1 // pino enable do LCD
#define lcd_rs pin_e0 // pino rs do LCD
#define lcd_db4 pin_d4 // pino de dados d4 do LCD
#define lcd_db5 pin_d5 // pino de dados d5 do LCD
#define lcd_db6 pin_d6 // pino de dados d6 do LCD
#define lcd_db7 pin_d7 // pino de dados d7 do LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a) // Inicialização rápida dos Pinos de I/O
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
/***************************************************************************/
/* Rotinas para o LCD */
/***************************************************************************/
//Este é o bloco com as rotinas necessárias para manipular o LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de "Nibble" para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina lê o "Nibble" inferior de uma variável e envia para o LCD.
void envia_nibble_lcd(int dado)
{
//Carrega as vias de dados (pinos) do LCD de acordo com o nibble lido
output_bit(lcd_db4, bit_test(dado,0)); //Carrega DB4 do LCD com o bit DADO<0>
output_bit(lcd_db5, bit_test(dado,1)); //Carrega DB5 do LCD com o bit DADO<1>
output_bit(lcd_db6, bit_test(dado,2)); //Carrega DB6 do LCD com o bit DADO<2>
output_bit(lcd_db7, bit_test(dado,3)); //Carrega DB7 do LCD com o bit DADO<3>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de Byte para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina irá enviar um dado ou um comando para o LCD conforme abaixo:
// ENDEREÇO = 0 -> a variável DADO será uma instrução
// ENDEREÇO = 1 -> a variável DADO será um caractere
void envia_byte_lcd(boolean endereco, int dado)
{
output_bit(lcd_rs,endereco); // Seta o bit RS para instrução ou caractere
delay_us(100); // Aguarda 100 us para estabilizar o pino do LCD
output_low(lcd_enable); // Desativa a linha ENABLE
envia_nibble_lcd(dado>>4); // Envia a parte ALTA do dado/coamndo
envia_nibble_lcd(dado & 0x0f);// Limpa a parte ALTA e envia a parte BAIXA do
// dado/comando
delay_us(40); // Aguarda 40us para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
void escreve_lcd(char c)
// envia caractere para o display
{
envia_byte_lcd(1,c);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como esta operação pode ser muito utilizada, transformando-a em função
// faz cvom que o código compilado seja menor.
void limpa_lcd()
Tutorial LCD em 4 vias 60
{
envia_byte_lcd(0,0x01); // Envia instrução para limpar o LCD
delay_ms(2); // Aguarda 2ms para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Inicializa o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void inicializa_lcd()
{
output_low(lcd_db4); // Garante que o pino DB4 estão em 0 (low)
output_low(lcd_db5); // Garante que o pino DB5 estão em 0 (low)
output_low(lcd_db6); // Garante que o pino DB6 estão em 0 (low)
output_low(lcd_db7); // Garante que o pino DB7 estão em 0 (low)
output_low(lcd_rs); // Garante que o pino RS estão em 0 (low)
output_low(lcd_enable);// Garante que o pino ENABLE estão em 0 (low)
delay_ms(15); // Aguarda 15ms para estabilizar o LCD
/***************************************************************************/
/* Final das rotinas para o LCD */
/***************************************************************************/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Pic *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
main()
{
// Configura o PIC
setup_adc_ports(no_analogs);
// Reseta portas
porta = 0;
portb = 0;
portc = 0;
portd = 0;
porte = 0;
// configura os tris
set_tris_a(0b00111111); // configuração da direção dos pinos de I/O
set_tris_b(0b11111111);
set_tris_c(0b11111111);
set_tris_d(0b00001111);
set_tris_e(0b11111100);
// Inicializa o LCD
inicializa_lcd();
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como não há outra execução, a rotina principal fica vazia
while (true)
{
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
}
Início
Define Microcontrolador
Configura o PIC:
Reseta PORTs
Configura TRIS
Inicializa o LCD
Escreve na tela
Final
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Segundo teste de LCD em 4 vias - Olá Mundo utilizando a função PRINTF()
//
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição do PIC utilizado *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <16f628a.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#fuses INTRC,NOWDT,PUT,MCLR,NOBROWNOUT,NOLVP
#ROM 0x07ff = {0} //Calibragem do oscilador interno
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use delay(clock=4000000)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Estas são as definições dos pinos que o LCD utiliza.
// Definem quais pinos do PIC controlarão os pinos do LCD
#define lcd_enable pin_b5 // pino enable do LCD
#define lcd_rs pin_b4 // pino rs do LCD
#define lcd_db4 pin_b0 // pino de dados d4 do LCD
#define lcd_db5 pin_b1 // pino de dados d5 do LCD
#define lcd_db6 pin_b2 // pino de dados d6 do LCD
#define lcd_db7 pin_b3 // pino de dados d7 do LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a) // Inicialização rápida dos Pinos de I/O
#use fast_io(b)
/***************************************************************************/
/* Rotinas para o LCD */
/***************************************************************************/
//Este é o bloco com as rotinas necessárias para manipular o LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de "Nibble" para o LCD *
Tutorial LCD em 4 vias 64
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina lê o "Nibble" inferior de uma variável e envia para o LCD.
void envia_nibble_lcd(int dado)
{
//Carrega as vias de dados (pinos) do LCD de acordo com o nibble lido
output_bit(lcd_db4, bit_test(dado,0)); //Carrega DB4 do LCD com o bit DADO<0>
output_bit(lcd_db5, bit_test(dado,1)); //Carrega DB5 do LCD com o bit DADO<1>
output_bit(lcd_db6, bit_test(dado,2)); //Carrega DB6 do LCD com o bit DADO<2>
output_bit(lcd_db7, bit_test(dado,3)); //Carrega DB7 do LCD com o bit DADO<3>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de Byte para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina irá enviar um dado ou um comando para o LCD conforme abaixo:
// ENDEREÇO = 0 -> a variável DADO será uma instrução
// ENDEREÇO = 1 -> a variável DADO será um caractere
void envia_byte_lcd(boolean endereco, int dado)
{
output_bit(lcd_rs,endereco); // Seta o bit RS para instrução ou caractere
delay_us(100); // Aguarda 100 us para estabilizar o pino do LCD
output_low(lcd_enable); // Desativa a linha ENABLE
envia_nibble_lcd(dado>>4); // Envia a parte ALTA do dado/comando
envia_nibble_lcd(dado & 0x0f);// Limpa a parte ALTA e envia a parte BAIXA do
// dado/comando
delay_us(40); // Aguarda 40us para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de caractere para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina serve apenas como uma forma mais fácil de escrever um caractere
// no display. Ela pode ser eliminada e ao invés dela usaremos diretamente a
// função envia_byte_lcd(1,"<caractere a ser mostrado no LCD>"); ou
// envia_byte_lcd(1,<código do caractere a ser mostrado no LCD>);
void escreve_lcd(char c)
// envia caractere para o display
{
envia_byte_lcd(1,c);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como esta operação pode ser muito utilizada, transformando-a em função
// faz com que o código compilado seja menor.
void limpa_lcd()
{
envia_byte_lcd(0,0x01); // Envia instrução para limpar o LCD
delay_ms(2); // Aguarda 2ms para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Inicializa o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void inicializa_lcd()
Tutorial LCD em 4 vias 65
{
output_low(lcd_db4); // Garante que o pino DB4 estão em 0 (low)
output_low(lcd_db5); // Garante que o pino DB5 estão em 0 (low)
output_low(lcd_db6); // Garante que o pino DB6 estão em 0 (low)
output_low(lcd_db7); // Garante que o pino DB7 estão em 0 (low)
output_low(lcd_rs); // Garante que o pino RS estão em 0 (low)
output_low(lcd_enable); // Garante que o pino ENABLE estão em 0 (low)
delay_ms(15); // Aguarda 15ms para estabilizar o LCD
/***************************************************************************/
/* Final das rotinas para o LCD */
/***************************************************************************/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do PIC *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
main()
{
// Reseta portas
porta = 0;
portb = 0;
// configura os tris
set_tris_a(0b00111111); // configuração da direção dos pinos de I/O
set_tris_b(0b11000000);
// Inicializa o LCD
inicializa_lcd();
//Escreve tela
printf(escreve_lcd,"Ola Mundo!");
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como não há outra execução, a rotina principal fica vazia
while (true)
{
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Neste exercício, o display será deslocado para a esquerda e, ao final
// da mensagem ele será deslocado para a direita, criando um efeito de
// vai-e-vem. Serão utilizadas as duas linhas do LCD para ter uma melhor
// visualização.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição do PIC utilizado *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <16f877a.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#fuses XT,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP,NOCPD,NOWRT
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use delay(clock=4000000)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Estas são as definições dos pinos que o LCD utiliza.
#define lcd_enable pin_e1 // pino enable do LCD
#define lcd_rs pin_e0 // pino rs do LCD
#define lcd_db4 pin_d4 // pino de dados d4 do LCD
#define lcd_db5 pin_d5 // pino de dados d5 do LCD
#define lcd_db6 pin_d6 // pino de dados d6 do LCD
#define lcd_db7 pin_d7 // pino de dados d7 do LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a) // Inicialização rápida dos Pinos de I/O
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de Byte para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina irá enviar um dado ou um comando para o LCD conforme abaixo:
// ENDEREÇO = 0 -> a variável DADO será uma instrução
// ENDEREÇO = 1 -> a variável DADO será um caractere
void envia_byte_lcd(boolean endereco, int dado)
{
output_bit(lcd_rs,endereco); // Seta o bit RS para instrução ou caractere
delay_us(100); // Aguarda 100 us para estabilizar o pino do LCD
output_low(lcd_enable); // Desativa a linha ENABLE
envia_nibble_lcd(dado>>4); // Envia a parte ALTA do dado/coamndo
envia_nibble_lcd(dado & 0x0f);// Limpa a parte ALTA e envia a parte BAIXA do
// dado/comando
delay_us(40); // Aguarda 40us para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de caractere para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina serve apenas como uma forma mais fácil de escrever um caractere
// no display. Ela pode ser eliminada e ao invés dela usaremos diretamente a
// função envia_byte_lcd(1,"<caractere a ser mostrado no lcd>"); ou
// envia_byte_lcd(1,<código do caractere a ser mostrado no lcd>);
void escreve_lcd(char c)
// envia caractere para o display
{
envia_byte_lcd(1,c);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como esta operação pode ser muito utilizada, transformando-a em função
// faz cvom que o código compilado seja menor.
void limpa_lcd()
{
envia_byte_lcd(0,0x01); // Envia instrução para limpar o LCD
delay_ms(2); // Aguarda 2ms para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
Tutorial LCD em 4 vias 73
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Inicializa o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void inicializa_lcd()
{
output_low(lcd_db4); // Garante que o pino DB4 estão em 0 (low)
output_low(lcd_db5); // Garante que o pino DB5 estão em 0 (low)
output_low(lcd_db6); // Garante que o pino DB6 estão em 0 (low)
output_low(lcd_db7); // Garante que o pino DB7 estão em 0 (low)
output_low(lcd_rs); // Garante que o pino RS estão em 0 (low)
output_low(lcd_enable);// Garante que o pino ENABLE estão em 0 (low)
delay_ms(15); // Aguarda 15ms para estabilizar o LCD
envia_nibble_lcd(0x03);// Envia comando para inicializar o display
delay_ms(5); // Aguarda 5ms para estabilizar o LCD
envia_nibble_lcd(0x03);// Envia comando para inicializar o display
delay_ms(5); // Aguarda 5ms para estabilizar o LCD
envia_nibble_lcd(0x03);// Envia comando para inicializar o display
delay_ms(5); // Aguarda 5ms para estabilizar o LCD
envia_nibble_lcd(0x02);// CURSOR HOME - Envia comando para zerar o contador de
// caracteres e retornar à posição inicial (0x80).
delay_ms(1); // Aguarda 1ms para estabilizar o LCD
envia_byte_lcd(0,0x28);// FUNCTION SET - Configura o LCD para 4 bits,
// 2 linhas, fonte 5X7.
envia_byte_lcd(0,0x0c);// DISPLAY CONTROL - Display ligado, sem cursor
limpa_lcd(); // Limpa o LCD
envia_byte_lcd(0,0x06);// ENTRY MODE SET - Desloca o cursor para a direita
return; // Retorna ao ponto de chamada da função
}
/***************************************************************************/
/* Final das rotinas para o LCD */
/***************************************************************************/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Pic *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
main()
{
// Configura o PIC
setup_adc_ports(no_analogs);
// Reseta portas
porta = 0;
portb = 0;
portc = 0;
portd = 0;
porte = 0;
// configura os tris
set_tris_a(0b00111111); // configuração da direção dos pinos de I/O
set_tris_b(0b11111111);
set_tris_c(0b11111111);
set_tris_d(0b00001111);
set_tris_e(0b11111100);
// Inicializa o LCD
inicializa_lcd();
//Escreve tela
printf(escreve_lcd,"Teste 1-linha com mais de 16 caracteres");
envia_byte_lcd(0,0xc0); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"Teste 2-linha comum, + de 16 caracteres");
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina é a responsável pelo movimento de vai-e-vem do display.
// Ela fica em loop infinito.;
while (true)
Tutorial LCD em 4 vias 74
{
int i;
//Desloca os caracteres do LCD para a esquerda
for(i=0;i<=22;i++)
{
envia_byte_lcd(0,0x18); //0x18 = 0b00011000
delay_ms(250);
}
//Desloca os caracteres do LCD para a direita
for(i=0;i<=22;i++)
{
envia_byte_lcd(0,0x1c); //0x1c = 0b00011100
delay_ms(250);
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Neste exercício, o display será deslocado para a esquerda e, ao final
// da mensagem ele será deslocado para a direita, criando um efeito de
// vai-e-vem. Serão utilizadas as duas linhas do LCD para ter uma melhor
// visualização.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição do PIC utilizado *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <16f628a.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#fuses INTRC,NOWDT,PUT,MCLR,NOBROWNOUT,NOLVP
#ROM 0x07ff = {0} //Calibragem do oscilador interno
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use delay(clock=4000000)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Estas são as definições dos pinos que o LCD utiliza.
// Definem quais pinos do PIC controlarão os pinos do LCD
#define lcd_enable pin_b5 // pino enable do LCD
#define lcd_rs pin_b4 // pino rs do LCD
#define lcd_db4 pin_b0 // pino de dados d4 do LCD
#define lcd_db5 pin_b1 // pino de dados d5 do LCD
#define lcd_db6 pin_b2 // pino de dados d6 do LCD
#define lcd_db7 pin_b3 // pino de dados d7 do LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a) // Inicialização rápida dos Pinos de I/O
#use fast_io(b)
/***************************************************************************/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de "Nibble" para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina lê o "Nibble" inferior de uma variável e envia para o LCD.
void envia_nibble_lcd(int dado)
{
//Carrega as vias de dados (pinos) do LCD de acordo com o nibble lido
output_bit(lcd_db4, bit_test(dado,0)); //Carrega DB4 do LCD com o bit DADO<0>
output_bit(lcd_db5, bit_test(dado,1)); //Carrega DB5 do LCD com o bit DADO<1>
output_bit(lcd_db6, bit_test(dado,2)); //Carrega DB6 do LCD com o bit DADO<2>
output_bit(lcd_db7, bit_test(dado,3)); //Carrega DB7 do LCD com o bit DADO<3>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de Byte para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina irá enviar um dado ou um comando para o LCD conforme abaixo:
// ENDEREÇO = 0 -> a variável DADO será uma instrução
// ENDEREÇO = 1 -> a variável DADO será um caractere
void envia_byte_lcd(boolean endereco, int dado)
{
output_bit(lcd_rs,endereco); // Seta o bit RS para instrução ou caractere
delay_us(100); // Aguarda 100 us para estabilizar o pino do LCD
output_low(lcd_enable); // Desativa a linha ENABLE
envia_nibble_lcd(dado>>4); // Envia a parte ALTA do dado/comando
envia_nibble_lcd(dado & 0x0f);// Limpa a parte ALTA e envia a parte BAIXA do
// dado/comando
delay_us(40); // Aguarda 40us para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de caractere para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina serve apenas como uma forma mais fácil de escrever um caractere
// no display. Ela pode ser eliminada e ao invés dela usaremos diretamente a
// função envia_byte_lcd(1,"<caractere a ser mostrado no LCD>"); ou
// envia_byte_lcd(1,<código do caractere a ser mostrado no LCD>);
void escreve_lcd(char c)
// envia caractere para o display
{
envia_byte_lcd(1,c);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como esta operação pode ser muito utilizada, transformando-a em função
// faz com que o código compilado seja menor.
void limpa_lcd()
{
envia_byte_lcd(0,0x01); // Envia instrução para limpar o LCD
delay_ms(2); // Aguarda 2ms para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
Tutorial LCD em 4 vias 77
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Inicializa o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void inicializa_lcd()
{
output_low(lcd_db4); // Garante que o pino DB4 estão em 0 (low)
output_low(lcd_db5); // Garante que o pino DB5 estão em 0 (low)
output_low(lcd_db6); // Garante que o pino DB6 estão em 0 (low)
output_low(lcd_db7); // Garante que o pino DB7 estão em 0 (low)
output_low(lcd_rs); // Garante que o pino RS estão em 0 (low)
output_low(lcd_enable); // Garante que o pino ENABLE estão em 0 (low)
delay_ms(15); // Aguarda 15ms para estabilizar o LCD
/***************************************************************************/
/* Final das rotinas para o LCD */
/***************************************************************************/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do PIC *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
main()
{
// Reseta portas
porta = 0;
portb = 0;
// configura os tris
set_tris_a(0b00111111); // configuração da direção dos pinos de I/O
set_tris_b(0b11000000);
// Inicializa o LCD
inicializa_lcd();
//Escreve tela
printf(escreve_lcd,"Teste 1-linha com mais de 16 caracteres");
envia_byte_lcd(0,0xc0); //Desloca o cursor para a segunda linha do LCD
printf(escreve_lcd,"Teste 2-linha comum, + de 16 caracteres");
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina é a responsável pelo movimento de vai-e-vem do display.
// Ela fica em loop infinito.;
while (true)
{
int i;
//Desloca os caracteres do LCD para a esquerda
Tutorial LCD em 4 vias 78
for(i=0;i<=22;i++)
{
envia_byte_lcd(0,0x18); //0x18 = 0b00011000
delay_ms(250);
}
//Desloca os caracteres do LCD para a direita
for(i=0;i<=22;i++)
{
envia_byte_lcd(0,0x1c); //0x1c = 0b00011100
delay_ms(250);
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
}
Faça um teste... Comentes as linhas que direcionam os caracteres do LCD para a direita
e veja o que acontece...
Início cria_cgram();
Fim Retorna
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tutorial LCD em 4 vias *
* Para uso na placa de testes *
* *
* Exercício 4 - Criando caracteres na CGRAM *
* *
* Criado por Eduardo de Souza Ramos *
* *
* Memory usage: ROM=7% RAM=3% - 6% *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* VERSÃO : 1.0 *
* DATA : 31/08/2005 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Neste exercício, criaremos 8 caracteres especiais (desenhos) na CGRAM
// para utilizarmos em qualquer ponto do LCD
// A priori eles serão exibidos nas 8 primeiras posições da primeira
// linha do LCD. Maseles poderão ser utilizados em qualquer ponto.
// Como estes caracteres ficam na CGRAM, são voláteis, ou seja, ao
// desligarmos o módulo e o ligarmos novamente, precisarmos reintroduzir
// o código para a criação de caracteres.
// Reparem que, apesar de termos 16 posições disponíveis na CGRAM,
// somente poderemos criar 8 caracteres. As 8 posições adjacentes (posições
// 0x08 a 0x0f) são espelho da primeira (0x00 a 0x07)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição do PIC utilizado *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <16f877a.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#fuses XT,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP,NOCPD,NOWRT
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use delay(clock=4000000)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Estas são as definições dos pinos que o LCD utiliza.
// Definem quais pinos do PIC controlarão os pinos do LCD
#define lcd_enable pin_e1 // pino enable do LCD
#define lcd_rs pin_e0 // pino rs do LCD
#define lcd_db4 pin_d4 // pino de dados d4 do LCD
#define lcd_db5 pin_d5 // pino de dados d5 do LCD
#define lcd_db6 pin_d6 // pino de dados d6 do LCD
#define lcd_db7 pin_d7 // pino de dados d7 do LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/***************************************************************************/
/* Rotinas para o LCD */
/***************************************************************************/
//Este é o bloco com as rotinas necessárias para manipular o LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de "Nibble" para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina lê o "Nibble" inferior de uma variável e envia para o LCD.
void envia_nibble_lcd(int dado)
{
//Carrega as vias de dados (pinos) do LCD de acordo com o nibble lido
output_bit(lcd_db4, bit_test(dado,0)); //Carrega DB4 do LCD com o bit DADO<0>
output_bit(lcd_db5, bit_test(dado,1)); //Carrega DB5 do LCD com o bit DADO<1>
output_bit(lcd_db6, bit_test(dado,2)); //Carrega DB6 do LCD com o bit DADO<2>
output_bit(lcd_db7, bit_test(dado,3)); //Carrega DB7 do LCD com o bit DADO<3>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de Byte para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina irá enviar um dado ou um comando para o LCD conforme abaixo:
// ENDEREÇO = 0 -> a variável DADO será uma instrução
// ENDEREÇO = 1 -> a variável DADO será um caractere
void envia_byte_lcd(boolean endereco, int dado)
{
output_bit(lcd_rs,endereco); // Seta o bit RS para instrução ou caractere
delay_us(100); // Aguarda 100 us para estabilizar o pino do LCD
output_low(lcd_enable); // Desativa a linha ENABLE
envia_nibble_lcd(dado>>4); // Envia a parte ALTA do dado/coamndo
envia_nibble_lcd(dado & 0x0f);// Limpa a parte ALTA e envia a parte BAIXA do
// dado/comando
delay_us(40); // Aguarda 40us para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de caractere para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina serve apenas como uma forma mais fácil de escrever um caractere
// no display. Ela pode ser eliminada e ao invés dela usaremos diretamente a
// função envia_byte_lcd(1,"<caractere a ser mostrado no lcd>"); ou
// envia_byte_lcd(1,<código do caractere a ser mostrado no lcd>);
void escreve_lcd(char c)
// envia caractere para o display
{
Tutorial LCD em 4 vias 85
envia_byte_lcd(1,c);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como esta operação pode ser muito utilizada, transformando-a em função
// faz cvom que o código compilado seja menor.
void limpa_lcd()
{
envia_byte_lcd(0,0x01); // Envia instrução para limpar o LCD
delay_ms(2); // Aguarda 2ms para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Inicializa o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void inicializa_lcd()
{
output_low(lcd_db4); // Garante que o pino DB4 estão em 0 (low)
output_low(lcd_db5); // Garante que o pino DB5 estão em 0 (low)
output_low(lcd_db6); // Garante que o pino DB6 estão em 0 (low)
output_low(lcd_db7); // Garante que o pino DB7 estão em 0 (low)
output_low(lcd_rs); // Garante que o pino RS estão em 0 (low)
output_low(lcd_enable); // Garante que o pino ENABLE estão em 0 (low)
delay_ms(15); // Aguarda 15ms para estabilizar o LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Cria caracteres na CG RAM *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cria_cgram()
{
envia_byte_lcd(0,0b01000000); // Vai para primeira posição da CGRAM
limpa_lcd();
/***************************************************************************/
Tutorial LCD em 4 vias 87
/* Final das rotinas para o LCD */
/***************************************************************************/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Pic *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
main()
{
// Configura o PIC
setup_adc_ports(no_analogs);
// Reseta portas
porta = 0;
portb = 0;
portc = 0;
portd = 0;
porte = 0;
// configura os tris
set_tris_a(0b00111111); // configuração da direção dos pinos de I/O
set_tris_b(0b11111111);
set_tris_c(0b11111111);
set_tris_d(0b00001111);
set_tris_e(0b11111100);
// Inicializa o LCD
inicializa_lcd();
//Escreve tela
limpa_lcd();
cria_cgram();
envia_byte_lcd(0,0xc0);
escreve_lcd(0b00001000);
escreve_lcd(0b00001001);
escreve_lcd(0b00001010);
escreve_lcd(0b00001011);
escreve_lcd(0b00001100);
escreve_lcd(0b00001101);
escreve_lcd(0b00001110);
escreve_lcd(0b00001111);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//
while (true)
{
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
}
Tutorial LCD em 4 vias 88
Placa de testes
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Neste exercício, criaremos 8 caracteres especiais (desenhos) na CGRAM
// para utilizarmos em qualquer ponto do LCD
// A priori eles serão exibidos nas 8 primeiras posições da primeira
// linha do LCD. Mas eles poderão ser utilizados em qualquer ponto.
// Como estes caracteres ficam na CGRAM, são voláteis, ou seja, ao
// desligarmos o módulo e o ligarmos novamente, precisarmos reintroduzir
// o código para a criação de caracteres.
// Reparem que, apesar de termos 16 posições disponíveis na CGRAM,
// somente poderemos criar 8 caracteres. As 8 posições adjacentes (posições
// 0x08 a 0x0f) são espelho da primeira (0x00 a 0x07)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição do PIC utilizado *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <16f628a.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#fuses INTRC,NOWDT,PUT,MCLR,NOBROWNOUT,NOLVP
#ROM 0x07ff = {0} //Calibragem do oscilador interno
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use delay(clock=4000000)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Estas são as definições dos pinos que o LCD utiliza.
// Definem quais pinos do PIC controlarão os pinos do LCD
#define lcd_enable pin_b5 // pino enable do LCD
#define lcd_rs pin_b4 // pino rs do LCD
#define lcd_db4 pin_b0 // pino de dados d4 do LCD
#define lcd_db5 pin_b1 // pino de dados d5 do LCD
#define lcd_db6 pin_b2 // pino de dados d6 do LCD
#define lcd_db7 pin_b3 // pino de dados d7 do LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a) // Inicialização rápida dos Pinos de I/O
/***************************************************************************/
/* Rotinas para o LCD */
/***************************************************************************/
//Este é o bloco com as rotinas necessárias para manipular o LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de "Nibble" para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina lê o "Nibble" inferior de uma variável e envia para o LCD.
void envia_nibble_lcd(int dado)
{
//Carrega as vias de dados (pinos) do LCD de acordo com o nibble lido
output_bit(lcd_db4, bit_test(dado,0)); //Carrega DB4 do LCD com o bit DADO<0>
output_bit(lcd_db5, bit_test(dado,1)); //Carrega DB5 do LCD com o bit DADO<1>
output_bit(lcd_db6, bit_test(dado,2)); //Carrega DB6 do LCD com o bit DADO<2>
output_bit(lcd_db7, bit_test(dado,3)); //Carrega DB7 do LCD com o bit DADO<3>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de Byte para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina irá enviar um dado ou um comando para o LCD conforme abaixo:
// ENDEREÇO = 0 -> a variável DADO será uma instrução
// ENDEREÇO = 1 -> a variável DADO será um caractere
void envia_byte_lcd(boolean endereco, int dado)
{
output_bit(lcd_rs,endereco); // Seta o bit RS para instrução ou caractere
delay_us(100); // Aguarda 100 us para estabilizar o pino do LCD
output_low(lcd_enable); // Desativa a linha ENABLE
envia_nibble_lcd(dado>>4); // Envia a parte ALTA do dado/comando
envia_nibble_lcd(dado & 0x0f);// Limpa a parte ALTA e envia a parte BAIXA do
// dado/comando
delay_us(40); // Aguarda 40us para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de caractere para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina serve apenas como uma forma mais fácil de escrever um caractere
// no display. Ela pode ser eliminada e ao invés dela usaremos diretamente a
// função envia_byte_lcd(1,"<caractere a ser mostrado no LCD>"); ou
// envia_byte_lcd(1,<código do caractere a ser mostrado no LCD>);
void escreve_lcd(char c)
// envia caractere para o display
{
envia_byte_lcd(1,c);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como esta operação pode ser muito utilizada, transformando-a em função
Tutorial LCD em 4 vias 90
// faz com que o código compilado seja menor.
void limpa_lcd()
{
envia_byte_lcd(0,0x01); // Envia instrução para limpar o LCD
delay_ms(2); // Aguarda 2ms para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Inicializa o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void inicializa_lcd()
{
output_low(lcd_db4); // Garante que o pino DB4 estão em 0 (low)
output_low(lcd_db5); // Garante que o pino DB5 estão em 0 (low)
output_low(lcd_db6); // Garante que o pino DB6 estão em 0 (low)
output_low(lcd_db7); // Garante que o pino DB7 estão em 0 (low)
output_low(lcd_rs); // Garante que o pino RS estão em 0 (low)
output_low(lcd_enable); // Garante que o pino ENABLE estão em 0 (low)
delay_ms(15); // Aguarda 15ms para estabilizar o LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Cria caracteres na CG RAM *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cria_cgram()
{
envia_byte_lcd(0,0b01000000); // Vai para primeira posição da CGRAM
limpa_lcd();
/***************************************************************************/
/* Final das rotinas para o LCD */
/***************************************************************************/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do PIC *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
main()
Tutorial LCD em 4 vias 92
{
// Reseta portas
porta = 0;
portb = 0;
// configura os tris
set_tris_a(0b00111111); // configuração da direção dos pinos de I/O
set_tris_b(0b11000000);
// Inicializa o LCD
inicializa_lcd();
//Escreve tela
limpa_lcd();
cria_cgram();
//envia_byte_lcd(0,0x80);
escreve_lcd(0b00000000);
escreve_lcd(0b00000001);
escreve_lcd(0b00000010);
escreve_lcd(0b00000011);
escreve_lcd(0b00000100);
escreve_lcd(0b00000101);
escreve_lcd(0b00000110);
escreve_lcd(0b00000111);
envia_byte_lcd(0,0xc0);
escreve_lcd(0b00001000);
escreve_lcd(0b00001001);
escreve_lcd(0b00001010);
escreve_lcd(0b00001011);
escreve_lcd(0b00001100);
escreve_lcd(0b00001101);
escreve_lcd(0b00001110);
escreve_lcd(0b00001111);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//
while (true)
{
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Pequena animação para exemplificar o uso dos caracteres gerados na CGRAM
// e testar a função de backspace.
// O tempo de animação é controlado pela constante tempo
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição do PIC utilizado *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <16f877a.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#fuses XT,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP,NOCPD,NOWRT
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use delay(clock=4000000)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Estas são as definições dos pinos que o LCD utiliza.
// Definem quais pinos do PIC controlarão os pinos do LCD
#define lcd_enable pin_e1 // pino enable do LCD
#define lcd_rs pin_e0 // pino rs do LCD
#define lcd_db4 pin_d4 // pino de dados d4 do LCD
#define lcd_db5 pin_d5 // pino de dados d5 do LCD
#define lcd_db6 pin_d6 // pino de dados d6 do LCD
#define lcd_db7 pin_d7 // pino de dados d7 do LCD
#define tempo 150
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a) // Inicialização rápida dos Pinos de I/O
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
/***************************************************************************/
/* Rotinas para o LCD */
/***************************************************************************/
//Este é o bloco com as rotinas necessárias para manipular o LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de "Nibble" para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina lê o "Nibble" inferior de uma variável e envia para o LCD.
void envia_nibble_lcd(int dado)
{
//Carrega as vias de dados (pinos) do LCD de acordo com o nibble lido
output_bit(lcd_db4, bit_test(dado,0)); //Carrega DB4 do LCD com o bit DADO<0>
output_bit(lcd_db5, bit_test(dado,1)); //Carrega DB5 do LCD com o bit DADO<1>
output_bit(lcd_db6, bit_test(dado,2)); //Carrega DB6 do LCD com o bit DADO<2>
output_bit(lcd_db7, bit_test(dado,3)); //Carrega DB7 do LCD com o bit DADO<3>
//Gera um pulso de enable
output_high(lcd_enable); // ENABLE = 1
delay_us(1); // Recomendado para estabilizar o LCD
output_low(lcd_enable); // ENABLE = 0
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de Byte para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina irá enviar um dado ou um comando para o LCD conforme abaixo:
// ENDEREÇO = 0 -> a variável DADO será uma instrução
// ENDEREÇO = 1 -> a variável DADO será um caractere
void envia_byte_lcd(boolean endereco, int dado)
{
output_bit(lcd_rs,endereco); // Seta o bit RS para instrução ou caractere
delay_us(100); // Aguarda 100 us para estabilizar o pino do LCD
output_low(lcd_enable); // Desativa a linha ENABLE
envia_nibble_lcd(dado>>4); // Envia a parte ALTA do dado/coamndo
envia_nibble_lcd(dado & 0x0f);// Limpa a parte ALTA e envia a parte BAIXA do
// dado/comando
delay_us(40); // Aguarda 40us para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de caractere para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina serve apenas como uma forma mais fácil de escrever um caractere
// no display. Ela pode ser eliminada e ao invés dela usaremos diretamente a
// função envia_byte_lcd(1,"<caractere a ser mostrado no lcd>"); ou
// envia_byte_lcd(1,<código do caractere a ser mostrado no lcd>);
void escreve_lcd(char c)
// envia caractere para o display
{
envia_byte_lcd(1,c);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como esta operação pode ser muito utilizada, transformando-a em função
// faz cvom que o código compilado seja menor.
void limpa_lcd()
{
envia_byte_lcd(0,0x01); // Envia instrução para limpar o LCD
delay_ms(2); // Aguarda 2ms para estabilizar o LCD
Tutorial LCD em 4 vias 99
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Inicializa o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void inicializa_lcd()
{
output_low(lcd_db4); // Garante que o pino DB4 estão em 0 (low)
output_low(lcd_db5); // Garante que o pino DB5 estão em 0 (low)
output_low(lcd_db6); // Garante que o pino DB6 estão em 0 (low)
output_low(lcd_db7); // Garante que o pino DB7 estão em 0 (low)
output_low(lcd_rs); // Garante que o pino RS estão em 0 (low)
output_low(lcd_enable); // Garante que o pino ENABLE estão em 0 (low)
delay_ms(15); // Aguarda 15ms para estabilizar o LCD
envia_nibble_lcd(0x03); // Envia comando para inicializar o display
delay_ms(5); // Aguarda 5ms para estabilizar o LCD
envia_nibble_lcd(0x03); // Envia comando para inicializar o display
delay_ms(5); // Aguarda 5ms para estabilizar o LCD
envia_nibble_lcd(0x03); // Envia comando para inicializar o display
delay_ms(5); // Aguarda 5ms para estabilizar o LCD
envia_nibble_lcd(0x02); // CURSOR HOME - Envia comando para zerar o contador de
// caracteres e retornar à posição inicial (0x80).
delay_ms(1); // Aguarda 1ms para estabilizar o LCD
envia_byte_lcd(0,0x28); // FUNCTION SET - Configura o LCD para 4 bits,
// 2 linhas, fonte 5X7.
envia_byte_lcd(0,0x0c); // DISPLAY CONTROL - Display ligado, sem cursor
limpa_lcd(); // Limpa o LCD
envia_byte_lcd(0,0x06); // ENTRY MODE SET - Desloca o cursor para a direita
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Cria caracteres na CG RAM *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cria_cgram()
{
//escreve_lcd(0b00000000);
//escreve_lcd(0b00000001);
//escreve_lcd(0b00000010);
//escreve_lcd(0b00000011);
//escreve_lcd(0b00000100);
//escreve_lcd(0b00000101);
//escreve_lcd(0b00000110);
//escreve_lcd(0b00000111);
limpa_lcd();
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Cria uma animação na CG RAM *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void anima_cgram()
{
int i;
for (i=0;i<=15;i++)
{
escreve_lcd(0b00000000);
delay_ms(tempo);
envia_byte_lcd(0,0b00010000); //backspace
escreve_lcd(0b00000001);
delay_ms(tempo);
envia_byte_lcd(0,0b00010000); //backspace
escreve_lcd(0b00000010);
delay_ms(tempo);
envia_byte_lcd(0,0b00010000); //backspace
escreve_lcd(0b00000011);
delay_ms(tempo);
envia_byte_lcd(0,0b00010000); //backspace
escreve_lcd(" ");
}
return;
}
/***************************************************************************/
/* Final das rotinas para o LCD */
/***************************************************************************/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do Pic *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
main()
{
// Configura o PIC
setup_adc_ports(no_analogs);
// Reseta portas
porta = 0;
portb = 0;
portc = 0;
portd = 0;
porte = 0;
// configura os tris
Tutorial LCD em 4 vias 101
set_tris_a(0b00111111); // configuração da direção dos pinos de I/O
set_tris_b(0b11111111);
set_tris_c(0b11111111);
set_tris_d(0b00001111);
set_tris_e(0b11111100);
// Inicializa o LCD
inicializa_lcd();
//Escreve tela
limpa_lcd();
cria_cgram();
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina é a responsável pelo movimento de vai-e-vem do display.
while (true)
{
//Faz uma animação do robozinho
envia_byte_lcd(0,0x80);
anima_cgram();
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Descrição geral *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Pequena animação para exemplificar o uso dos caracteres gerados na CGRAM
// e testar a função de backspace.
// O tempo de animação é controlado pela constante tempo
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição do PIC utilizado *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <16f628a.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações para gravação *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#fuses INTRC,NOWDT,PUT,MCLR,NOBROWNOUT,NOLVP
#ROM 0x07ff = {0} //Calibragem do oscilador interno
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição para uso de Rotinas de Delay *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use delay(clock=4000000)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constantes internas *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Estas são as definições dos pinos que o LCD utiliza.
// Definem quais pinos do PIC controlarão os pinos do LCD
#define lcd_enable pin_b5 // pino enable do LCD
#define lcd_rs pin_b4 // pino rs do LCD
#define lcd_db4 pin_b0 // pino de dados d4 do LCD
#define lcd_db5 pin_b1 // pino de dados d5 do LCD
#define lcd_db6 pin_b2 // pino de dados d6 do LCD
#define lcd_db7 pin_b3 // pino de dados d7 do LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Definição e inicialização dos port's *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#use fast_io(a) // Inicialização rápida dos Pinos de I/O
#use fast_io(b)
/***************************************************************************/
/* Rotinas para o LCD */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de "Nibble" para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina lê o "Nibble" inferior de uma variável e envia para o LCD.
void envia_nibble_lcd(int dado)
{
//Carrega as vias de dados (pinos) do LCD de acordo com o nibble lido
output_bit(lcd_db4, bit_test(dado,0)); //Carrega DB4 do LCD com o bit DADO<0>
output_bit(lcd_db5, bit_test(dado,1)); //Carrega DB5 do LCD com o bit DADO<1>
output_bit(lcd_db6, bit_test(dado,2)); //Carrega DB6 do LCD com o bit DADO<2>
output_bit(lcd_db7, bit_test(dado,3)); //Carrega DB7 do LCD com o bit DADO<3>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de Byte para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Esta rotina irá enviar um dado ou um comando para o LCD conforme abaixo:
// ENDEREÇO = 0 -> a variável DADO será uma instrução
// ENDEREÇO = 1 -> a variável DADO será um caractere
void envia_byte_lcd(boolean endereco, int dado)
{
output_bit(lcd_rs,endereco); // Seta o bit RS para instrução ou caractere
delay_us(100); // Aguarda 100 us para estabilizar o pino do LCD
output_low(lcd_enable); // Desativa a linha ENABLE
envia_nibble_lcd(dado>>4); // Envia a parte ALTA do dado/comando
envia_nibble_lcd(dado & 0x0f);// Limpa a parte ALTA e envia a parte BAIXA do
// dado/comando
delay_us(40); // Aguarda 40us para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Envio de caractere para o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina serve apenas como uma forma mais fácil de escrever um caractere
// no display. Ela pode ser eliminada e ao invés dela usaremos diretamente a
// função envia_byte_lcd(1,"<caractere a ser mostrado no LCD>"); ou
// envia_byte_lcd(1,<código do caractere a ser mostrado no LCD>);
void escreve_lcd(char c)
// envia caractere para o display
{
envia_byte_lcd(1,c);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Função para limpar o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Como esta operação pode ser muito utilizada, transformando-a em função
// faz com que o código compilado seja menor.
void limpa_lcd()
{
envia_byte_lcd(0,0x01); // Envia instrução para limpar o LCD
delay_ms(2); // Aguarda 2ms para estabilizar o LCD
return; // Retorna ao ponto de chamada da função
}
Tutorial LCD em 4 vias 104
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Inicializa o LCD *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void inicializa_lcd()
{
output_low(lcd_db4); // Garante que o pino DB4 estão em 0 (low)
output_low(lcd_db5); // Garante que o pino DB5 estão em 0 (low)
output_low(lcd_db6); // Garante que o pino DB6 estão em 0 (low)
output_low(lcd_db7); // Garante que o pino DB7 estão em 0 (low)
output_low(lcd_rs); // Garante que o pino RS estão em 0 (low)
output_low(lcd_enable); // Garante que o pino ENABLE estão em 0 (low)
delay_ms(15); // Aguarda 15ms para estabilizar o LCD
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Cria caracteres na CG RAM *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cria_cgram()
{
//escreve_lcd(0b00000000);
//escreve_lcd(0b00000001);
//escreve_lcd(0b00000010);
//escreve_lcd(0b00000011);
//escreve_lcd(0b00000100);
//escreve_lcd(0b00000101);
//escreve_lcd(0b00000110);
//escreve_lcd(0b00000111);
limpa_lcd();
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Cria uma animação na CG RAM *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void anima_cgram()
{
int i;
for (i=0;i<=15;i++)
{
escreve_lcd(0b00000000);
delay_ms(tempo);
envia_byte_lcd(0,0b00010000); //backspace
escreve_lcd(0b00000001);
delay_ms(tempo);
envia_byte_lcd(0,0b00010000); //backspace
escreve_lcd(0b00000010);
delay_ms(tempo);
envia_byte_lcd(0,0b00010000); //backspace
escreve_lcd(0b00000011);
delay_ms(tempo);
envia_byte_lcd(0,0b00010000); //backspace
escreve_lcd(" ");
}
return;
}
/***************************************************************************/
/* Final das rotinas para o LCD */
/***************************************************************************/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Configurações do PIC *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
main()
{
// Reseta portas
porta = 0;
portb = 0;
// configura os tris
set_tris_a(0b00111111); // configuração da direção dos pinos de I/O
set_tris_b(0b11000000);
Tutorial LCD em 4 vias 106
// Inicializa o LCD
inicializa_lcd();
//Escreve tela
limpa_lcd();
cria_cgram();
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Rotina principal *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Esta rotina é a responsável pelo movimento de vai-e-vem do display.
// Ela fica em loop infinito.;
while (true)
{
//Faz uma animação do robozinho
envia_byte_lcd(0,0x80);
anima_cgram();
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Fim do Programa *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
}
01. INTRODUÇÃO
Os módulos LCD são interfaces de saída muito útil em sistemas microprocessados. Estes módulos podem ser gráficos e a caracter.
Os módulos LCD gráficos são encontrados com resuluções de 122x32, 128x64, 240x64 e 240x128 dots pixel, e geralmente estão
disponíveis com 20 pinos para conexão. Os LCD comuns (tipo caracter) são especificados em número de linhas por colunas e são
encontrados nas configurações previstas na Tabela 1.
Os módulos podem ser encontrados com LED backlight (com uma iluminação de fundo) para facilitar as leituras durante a noite.
Neste caso, a alimentação deste led faz-se normalmente pelos pinos 15 e 16 para os módulos comuns e 19 e 20 para os módulos
gráficos, sendo os pinos 15 e 19 para ligação ao anodo e os pinos 16 e 20 para o catodo. A corrente de alimentação deste led varia
de 100 a 200mA, dependendo do modelo.
Estes módulos utilizam um controlador próprio, permitindo sua interligação com com outras placas através de seus pinos, onde
deve ser alimentado o módulo e interligado o barramento de dados e controle do módulo com a placa do usuário. Naturalmente
que além de alimentar e conectar os pinos do módulo com a placa do usuário deverá haver um protocolo de comunicação entre as
partes, que envolve o envio de bytes de instruções e bytes de dados pelo sistema do usuário.
Assim como em um rádio relógio todo módulo LCD permite um ajuste na intensidade da luz emitida ou ajuste
de contraste, isto é possível variando-se a tensão no pino 3. A Figura 1 mostra um circuito típico e
recomendado pela maioria dos fabricantes para efetuar este ajuste. Alguns fabricantes recomenda o uso de um
resistor de 4K7 em série com o potenciômetro de 10K.
A Tabela 2 descreve cada pino do módulo ou do display para conexão deste a outras placas:
1
Display LCD
2
Display LCD
Os módulos LCD são projetados para conectar-se com a maioria das CPU’s disponíveis no mercado, bastando para isso que esta
CPU atenda as temporizações de leitura e escrita de instruções e dados, fornecido pelo fabricante do módulo. A Figura 2 mostra
um exemplo de diagrama de tempos típico requeridos para operação de escrita no módulo LCD, estes tempos variam em função
do clock da CPU do usuário.
A Tabela 3 a seguir mostra a relação entre a freqüência da CPU e a temporização de leitura/escrita da maioria dos módulos LCD.
Em geral, podemos conectar o barramento de dados da CPU ao barramento do módulo, mapeando-o convenientemente na placa
de usuário, e efetuarmos uma operação normal de leitura/escrita sem mais problemas.
Clock da CPU
t AS
(MHz) PW EH
(nS) t H
(nS )
08 MHz 325 650 75
10 MHz 250 500 50
12 MHz 200 400 33,3
16 MHz 138 275 12,5
Tabela 3 - Relação clock da CPU x Temporização do Módulo LCD
A Figura 3 mostra um exemplo de conexão de uma placa baseada nos microcontroladores da linha Intel de 8 bits (8051), ao
módulo LCD. Neste caso como os sinais A0 e A1 estão conectados aos pinos 4 e 5, teremos então 04 (quatro) endereços distintos
para comunicação entre a CPU e o módulo LCD. A Tabela 4 mostra estes endereços.
3
Display LCD
4
Display LCD
O exemplo apresentado na Figura 3 refere-se a conexão do módulo LCD com comunicação/transmissão de 8 bits, mas podemos
conectar o módulo com transmissão a cada 4 bits, conforme é mostrado na Figura 4. Neste caso não utilizamos os pinos 7, 8, 9 e
10. Isto é muito útil quando a CPU do usuário possui poucos pinos de I/O, caso típico da linha de microprocessadores PIC, como
por exemplo o Basic Stamp. Agora surge a dúvida, um mesmo módulo pode conectar-se com 8 ou 4 bits? como isto é possível?
Ocorre que o módulo LCD quando alimentado necessita de algumas instruções de inicialização que identificará qual a forma de
transmissão de dados que será estabelecida entre a CPU e o módulo.
5
Display LCD
A Tabela 5 traz um resumo das instruções mais usadas na comunicação com os módulos LCD.
A Tabela 6 apresenta o conjunto de instruções, levando-se em consideração que a comunicação com o módulo seja com
barramento de 8 bits (fixado durante a inicialização). Para o caso desta comunicação ocorrer com apenas 4 bits (nible), os dados
ou instruções serão enviados por nible. sendo enviado o nible mais significativo primeiro. Por exemplo para limpar o display,
escreve-se o nible 0000 e depois 0001.
6
Display LCD
7
Display LCD
Esta instrução escreve o caracter ASCII 32 que corresponde ao branco ou barra de espaço em todos os endereços da DDRAM
apagando a mensagem que estiver escrita. O cursor retorna ao endereço “zero”, ou seja, à posição mais a esquerda da primeira
linha.
RS R/W B7 B6 B5 B4 B3 B2 B1 B0
CÓDIGO 0 0 0 0 0 0 0 0 1 *
MSB LSB
Faz retornar o cursor para a posição mais a esquerda da primeira linha e faz voltar à posição original mensagens previamente
deslocadas. O conteúdo da DDRAM permanece inalterado.
RS R/W B7 B6 B5 B4 B3 B2 B1 B0
CÓDIGO 0 0 0 0 0 0 0 1 X S
MSB LSB
Esta instrução tem efeito somente durante a leitura ou escrita de dados, portanto, deve ser ativada na inicialização.
§ Estabelece o sentido de deslocamento do cursor (X=0 p/ esquerda, X=1 p/ direita)
§ Estabelece se a mensagem deve ou não ser deslocada com a entrada de um novo caracter
S=1 SIM, S=0 NÃO. Exemplo: X=1 e S=1 => mensagem desloca p/ direita.
RS R/W B7 B6 B5 B4 B3 B2 B1 B0
CÓDIGO 0 0 0 0 0 0 0 D C B
MSB LSB
A mensagem fica aparente quando D=1 e desaparece quando D=0, porém o conteúdo da DDRAM fica inalterado. O cursor fica
aparente quando C=1 e desaparece quando C=0, porém as propriedades de escritas vigentes permanecem inalteradas. O
cursor quando aparente liga a última linha que compõem o caracter, exceto quando B=1, que apresenta em alternância com uma
matriz com todos os pontos negros em intervalos de 0,4 segundos. Quando B=1 e C=0, obteremos a ativação intermitente de uma
matriz completa (todos os pontos da matriz).
RS R/W B7 B6 B5 B4 B3 B2 B1 B0
CÓDIGO 0 0 0 0 0 1 C R * *
MSB LSB
8
Display LCD
Desloca o cursor ou a mensagem sem que para isso tenha que escrever ou ler dados do display. Utilizado para posicionamento dos
dados no display.
C R FUNÇÃO
0 0 Desloca o cursor para a esquerda e decrementa o contador de endereço.
0 1 Desloca o cursor para a direita e incrementa o contador de endereço.
1 0 Desloca a mensagem e o cursor para a esquerda.
1 1 Desloca a mensagem e o cursor para a direita
RS R/W B7 B6 B5 B4 B3 B2 B1 B0
CÓDIGO 0 0 0 0 1 Y N F * *
MSB LSB
Y estabelece o modo de comunicação. Se Y=1 estabelece 8 bits e quando Y=0 será 4 bits, enviados em duas operações, com os 4
bits (Nible) mais significativos sendo enviados primeiro. N fixa o número de linhas: N=0 para uma linha e N=1 para duas ou
mais linhas. F fixa o tipo da matriz: F=0 para matriz 7x5 ou 8x5 e F=1 para matriz 10x5 (somente possível quando apresentando
em uma linha).
CGRAM é uma região da memória RAM destinada para criação de caracteres especiais, como por exemplo: ç, é, Ê, etc.
RS R/W B7 B6 B5 B4 B3 B2 B1 B0
CÓDIGO 0 0 0 1 A A A A A A
MSB LSB
Estabelece o endereço da CGRAM no contador de endereços (AC) como um número binário AAAAAA e após isto os dados serão
escritos ou lidos pela CPU neste endereço. Cada caracter especial ocupa 8 endereços na CGRAM.
RS R/W B7 B6 B5 B4 B3 B2 B1 B0
CÓDIGO 0 0 1 A A A A A A A
MSB LSB
Estabelece o endereço da DDRAM no contador de endereços (AC) como um número binário AAAAAAA e após isto os dados
serão escritos ou lidos pela CPU neste endereço. Para os display de uma linha AAAAAAA varia de 80H a CFH. Já para todos os
display de duas linhas varia de 80H a A7H para a primeira linha e de C0H a E7H para a segunda linha.
RS R/W B7 B6 B5 B4 B3 B2 B1 B0
CÓDIGO 0 1 BF A A A A A A A
MSB LSB
Busy Flag ou o bit 7 indica ao sistema onde está conectado o módulo LCD, se o controlador do módulo está ocupado com alguma
operação interna (BF=1), e neste caso, não aceita nenhuma instrução até que BF volte para 0.
Além disso, permite a leitura do conteúdo do contador de endereços (AC) expressa por AAAAAAA. O contador de endereços
pode conter tanto endereço da CGRAM como da DDRAM, depende neste caso, da instrução anterior.
9
Display LCD
RS R/W B7 B6 B5 B4 B3 B2 B1 B0
CÓDIGO 1 0 A A A A A A A A
MSB LSB
Escreve o byte AAAAAAAA tanto na CGRAM como na DDRAM, dependendo da instrução anterior (que define o endereço).
Após a escrita, o endereço é automaticamente incrementado ou decrementado de uma unidade dependendo do modo escolhido
(ver item 3.1.3).
RS R/W B7 B6 B5 B4 B3 B2 B1 B0
CÓDIGO 1 1 A A A A A A A A
MSB LSB
Faz uma leitura na CGRAM ou na DDRAM, dependendo da instrução anterior (que define o endereço). É importante que
precedendo a esta leitura seja executado a instrução de estabelecimento do endereço da CGRAM ou DDRAM, pois caso contrário
o dado lido é inválido.
Caracter
Módulo 8x1 1 2 3 4 5 6 7 8
Endereço(hexa) 80 81 82 83 84 85 86 87
LCD 16x1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
80 81 82 83 84 85 86 87 88 89 8 8B 8C 8 8E 8F
A D
LCD 16x1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
80 81 82 83 84 85 86 87 C0 C1 C2 C3 C4 C5 C6 C7
LCD 16x2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
linha 1 80 81 82 83 84 85 86 87 88 89 8 8B 8C 8 8E 8F
A D
linha 2 C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 C C C C C C
A B C D E F
10
Display LCD
LCD 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
20x2
linha 1 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93
linha 2 C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3
LCD 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
20x4
linha 1 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93
linha 2 C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3
linha 3 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93
linha 4 C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3
LCD 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
24x1
LCD
24x2
linha 1 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94 95 96 97
linha 2 C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3 D4 D5 D6 D7
LCD 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
40x1
a LCD
40X4
linha 1 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93
linha 2 C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3
linha 3 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93
linha 4 C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3
Cont. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
linha 1 94 95 96 97 98 99 9A 9B 9C 9E 9D 9F A0 A1 A2 A3 A4 A5 A6 A7
linha 2 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF E0 E1 E2 E3 E4 E5 E6 E7
linha 3 94 95 96 97 98 99 9A 9B 9C 9E 9D 9F A0 A1 A2 A3 A4 A5 A6 A7
linha 4 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF E0 E1 E2 E3 E4 E5 E6 E7
OBS:
§ Para os módulos de 04 linhas estamos considerando que existe um outro pino de habilitação (como o pino 6) para as duas
últimas linhas, portando outros endereços de hardware.
§ Antes de enviar uma instrução para escrita de dados no display, enviar antes uma de endereçamento na DDRAM, com o
endereço onde deve ser escrito o caracter, tipo um gotoxy().
11
Display LCD
Os caracteres especiais previamente programado, durante a inicialização, podem ser utilizados a qualquer tempo como se fossem
caracteres normais, lembrando que os endereços bases em hexadecimal para gravação dos caracteres especiais, na maioria dos
módulos LCD, são respectivamente: 40, 48, 50, 58, 60, 68, 70 e 78. Cada caracter especial ocupa 8 (oito) endereços.
50 1 0 x x x 0E
51 1 0 x x 11
52 1 0 x 10
53 1 0 x 10
54 1 0 x x x 15
55 1 0 x x x 0E
56 1 0 x 10
57 1 0 00*
Tabela 7 - Caracter especial {ç} na CGRAM
Isto significa que para utilizarmos o caracter gravado no endereço base 50, durante a inicialização ou reset do sistema, teremos
que escrevermos 8 bytes entre os endereços 50 e 57, para construirmos o caracter. Para ilustrar este procedimento, supor que
queiramos construir o caracter {ç} no endereço base 50. Neste caso, devemos construir o mapa deste caracter especial como
mostrado na Tabela 7 (supondo estar trabalhando com matriz 7x5 e com auto incremento de endereço a cada escrita). Observe
que o último endereço sempre será 00, pois esta posição é sempre ocupada pelo cursor.
12
Display LCD
Entre as quatro primeiras instruções recomendamos um delay de 15 mS. As demais instruções podem ser escritas após checar o
Busy Flag. Estes bits (nible) devem estar conectados aos pinos 11, 12.13 e 14.
13
Display LCD
A seguir passaremos a descrever um resumo dos procedimentos para utilização de um módulo ou display LCD:
1. Ao energizar o módulo ajuste o potenciômetro de controle do brilho ou contraste até obter a visualização da matriciação na
primeira linha para módulo de duas linhas ou até a matriciação de meia linha para módulos de uma linha.
2. Alguns módulos de uma linha só funcionam com a instrução 38 ao invés de 30, conforme instruções de inicialização.
3. O sinal de Enable (pino 6) deverá ser gerado conforme a temporização mostrada na Figura 2. Os códigos de dados ou de
instruções só serão processados pelo processador do módulo após a descida do sinal do Enable.
4. Para ajustar a velocidade de comunicação entre a CPU do usuário e o módulo LCD existem duas possibilidades:
§ Intercalar uma rotina de atraso de aproximadamente 15 mS entre as instruções.
§ Fazer a leitura do Busy Flag antes do envio de cada instrução e só enviar quando o mesmo for 0. Neste caso, a única
exceção será durante a inicialização.
5. Durante a inicialização enviar a seqüência correta das instruções de inicialização conforme item 3.4
7. Após a escrita de dados na CGRAM envie a instrução 01, para posicionar o cursor.
8. Para escrever os caracteres especiais previamente gravados na CGRAM, utilize os códigos de 00 até 07 correspondente aos
endereços bases de 40, 48 até 78 em hexa.
9. Comandos úteis:
14
Display LCD
Obs: Após o endereçamento da CGRAM, o cursor se desloca para a primeira posição da segunda linha (ou metade), portanto é
recomendado enviar a instrução 01 ou “limpa display e cursor home”.
15
Display LCD
5.1 - MANUSEIO
§ Somente retire o módulo de sua embalagem protetora imediatamente antes de sua instalação
§ Não guarde os módulos em recintos de alta temperatura e alta umidade. A temperatura de armazenamento deverá estar
compreendida entre 5 e 30 oC.
§ O LCD é coberto por uma lâmina plástica polarizada a qual não pode ser riscada. Cuidado em seu manuseio. Para a limpeza
da lâmina utilize cotonetes embebido em benzina. Não utilize outros tipos de solventes.
§ Observe cuidadosamente os procedimentos de controle anti-estático quando manusear os módulos. Eles incorporam circuitos
integrados CMOS LSI os quais são sensíveis à descarga eletrostática. Não toque nos terminais do conector, trilhas do circuito
impresso e/ou terminais do CI.
5.2 - INSTALAÇÃO
§ Nunca desmonte o módulo
§ Use uma estação de solda aterrada para soldagem de conectores ou terminais.
§ montador deverá também ser convenientemente aterrado.
§ Sempre que o projeto o permita, instale o módulo atrás de uma janela protetora de plástico ou vidro.
§ Somente retire a fita adesiva que protege a lâmina plástica frontal imediatamente antes de seu uso.
5.3 - OPERAÇÃO
16
Display LCD
Baseado no hardware da Figura 3, eaborar um programa em assembler para o 8031 que escreva no módulo LCD a seguinte
mensagem: “Vila Nova”.
;=======================================================================
; Programa: Exemplo para manuseio de display ou modulo LCD
; Autor: Ilton L. Barbacena
; Data: Out/96
; Compilador: ASM51.EXE / versao shareware para 8051 / $mod51
; versao: 1.0
; Descricao: Este programa grava a mensagem "Vila Nova"
; no display LCD 2x20 (duas linha de 20 caracteres).
; Os pinos de dados do mudulo LCD estao conectados
; diretamente no barramento de dados da CPU, conforme
; Figura 3 da apostila sobre LCD.
;=======================================================================
$mod51
lcd_wr_inst equ 4000H
lcd_wr_dado equ 4001H
lcd_rd_inst equ 4002H
lcd_rd_dado equ 4003H
;========================================================================
; Programa principal
;========================================================================
ORG 0H
MOV SP,#50H
MOV TMOD,#11H ; TIMER1 / TIMER0 no modo 1
CLR EA ; desabilita todas as interrupcoes
CALL inicia_lcd
MOV R7,#0FFH
loop: INC R7
MOV A,R7
MOV DPTR,#mensagem
MOVC A,@A+DPTR ; le caracter da mensagem
CJNE A,#0FFH,cont ; testa se fim da mensagem
JMP fim
17
Display LCD
;=======================================================================
; Rotinas chamadas pelo Programa Principal
;=======================================================================
ORG 100H
18
Display LCD
;=========================================================
; Rotina de tempo: 15 mS / clock 12 MHz => 50.000 ciclos
;=========================================================
tempo:
MOV DPTR,#15536 ; (65536-50000)
MOV TH1,DPH
MOV TL1,DPL
SETB TR1 ; dispara timer1
JNB TF1,$ ; aguarda estouro => 50.0000
CLR TR1
CLR TF1 ; prepara para proxima chamada
RET
Repetir o exercício anterior, porém com a mensagem “Escola Técnica”. Construir o {é} na CGRAM. Lembre-se que apenas os
códigos ascii são caracteres válidos para o LCD (verificar a tabela no manual do fabricante).
19
PIC: Conversor A/D e LCD
OBJETIVOS
• Compreender a operação do conversor A/D do PIC;
• Aprender a utilizar as funções do drive de LCD ;
• Desenvolver uma IHM usando o LCD e o teclado da placa de experimentos;
CONVERSOR A/D
O módulo do conversor A/D possui 8 entradas analógicas, que possuem um capacitor de sample-
and-hold. A saída do sample-and-hold é conectada a entrada do conversor A/D a partir de um
multiplex 8 x 1. O conversor A/D gera uma palavra binária de 10 bits para representar o valor de
tensão na entrada analógica selecionada.
O módulo A/D tem duas entradas de tensão de referência (alta e baixa), que são selecionadas por
software, entre algumas opções de combinação pré-estabelecidas. Uma característica apenas
presente no módulo conversor A/D é que o mesmo pode operar mesmo o PIC estando no modo
SLEEP. Para operar neste modo o sinal de clock do conversor A/D (CAD) deve ser derivado do
oscilador RC interno do PIC.
O conversor A/D possui quatro registradores:
• Registrador do byte mais significado do resultado da conversão (ADRESH);
• Registrador do byte menos significado do resultado da conversão (ADRESL);
• Registrador de controle 0 (ADCON0) e
• Registrador de controle 1.
1
• Sete o bit GO/DONE (ADCON0)
5. Aguarde o tempo de conversão ter transcorrido;
• Realize um POLLING no bit GO/DONE, verificando se o seu valor é zero
(indicativo de fim de conversão A/D);
• ou aguarde pela interrupção gerada pelo módulo A/D ao fim da conversão;
6. Leia o par de registradores (ADRESH:ADRESL), resete o bit ADIF se a interrupção do
conversor A/D está sendo utilizada;
7. Para realizar uma nova conversão retorne ao passo 1 ou 2 (antes de uma nova conversão
ser iniciada, deve ser aguardado um tempo de 2TAD, que é o tempo de conversão por bit,
cujo valor é definido na tabela 1).
O conversor A/D necessita de no mínimo 12 TAD para realizar uma conversão de 10 bits. A fonte
do clock do conversor A/D é selecionada por software entre as possibilidades abaixo:
• 2Tosc
• 8Tosc
• 32Tosc
• Oscilador RC interno
Para uma conversão correta, o clock do conversor A/D deve ser selecionado para garantir um TAD
mínimo de 1.6µs. A tabela 1 mostra os valores de TAD em função da seleção da fonte do clock.
Se o bit GO/DONE for resetado durante uma conversão, esta será abortada. Os registradores de
resultado do módulo A/D não serão atualizados com a parcialmente concluída conversão. Assim,
os registradores ADRESH:ADRESL continuaram armazenando o valor da última conversão
concluída (ou o último valor escrito para os registradores ADRESH:ADRESL). Após uma
conversão ser abortada, um tempo de 2TAD é necessário antes de uma nova conversão ser
iniciada. Após este tempo, a aquisição do canal selecionado é automaticamente iniciada.
O par de registradores ADRESH:ADRESL comporta 16 bits, assim, o valor convertido de 10 bits
pode ser justificado a direita ou à esquerda, de acordo com o bit seleção de formato do conversor
A/D (ADFM), que controla a justificação. Os bits extras não utilizados são carregados com “0”
(zeros). Quando o módulo A/D não estiver sendo utilizado, os registradores ADRESH:ADRESL
podem ser usados como dois registradores de propósito geral de 8 bits.
2
Justificação do resultado da conversão A/D
3
Registrador ADCON0 - Controla a operação do módulo A/D.
4
Registrador ADCON1 – Configura a função dos pinos das portas (A e E)
Os registradores ADCON1 e TRIS controlam a operação dos pinos das portas A/D. Os pinos das
portas que serão entradas analógicas devem ter seus correspondentes bits TRIS setados. Se o bit
está resetado, o nível de tensão da saída digital será convertido. A operação do conversor A/D
independe do estado dos bits CHS2:CHS0 e dos bits TRIS
Observações:
1 – Quando o registrador da porta é lido, qualquer pino configurado como um canal de entrada
analógica será lido como zero (nível baixo). Pinos configurados como entradas digitais irão se
converter em entradas analógicas. Níveis analógicos em uma entrada configurada como digital,
não afetarão a precisão da conversão.
2 – Níveis analógicos em qualquer pino que é definido como uma entrada digital (incluindo os
pinos AN7:AN0) podem fazer com que o buffer de entrada consuma corrente que está fora das
especificações do dispositivo.
5
Registradores associados com o módulo do conversor A/D
/*=====================================================================
=======================================================================
ARQUIVO - DRIVER: LCD_16x2_LIB.C
DATA DE CRIAÇÃO: 03/11/2003
REVISÃO: 1.0
DATA DA ULTIMA REV: 03/12/2004
ULTIMA REV: 1.1
MICROCONTROLADOR: FAMILIA PIC
FUNÇÃO:
=======================================================================
=====================================================================*/
#ifndef CS_LCD