You are on page 1of 8

12/12/2017 Ligando Display LCD 16x2 ao PIC 16F628A - FilipeFlop

Início  Embarcados  Ligando Display LCD 16×2 ao PIC 16F628A

Ligando Display LCD 16×2 ao PIC 16F628A  19

Embarcados 
26 de maio de 2014 
Adilson Thomsen

Para ligarmos um display LCD 16×2 ao PIC, precisamos antes de mais nada saber como programar pic
e  entender  um pouco sobre a forma como esse tipo de display trabalha. Um dos tipos mais comuns de
controlador utilizados em displays LCD é o HD44780, que pode ser ligado ao microcontrolador usando-se 4
ou 8 os, e que vai determinar a velocidade de comunicação entre eles.

Não podemos simplesmente enviar dados à um LCD sem uma sequencia lógica. Antes de utilizá-lo, é
necessário o envio de comandos que preparam o display para receber caracteres. Vamos tomar como
exemplo o display LCD 16×2 com controlador HD44780, disponível aqui na FILIPEFLOP :

Esse tipo de display tem 16 pinos : 3 pinos de alimentação, 3 de controle, 8 de dados e 2 para acionar o
backlight (ou luz de fundo), que você pode ver em detalhes na imagem abaixo :

https://www.filipeflop.com/blog/display-lcd-16x2-pic-16f628a/ 1/8
12/12/2017 Ligando Display LCD 16x2 ao PIC 16F628A - FilipeFlop

Os pinos de controle do display LCD 16×2 são o RS, o R/W e o E.

O pino RS tem a função de mostrar ao display que tipo de dados estamos transmitindo. Em nível baixo (0),
os dados são tratados como comandos, e em nível alto (1), os dados são tratados como caracteres. O pino
R/W (Read/Write) é utilizado para determinar se estamos lendo ou transmitindo dados para o display. Já o
pino ENABLE é utilizado para determinar o início da transferência de dados entre o microcontrolador e o
display.

Os pinos de dados D0 a D7 formam o barramento de dados. O mais comum é utilizarmos apenas 4 pinos
para comunicação com o microcontrolador, mas nada impede que em aplicações mais elaboradas sejam
utilizados todos os 8 pinos. Essa é uma das funções do envio de comandos que preparam o display, pois é
nesse momento que determinamos se vamos usar 4 ou 8 pinos para comunicação.

No Arduino temos várias bibliotecas prontas que fazem todo esse trabalho pesado. No caso do PIC,
podemos agrupar os comandos também em um arquivo texto e criar uma biblioteca própria. Esse é o
método que vamos utilizar nesse post, contando com a ajuda das rotinas de comando do display
disponibilizadas no blog do Marcelo Maciel.

Para controle do display LCD 16×2 vamos utilizar o microcontrolador PIC16F628A, e o programa
desenvolvido para uso no software MPLab. Os detalhes para con guração e utilização do MPLab você
encontra no artigo Programando PIC16F628A para piscar um led, aqui mesmo no blog.

Crie no MPLab a estrutura básica do projeto, e na mesma pasta do projeto crie um arquivo texto com o
nome de lcd.h. Dentro desse arquivo, copie o seguinte código :

1 /***************************************************************************/
2 /* Rotinas para o LCD */
3 /***************************************************************************/
4  
5 //Este é o bloco com as rotinas necessárias para manipular o LCD
6  
7 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8 * Envio de "Nibble" para o LCD *
9 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10  
11 //Esta rotina lê o "Nibble" inferior de uma variável e envia para o LCD.
12 void envia_nibble_lcd(int dado)
13 {
14 //Carrega as vias de dados (pinos) do LCD de acordo com o nibble lido
15 output_bit(lcd_db4, bit_test(dado,0));    //Carrega DB4 do LCD com o bit DADO<0>
16 output_bit(lcd_db5, bit_test(dado,1));    //Carrega DB5 do LCD com o bit DADO<1>
17 output_bit(lcd_db6, bit_test(dado,2));    //Carrega DB6 do LCD com o bit DADO<2>
18 output_bit(lcd_db7, bit_test(dado,3));    //Carrega DB7 do LCD com o bit DADO<3>
19  
20 //Gera um pulso de enable
21 output_high(lcd_enable);      // ENABLE = 1
22 delay_us(1);                  // Recomendado para estabilizar o LCD
23 output_low(lcd_enable);       // ENABLE = 0
24 return;                       // Retorna ao ponto de chamada da função
25 }
26  
27 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
28 * Envio de Byte para o LCD *
29 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
30  
31 //Esta rotina irá enviar um dado ou um comando para o LCD conforme abaixo:
32 // ENDEREÇO = 0 -> a variável DADO será uma instrução
33 // ENDEREÇO = 1 -> a variável DADO será um caractere
34  
35 void envia_byte_lcd(boolean endereco, int dado)
36 {
37 output_bit(lcd_rs,endereco);  // Seta o bit RS para instrução ou caractere
38 delay_us(100);                // Aguarda 100 us para estabilizar o pino do LCD
39 output_low(lcd_enable);       // Desativa a linha ENABLE
40 envia_nibble_lcd(dado>>4);   // Envia a parte ALTA do dado/comando
41 envia_nibble_lcd(dado & 0x0f); // Limpa a parte ALTA e envia a parte BAIXA do
42                                // dado/comando
43 delay_us(40);                  // Aguarda 40us para estabilizar o LCD
44 return;                       // Retorna ao ponto de chamada da função
45 }
46  
47  
48 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
49 * Envio de caractere para o LCD *
50 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
51 // Esta rotina serve apenas como uma forma mais fácil de escrever um caractere
52 // no display. Ela pode ser eliminada e ao invés dela usaremos diretamente a
53 // função envia_byte_lcd(1,"<caractere a ser mostrado no LCD>"); ou
54 // envia_byte_lcd(1,<código do caractere a ser mostrado no LCD>);
55  
56 void escreve_lcd(char c)
57 // envia caractere para o display
58 {
59 envia_byte_lcd(1,c);
60 }
61  
62 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
63 * Função para limpar o LCD *
64 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
65 // Como esta operação pode ser muito utilizada, transformando-a em função
66 // faz com que o código compilado seja menor.
67  
68 void limpa_lcd()
69 {
70 envia_byte_lcd(0,0x01);          // Envia instrução para limpar o LCD
71 delay_ms(2);                     // Aguarda 2ms para estabilizar o LCD
72 return;                          // Retorna ao ponto de chamada da função
73 }
74  
75 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
76 * Inicializa o LCD *
77 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
78  
79 void inicializa_lcd()
80 {
81 output_low(lcd_db4);     // Garante que o pino DB4 estão em 0 (low)
82 output_low(lcd_db5);     // Garante que o pino DB5 estão em 0 (low)
83 output_low(lcd_db6);     // Garante que o pino DB6 estão em 0 (low)
84 output_low(lcd_db7);     // Garante que o pino DB7 estão em 0 (low)

https://www.filipeflop.com/blog/display-lcd-16x2-pic-16f628a/ 2/8
12/12/2017 Ligando Display LCD 16x2 ao PIC 16F628A - FilipeFlop
85 output_low(lcd_rs);      // Garante que o pino RS estão em 0 (low)
86 output_low(lcd_enable);  // Garante que o pino ENABLE estão em 0 (low)
87 delay_ms(15);            // Aguarda 15ms para estabilizar o LCD
88 envia_nibble_lcd(0x03);  // Envia comando para inicializar o display
89 delay_ms(5);             // Aguarda 5ms para estabilizar o LCD
90 envia_nibble_lcd(0x03);  // Envia comando para inicializar o display
91 delay_ms(5);             // Aguarda 5ms para estabilizar o LCD
92 envia_nibble_lcd(0x03);  // Envia comando para inicializar o display
93 delay_ms(5);             // Aguarda 5ms para estabilizar o LCD
94 envia_nibble_lcd(0x02);  // CURSOR HOME - Envia comando para zerar o
95                          //contador de caracteres e retornar à posição
96                          // inicial (0x80).
97 delay_ms(1);             // Aguarda 1ms para estabilizar o LCD
98 envia_byte_lcd(0,0x28);  // FUNCTION SET - Configura o LCD para 4 bits,
99                          // 2 linhas, fonte 5X7.
100 envia_byte_lcd(0,0x0c);  // DISPLAY CONTROL - Display ligado, sem cursor
101 limpa_lcd();             // Limpa o LCD
102 envia_byte_lcd(0,0x06);  // ENTRY MODE SET - Desloca o cursor para a direita
103 return;                  // Retorna ao ponto de chamada da função
104 }
105  
106 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
107 * Define inicio da escrita *
108 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
109 //Esta função foi adicionada e serve para se definir em que posição do
110 //LCD deseja-se iniciar a escrita. Para isto basta chamar a Função
111 //"caracter_Inicio()" indicando a linha e a coluna onde o cursor será
112 // posicionado antes de se mandar escrever
113  
114 void caracter_inicio(int linha, int coluna)//define a posicão de inicio da frase
115 {
116 int16 posicao=0;
117    if(linha == 1)
118    {
119       posicao=0x80;     //Se setado linha 1, end incial 0x80
120    }
121    if(linha == 2)
122    {
123       posicao=0xc0;     //Se setado linha 2, end incial 0xc0
124    }
125  
126 posicao=posicao+coluna;     //soma ao end inicial, o numero da coluna
127 posicao--;                  //subtrai 1 para corrigir posição
128  
129 envia_byte_lcd(0,posicao);
130 return;
131 }
132 /***************************************************************************/
133 /* Final das rotinas para o LCD */
134 /***************************************************************************/

A estrutura da pasta do projeto vai car mais ou menos assim :

No MPLab, coloque o código abaixo, que chama as rotinas contidas no arquivo lcd.h para inicializar o
display, apagar a tela, enviar caracteres, etc. No circuito vamos usar um cristal de 16Mhz, mas você pode
utilizar, por exemplo um de 20Mhz. Para isso, altere a linha com o comando #use delay(clock=16000000) no
início do programa:

#include <16F628A.h> //Define o modelo do microcontrolador

// Fusíveis de configuração do microcontrolador

#FUSES NOWDT //Watch Dog Timer desabilitado


#FUSES HS //oscilador cristal
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //sem proteção para leitura da eprom
#FUSES BROWNOUT //Resetar quando detectar brownout
#FUSES NOMCLR //Reset desabilitado
#FUSES NOLVP //prog. baixa voltagem desabilitado
#FUSES NOCPD //Sem travar o chip

#use delay(clock=16000000) //Define o cristal utilizado

https://www.filipeflop.com/blog/display-lcd-16x2-pic-16f628a/ 3/8
12/12/2017 Ligando Display LCD 16x2 ao PIC 16F628A - FilipeFlop
//Definição de entradas e saídas
//Cada bit representa um pino físico de I/O
// 0 significa que o pino será uma saída
// 1 significa que o pino será uma entrada
#define trisa 0b00000000
#define trisb 0b00000000

// 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_a1 // pino enable do LCD


#define lcd_rs pin_a0 // pino rs (register select)do LCD
// (0) para comandos (1) para dados

#define lcd_db4 pin_b4 // pino de dados d4 do LCD


#define lcd_db5 pin_b5 // pino de dados d5 do LCD
#define lcd_db6 pin_b6 // pino de dados d6 do LCD
#define lcd_db7 pin_b7 // pino de dados d7 do LCD
#include <lcd.h> //declaração da biblioteca do LCD

//Programa principal
void main(){

inicializa_lcd(); //Inicializa o LCD

while(1){
//limpa_lcd(); //Limpa o display do LCD
caracter_inicio(2,6);
printf(escreve_lcd," ");
delay_ms(500);
caracter_inicio(1,4); //Define o caracter de inicio da escrita
printf(escreve_lcd,"FILIPEFLOP"); //Escreve no LCD
delay_ms(2000);

caracter_inicio(1,4);
printf(escreve_lcd," ");
delay_ms(500);
caracter_inicio(2,6);
printf(escreve_lcd,"P I C");
delay_ms(2000);
}
} //fecha void main

Grave o programa utilizando o software MicroBRN, ou outro de sua preferência, e teste o microcontrolador
ligando-o ao display seguindo a tabela e circuito mostrados abaixo :

Além disso, ligue o pino 5 do PIC ao GND e o pino 14 ao 5v. O cristal deve ser ligado aos pinos 15 e 16 do
PIC.

A alimentação do circuito é de 5v e o potenciômetro é de 10 K, utilizado para controle do contraste do


display LCD 16×2. Se necessário, coloque um resistor no pino 15 ou 16 para reduzir a intensidade da luz de
fundo.

Gostou ? Ajude-nos a melhorar o blog atribuindo uma nota aos posts (estrelas no início ou no nal
do artigo) e visite nossa loja FILIPEFLOP !

https://www.filipeflop.com/blog/display-lcd-16x2-pic-16f628a/ 4/8
12/12/2017 Ligando Display LCD 16x2 ao PIC 16F628A - FilipeFlop

Posts Relacionados

3 projetos incríveis Introdução ao Bot Telegram com a Intel Galileo Gen2


com o Display Touch Beaglebone Green Beaglebone Black com nova imagem
Arduino Shield em microSD

Adilson Thomsen

Formado em Ciência da Computação pela Universidade de Mogi das Cruzes, atualmente


responsável pelo departamento técnico da FILIPEFLOP.

← Conectando Acelerômetro 3 Eixos MMA7361 no Relógio com o módulo RTC DS1307  →


Arduino

Deixe uma resposta

Conectar com:

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Comentário

Nome * E-mail *

Site

Publicar comentário

19 Comentários

Ola amigo bom noite. será que teria como você me enviar por e-mail o arquivo deste programa. pois não
consegui fazer.
Estou precisando pois quero fazer um robo e pretendo usar o pic16f628a e um display 16×2.

att: Mateus

mateus 24 de setembro de 2014 Responder

Essa biblioteca possibilita, assim como outras, um comando para mostrar o estado ou o valor de uma
variável? se sim, qual o comando?

Endryl Laureano 5 de outubro de 2014 Responder

https://www.filipeflop.com/blog/display-lcd-16x2-pic-16f628a/ 5/8
12/12/2017 Ligando Display LCD 16x2 ao PIC 16F628A - FilipeFlop

Meus parabéns!
Seus posts são de grande ajuda para muita gente, eu como iniciante em PIC tenho esclarecido
muitas dúvidas com os seus artigos.

Que Deus te dê muita sabedoria e você continue compartilhando conosco.

Gunter Braga 10 de dezembro de 2014 Responder

Valeu Gunter ! Abraço.

Adilson – Equipe FILIPEFLOP

Paulo 5 de janeiro de 2015 Responder

Boa tarde!
Uma dúvida, a segunda parte da programação, eu tenho que colocar logo abaixo da primeira?

Marlon 30 de janeiro de 2015 Responder

Boa noite Marlon,

Não. A primeira parte você coloca em um arquivo texto, o lcd.h. A segunda parte você vai utilizar
dentro do MPLab, para chamar as rotinas que foram inseridas nesse arquivo texto.

Abraço.

Adilson – Equipe FILIPEFLOP

Paulo 3 de fevereiro de 2015 Responder

Ola. Boa tarde


Gentileza informar se Voce grava um PIC para meu projeto. Caso positivo como fazer para enviar.

Mauricio 2 de abril de 2015 Responder

Esta biblioteca serve para qualquer PIC da familia 16?? mais especi camente o 16f877A?

Paulo Minholi 7 de julho de 2015 Responder

Boa noite,

Tentei fazer o projeto mas não funcionou… no display acendem todos os quadrados da linha inferior,
somente isso. Tem alguma ideia do que pode ser?

Godoy 19 de setembro de 2015 Responder

Ajuste o pot do Vee

Henrique 16 de outubro de 2015 Responder

olá, eu gostaria de saber até que distância consigo ligar o display do PIC? Exemplo posso ligar o LCD há 5
metros do PIC? A ideia é fazer esta ligação através de um cabo de rede.

Rafael 23 de setembro de 2015 Responder

Boa tarde Rafael,

https://www.filipeflop.com/blog/display-lcd-16x2-pic-16f628a/ 6/8
12/12/2017 Ligando Display LCD 16x2 ao PIC 16F628A - FilipeFlop

Não temos essa informação. Só testando mesmo.

Abraço.

Adilson – Equipe FILIPEFLOP

Paulo 23 de setembro de 2015 Responder

quantos sao de i/o como os pinos sao divididos

bruno rigueira 19 de janeiro de 2016 Responder

como é possivel con gurar os pinos de i/o

bruno rigueira 19 de janeiro de 2016 Responder

posso utilizar o pic 16f877a ?

saul 28 de junho de 2016 Responder

O que faz a função bit_test()? é do proprio pic?


Estou tentando utilizar essa biblioteca com um microcontrolador da freescale.

Felipe 9 de setembro de 2016 Responder

Como faço para escrever uma string maior que o numero de posições do LCD, de forma que uma frase
com 30 caracteres por exemplo, possa aparecer uma parte na linha de cima (16 colunas) e o restante na
linha de baixo (14 colunas) ??

Max Anderson 31 de maio de 2017 Responder

Olá, gostaria de saber como envio uma variável GLOBAL do tipo STRING para o LCD?.
Atualmente uso para enviar uma variável do tipo INTEIRO para o lcd a seguinte instrução:
printf(LCD_texto,”fHora: %2u:%2u:%2u”,hora,min,seg); //Escrevo
Funciona, mas String não estou conseguindo.
Poderia me ajudar?
Muito obrigado!!
Marcio Leandro

Marcio Leandro 28 de junho de 2017 Responder

Bom dia. acho muito bacana o trabalho de vocês de ensinar e ajudar quem esta aprendendo. Gostaria
de saber se vocês tem e pode me enviar o diagrama da placa de desenvolvimento “acepi 18-28” ja
procurei e não consigo encontrar nem mesmo na acepic. Sepuderem me ajudar eu agradeço.
Forte abraço a tds…

David Valério da Silva 13 de outubro de 2017 Responder

Pesquisar Posts no BLOG Categorias

Pesquisar …  Arduino (83)

 Display (7)

 Embarcados (41)

https://www.filipeflop.com/blog/display-lcd-16x2-pic-16f628a/ 7/8
12/12/2017 Ligando Display LCD 16x2 ao PIC 16F628A - FilipeFlop

 ESP8266 (15)

 Módulos (14)

 Motores e Servos (18)

 News (26)

 Outros (11)

 Raspberry Pi (45)

 Sensores (23)

 Shield (2)

 Wearable (4)

 Wireless (44)

Posts Recentes

Informações da CPU da Raspberry Pi


Zero W com display OLED
12 de dezembro de 2017

ESP8266: Gravando dados


permanentes na memória Flash
7 de dezembro de 2017

Como atualizar o Linux da Intel


Edison
5 de dezembro de 2017

Supercomputador com Raspberry Pi


30 de novembro de 2017

Primeiros passos de FPGA com a


Papilio One
29 de novembro de 2017

v Assine a Newsletter
...e junte-se à maior comunidade maker do Brasil
Digite seu E-mail Enviar

Dúvidas Institucional
Frequentes
r m n

o
0 0
 Pesquisar produtos… Quem Somos
Como comprar
Alguma dúvida? Entre em Termos de Uso
contato! Frete Grátis
(48) 3307-3495 Trabalhe
Pagamento e Conosco
envio

Atendimento Online Trocas e


Seg-Sex das 08h30-11h30 às 13h-17h
devoluções

     

FilipeFlop Componentes Eletrônicos | CNPJ: 12.672.380/0001-90


Rod. José Carlos Daux 4850 Galpão 19, Florianópolis/SC, 88032-005

https://www.filipeflop.com/blog/display-lcd-16x2-pic-16f628a/ 8/8