Módulo de Display LCD

Módulo de Display LCD

Introdução

Módulos de display LCD de caracteres alfanuméricos são interfaces de comunicação visual muito úteis e atraentes. Eles se encontram em quase todos os aparelhos domésticos, eletroeletrônicos, automóveis, instrumentos de medição etc. São dispositivos que possuem interfaces elétricas padronizadas e recursos internos gráficos e de software que permitem facilmente a permuta por outros de outros fabricantes, sem que seja necessário alterar o programa de aplicação. Por ser altamente padronizado seu custo é baixo. É um recurso antigo, deve ter uns vinte anos de idade ou mais, mas continua atual, com suas inúmeras formas, cores, tamanhos e preços. A tecnologia predominante continua sendo o LCD (Liquid Crystal Display), porém já se pode encontrar alguns baseados em LEDs orgânicos (OLED).

O módulo de display LCD representa um avanço tecnológico enorme se comparado com os primeiros displays a LED de 7, 14 ou 16 segmentos. Leia mais sobre os displays a LED no artigo técnico Displays de LED de 7 segmentos [1].

Especificações

Os módulos LCD são especificados principalmente por sua capacidade gráfica de comunicação, ou seja, o número de caracteres por linha e o número de linhas. Alguns valores típicos para essas especificações são:

Número de caracteres: 8, 12, 16, 20, 24 e 40

Número de linhas: 1, 2 e 4

Algumas configurações típicas de um módulo de display LCD

Módulo LCD 20 x 1
Figura 1: Módulo LCD 20 x 1
Módulo LCD 40 x 4
Figura 2: Módulo LCD 40 x 4

Outras especificações importantes que devemos considerar são as dimensões físicas do módulo, a tensão de alimentação, a disposição física dos pontos de conexão externa, a posição desses pontos de conexão com relação ao display, dos lados esquerdo ou direito, em cima ou embaixo, o tipo de interface eletrônica, paralela (predominante) ou serial, backlight (luz de fundo)  e finalmente o controlador do display.

Quando se consulta o manual de um módulo de display LCD, em geral se obtém apenas uma página contendo as dimensões e especificações elétricas. Isso pode parecer pouco mas é mais do que o suficiente. Observe na Figura 3 as especificações  do módulo retratado na Figura 1.

Especificações do módulo Winstar modelo WH2001B [6]
Figura 3: Especificações do módulo Winstar modelo WH2001B [6]

Interface de conexão externa

A interface de conexão com um microcontrolador também é padronizada. Ela tem de 14 a 16 pinos, dependendo se o módulo tem ou não backlight para permitir a leitura do display em ambientes escuros. Na Tabela 1 se pode observar a descrição dos pinos.

Tabela 1: Descrição dos pinos da interface de conexão

Pinos_b

Repare que o pino 3 foi reservado para ajustar o contraste do display. Isso permite que você ajuste esse contraste para a melhor visibilidade do texto. Na Figura 4 se pode observar um circuito simples para essa função.

Circuito simples para o ajuste de contraste
Figura 4: Circuito simples para o ajuste de contraste

O contraste muitas vezes varia em função da temperatura ambiente. Para isso pode-se utilizar o circuito ilustrado na Figura 5, por exemplo, que compensa essa variação.

Ajuste de contraste com compensação de temperatura
Figura 5: Ajuste de contraste com compensação de temperatura

Se for utilizado o backlight é necessário providenciar as conexões e dimensionar corretamente o resistor para limitar a corrente nos LEDs. Nas especificações do módulo WH2001B (Figura 6), se pode observar que a corrente típica dos LEDs de backlight (IF) é de 60 mA e a máxima de 75 mA com tensões diretas (VF) correspondentes respectivamente a 3,5 e 3,6V.

ATENÇÃO: Nunca ligue a fonte de alimentação diretamente nos terminais de backlight. Isto provocará o aquecimento excessivo do display e a queima prematura do módulo.

Características elétricas do módulo WH2001B
Figura 6: Características elétricas do módulo WH2001B

A Figura 7 ilustra um circuito típico para ativar o backlight. Utilizando os dados da Figura 6, podemos calcular o resistor de limitação de corrente.

Conexões típicas do backlight
Figura 7: Conexões típicas do backlight

Rlimit = (5 – 3,5)V / 60mA = 25 Ohms      (Pode-se utilizar os valores comerciais de 22 ou 27 Ohms 5%)

Quando for projetada a conexão do módulo com um microprocessador, é sempre bom lembrar que o operação do módulo LCD é relativamente lenta, se comparada com a de um microcontrolador. Na Figura 8 se pode observar os diagramas de tempos de leitura e escrita da interface com o microcontrolador. É muito importante que se estude esses diagramas e que sejam respeitados os tempos especificados nesses diagramas.

Figura 8: Diagramas de tempo típicos para a leitura e a escrita dos módulos LCD

Uma boa maneira de se verificar se o módulo está pronto para um novo acesso é testar o busyflag (bit de sinalização de ocupado). Para acessar esse flag, deve-se acionar os bits de controle RS = 0 e R/W = 1 (Read) e o flag poderá ser lido em DB7. Deve-se esperar o término das operações internas enquanto DB7 estiver em 1. Os detalhes você pode ler no manual do controlador.

Controladores de display  LCD

No intuito de manter a padronização e compatibilidade entre os módulos de display de diversos fabricantes, adotou-se no início que o componente da Samsung –  KS0066 [2] seria o padrão para esse tipo de módulo. É muito comum encontrarmos especificações de controladores como compatíveis com o KS0066. Outros controladores compatíveis: Samsung S6A0069 [3], Sitronix – ST 7066 [4] e Hitachi – HD44780 [5].  O HD44780 atualmente é o mais utilizado.

Quando se compra um módulo de display LCD é interessante se saber qual é o controlador que é utilizado nesse módulo. Os recursos oferecidos pelos controladores variam um pouco além dos recursos básicos comuns para todos. Alguns recursos comuns são a interface com um microcontrolador configurável para 4 ou 8 bits, memória ROM interna com os gráficos correspondentes a cada caractere disponível, opções de Fonts para os caracteres, entre outros. Na Figura 9 se pode observar como é formado graficamente o caractere “A”, numa matriz de pontos (pixels), onde os 1s indicam pixels acesos e os 0s, os pixels apagados.

Caractere "A" numa matriz de pixels (8 x 5)
Figura 9: Caractere “A” numa matriz de pixels (8 x 5)

A seguir serão mostrados os comandos ou instruções que podem ser utilizados nos módulos. O código dessas instruções também é padronizado. Serve para a maioria dos módulos. Veja a Tabela 2.

 Tabela 2: Instruções de um módulo LCD

Um outro aspecto importante na utilização do módulo é respeitar a sequência de inicialização, após a energização do módulo. As especificações do controlador fixam o seguinte fluxo (Figura 10).

Figura 10: Sequência de inicialização para operação em 8 bits

Observe que na inicialização existem situações em que não é possível testar o busy-flag, porém é necessário esperar no mínimo o tempo especificado para que o controlador esteja pronto para receber mais um comando.

Depois e inicializado, o módulo pode receber caracteres para serem apresentados no display. Para isso, basta transferi-los de forma adequada para o endereço interno ao controlador correspondente ao da DDRAM (Display Data RAM). O endereço inicial da primeira linha é 0x00, o da segunda é 0x40 etc. Os caracteres deverão estar codificados em ASCII. Simples, não?

Exemplo

A seguir serão apresentados alguns trechos de código desenvolvidos no MPLAB e o compilador C30 da Microchip, para um dsPIC32. Os dados de 8 bits para o display LCD foram conectados ao Port D e os demais sinais em outro Port. O módulo do display utilizado é um módulo no padrão 16 x 2. A seguir se pode observar a definição de diversas constantes e parâmetros para o módulo LCD.

Observação: Como o código está escrito em linguagem C, é muito fácil adaptá-lo para qualquer outro microcontrolador. 

//*************** DISPLAY LCD ***********************

#define DADO_DISPLAY              PORTD
#define MASCARA_DO_DISPLAY       0x00ff

#define RESET_LCD                _LATE4   //_RE4
#define RD_WR_LCD                _LATE5   //_RE5
#define ENABLE_LCD               _LATE6   //_RE6

#define BUSY_FLAG                _RD7
#define COMANDO_LCD              0
#define DADOS_LCD                1

// Define os comandos e configuração do DISPLAY LCD

#define CLR_DISPLAY              0b00000001
#define RETURN_HOME              0b00000010

//***

#define ENTRY_SET_MODE           0b00000100    // A ser composto com os parametros abaixo

// Direção do cursor

#define INCREMENT                0b00000010
#define DECREMENT                0b00000000

// Deslocamento do Display

#define EN_SHIFT                 0b00000001
#define NO_SHIFT                 0b00000000

//***

#define DISPLAY_ON_CONTROL       0b00001000    // A ser composto com os parametros abaixo

// Liga ou desliga o display

#define DISPLAY_ON               0b00000100
#define DISPLAY_OFF              0b00000000

// Liga ou desliga o cursor
#define CURSOR_ON                0b00000010
#define CURSOR_OFF               0b00000000

// Pisca o cursor
#define CURSOR_BLINK_ON          0b00000001
#define CURSOR_BLINK_OFF         0b00000000
//***

#define CURSOR_DISPLAY_SHIFT     0b00010000    // A ser composto com os parametros abaixo

// Bits de configuração do deslocamento

#define CURSOR_LEFT_AC_DECR      0b00000000
#define CURSOR_RIGHT_AC_INCR     0b00000100
#define SHIFT_DISPLAY_LEFT       0b00001000
#define SHIFT_DISPLAY_RIGHT      0b00001100

//***

#define FUNCTION_SET             0b00100000    // A ser composto com os parametros abaixo

// Tamanho do bus de dados
#define BUS_8_BITS               0b00010000
#define BUS_4_BITS               0b00000000

// Numero de linhas do Display
#define DISPLAY_2_LINHAS         0b00001000
#define DISPLAY_1_LINHA          0b00000000

// Tamanho do fonte
#define FONTE_5x11               0b00000100
#define FONTE_5x8                0b00000000

//***
#define SET_CGRAM_ADDRESS        0b01000000
#define SET_DRAM_ADDRESS         0b10000000

#define END_INICIAL_LINHA_1      0x00
#define END_INICIAL_LINHA_2      0x40

// Saudacao

int chSaudacaoDeAbertura[16] = {' ', ' ', 'E', 'M', 'B', 'A', 'R', 'C', 'A','D','O','S',' ',' ', 0x0};
int chSaudacaoDeAbertura_II[16] = {' ', 'D', 'i', 's', 'p', 'l', 'a', 'y',' ',' ','L','C','D',' ',' ', 0x0};

char fchFlagApresentouSaudacao = 0;
char fchFlagDisplayLimpo             = 0;

//***************************************************

A seguir, se pode observar as rotinas que acessam o módulo propriamente dito. Uma rotina que escreve um caractere e outra que escreve uma frase. Observe que na rotina que escreve um caractere é utilizado um temporizador (T4) para realizar as temporizações necessárias.

Rotina Escreve no Display LCD

void Escreve_no_Display_LCD(char chDado, char chModo)
   {
   //********************************************************************************************
   //
   // Rotina que escreve um caracter para o Display LCD
   //
   // Entradas: Caracter a ser transmitido
   //                  Modo de transmissao: COMANDO - 0
   //                                       DADOS   - 1
   // Saidas:     Nenhuma
   //
   //*******************
 
   char chfTerminou = 0;
   char chContadorDeTimeOut = 0;
   char chfFalhaDeBusy = 0;
   
   // Inicializa os sinais de controle
   
    RESET_LCD  = chModo;
    RD_WR_LCD  = 0b0;
    ENABLE_LCD = 0b0;
   
   // Inicializa temporizacao
   
    PR4        = ESPERA_MEIO_CICLO;
    
    // Atencao!!!! a variavel abaixo deve ser inicializada antes de habilitada a interrupcao!!!
   
   nTerminoDeTemporizacaoDisplay = 0;      // Inicializa flag de termino
   
   _T4IE       = 0b1;      // Habilita a interrupcao
   _TON_T4 = 0b1;      // Liga Timer
   
   // Espera o tempo necessario
   while (nTerminoDeTemporizacaoDisplay ==  0)
      {
      }
   // Transfere o dado
   
   DADO_DISPLAY = chDado & MASCARA_DO_DISPLAY;
   
   ENABLE_LCD = 0b1;
   
   // Inicializa temporicacao
   
     PR4                = ESPERA_MEIO_CICLO;
   
    // Atencao!!!! a variavel abaixo deve ser inicializada antes de habilitada a interrupcao!!!
   
     nTerminoDeTemporizacaoDisplay = 0;      // Inicializa flag de termino
   
   _T4IE       = 0b1;      // Habilita a interrupcao
   _TON_T4 = 0b1;          // Liga Timer
   
   // Espera o tempo necessario
   while (nTerminoDeTemporizacaoDisplay ==  0)
      {
      }
   while (chfTerminou == 0)
      {
        Aguarda sinal de OK */
        ENABLE_LCD = 0b0;
      
      // Inicializa temporicacao
      
        PR4                = ESPERA_MEIO_CICLO;
      
       // Atencao!!!! a variavel abaixo deve ser inicializada antes de habilitada a interrupcao!!!
      
        nTerminoDeTemporizacaoDisplay = 0;      // Inicializa flag de termino
      
        RD_WR_LCD = 0b1;
      
      _T4IE       = 0b1;          // Habilita a interrupcao
      _TON_T4 = 0b1;          // Liga Timer
      
      // Espera o tempo necessario// Espera o tempo m¡nimo
      while (nTerminoDeTemporizacaoDisplay ==  0)
         {
         }
       ENABLE_LCD = 0b1;
      
      // Inicializa temporicacao
      
        PR4                = ESPERA_MEIO_CICLO;
      
       // Atencao!!!! a variavel abaixo deve ser inicializada antes de habilitada a interrupcao!!!
      
        nTerminoDeTemporizacaoDisplay = 0;      // Inicializa flag de termino
      
      _T4IE       = 0b1;      // Habilita a interrupcao
      _TON_T4 = 0b1;          // Liga Timer
      
      // Espera o tempo necessario// Espera o tempo m¡nimo
      while (nTerminoDeTemporizacaoDisplay ==  0)
         {
         }
      if (BUSY_FLAG == 1)
         {
         // Incrementa o contador de time-out
         
         chContadorDeTimeOut++;
         if (chContadorDeTimeOut == CONTAGEM_TIME_OUT_LCD)
            {
            // Sinaliza que terminou a espera 
            
            chfTerminou =1;
            chfFalhaDeBusy = 1;
            }
         }
      else
         {
         // Sinaliza que terminou a espera 
         
         chfTerminou =1;
         }
      }

   // Testa se houve falha
   if (chfFalhaDeBusy == 1)
      {
      }
   // Termina o ultimo ciclo
   
     ENABLE_LCD = 0b0;      // Inicializa temporicacao
   
   _TON_T4 = 0b0;      // Desiga Timer
   _T4IE       = 0b0;      // Desabilita a interrupcao
   _T4IF       = 0b0;      // Zera o flag de interrupcao
    TMR4     = 0x0000;
     PR4                = ESPERA_MEIO_CICLO;
   
    // Atencao!!!! a variavel abaixo deve ser inicializada antes de habilitada a interrupcao!!!
   
     nTerminoDeTemporizacaoDisplay = 0;      // Inicializa flag de termino
   
     RD_WR_LCD = 0b0;
     RESET_LCD   = 0b0;
   
   _T4IE       = 0b1;      // Habilita a interrupcao
   _TON_T4 = 0b1;      // Liga Timer
   
   
   // Espera o tempo necessario
   while (nTerminoDeTemporizacaoDisplay ==  0)
      {
      }
   // Espera o display executar a atualizacao
   
   _TON_T4 = 0b0;      // Desiga Timer
   _T4IE       = 0b0;      // Desabilita a interrupcao
   _T4IF       = 0b0;      // Zera o flag de interrupcao
    TMR4     = 0x0000;
     PR4                = ESPERA45us;
   
    // Atencao!!!! a variavel abaixo deve ser inicializada antes de habilitada a interrupcao!!!
   
    nTerminoDeTemporizacaoDisplay = 0;      // Inicializa flag de termino
   
   _T4IE       = 0b1;      // Habilita a interrupcao
   _TON_T4 = 0b1;          // Liga Timer
   
   // Espera o tempo necessario
   while (nTerminoDeTemporizacaoDisplay ==  0)
      {
      }
   }

Rotina Escreve uma frase

void Escreve_Frase_no_Display_LCD(int *pchDado,  int nEndereco)
   {
   //************************************************************************************
   //
   //  Rotina que escreve um "string" ASCII no display LCD
   //
   //  Entradas: Ponteiro para "string", terminado com 0, máximo 17 caracteres incluindo o 0
   //            Endereco onde posicionar o primeiro caractere
   //
   //  Saidas:    Nenhuma
   //
   //****
 
   // Acerta o endereco
   
   Escreve_no_Display_LCD((SET_DRAM_ADDRESS | nEndereco), COMANDO_LCD);
   
   // Transfere a frase
   while (*pchDado != 0)
      {
      // Escreve a saudacao
      
      Escreve_no_Display_LCD(*pchDado, DADOS_LCD);
      pchDado++;
      }
   }

 O próximo trecho é inserido no programa principal na parte de inicializações.

   //=== Inicializa PORT D ===
   //

   PORTD = 0x0000;                  // Inicializa PORTD
   TRISD = 0xCF00;                  // Inicializa a configuração de E/S (1 = E/ 0 = S)
   ODCD  = 0x00FF;                  // Inicializa as saídas de coletor aberto
   //
   //=== Inicializa DISPLAY LCD  ===
   //
   
   // Aguarda periodo minimo antes de inicializar - 30ms
   
   char chAuxiliar = 3;
   while (chAuxiliar-- > 0)
      {
       PR4 = ESPERA10ms;
      
      nTerminoDeTemporizacaoDisplay = 0;      // Inicializa flag de termino
      
      _T4IE       = 0b1;          // Habilita a interrupcao
      _TON_T4 = 0b1;              // Liga Timer
      
      
      // Espera o tempo necessario
      while (nTerminoDeTemporizacaoDisplay == 0)
         {
         }
      }
   // Define o funcionamento do display
   
   Escreve_no_Display_LCD((FUNCTION_SET | BUS_8_BITS | DISPLAY_2_LINHAS |  FONTE_5x11), COMANDO_LCD);
   
   // Liga o Display
   
   Escreve_no_Display_LCD((DISPLAY_ON_CONTROL | DISPLAY_ON | CURSOR_OFF |  CURSOR_BLINK_OFF), COMANDO_LCD);
   
   // Limpa o Display
   
   Escreve_no_Display_LCD((CLR_DISPLAY), COMANDO_LCD);

   // Espera limpar o display
   
    PR4 = ESPERA1550us;
    nTerminoDeTemporizacaoDisplay = 0;      // Inicializa flag de termino

   _T4IE       = 0b1;          // Habilita a interrupcao
   _TON_T4 = 0b1;              // Liga Timer
   
   
   // Espera o tempo necessario
   while (nTerminoDeTemporizacaoDisplay == 0)
      {
      }

   // Escreve na primeira linha
   
   Escreve_Frase_no_Display_LCD(&chSaudacaoDeAbertura[0],  END_INICIAL_LINHA_1 );

   // Escreve restante na segunda linha
   
   
   Escreve_Frase_no_Display_LCD(&chSaudacaoDeAbertura_II[0],  END_INICIAL_LINHA_2 );
   fchFlagApresentouSaudacao = 1;
   

Se você quiser se aprofundar um pouco mais nesse assunto, sugiro que você leia o artigo técnico Display LCD [7] de Ilton L. Barbacena e Claudio Afonso Fleury.

Referências

[1] https://embarcados.com.br/displays_led_7_segmentos/

[2] https://www.datasheetarchive.com/dlmain/Datasheets-29/DSA-570765.pdf

[3] https://pdf1.alldatasheet.com/datasheet-pdf/view/37838/SAMSUNG/S6A0069.html

[4] https://pdf1.alldatasheet.com/datasheet-pdf/view/325981/SITRONIX/ST7066U.html

[5] https://pdf1.alldatasheet.com/datasheet-pdf/view/63673/HITACHI/HD44780.html

[6] https://www.winstar.com.tw/download.php?ProID=134

[7] ftp://ftp.dca.fee.unicamp.br/pub/docs/ea079/complementos/Lcd.pdf

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
9 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Leonardo
Leonardo
14/07/2021 12:04

Bom dia Henrique. você sabe me dizer se o controlador de um display 128×64 Sitronix St7565 é compatível com esses módulos de arduino como o St7920, se há algum site para consulta? lista? Obrigado

WILSON
WILSON
12/06/2020 16:17

Amigo,
Pode tirar uma duvida.
o display lcd2004 é compativel com display gdm2004?

Robson
Robson
02/05/2019 16:53

Parabéns, esclarecedor o artigo

Rafael
Rafael
25/01/2019 08:28

Muito bom! Obrigado pela aula.

Marcelo Moreno
Marcelo Moreno
20/04/2018 14:14

Parabéns! Pela Materia o Sr poderia fazer uma matéria de tipos de comunicação para si temas embarcados.

Bernardo
Bernardo
05/05/2015 21:14

Caro Henrique, boa noite ! Gostei muito do seu tutorial. Me remeteu aos tempos em que tínhamos que programar “na unha” a operação desses displays.
Uma dúvida: Qual editor de códigos é utilizado para colocar esses códigos na página do blog, de tal forma que fiquem com as linhas com contrastes diferentes e numeradas ?
Um abraço !

Diego Sueiro
Diego Sueiro
Reply to  Bernardo
05/05/2015 21:59

Olá Bernardo,

Para postar código-fonte utilizamos esse plugin:
https://wordpress.org/plugins/crayon-syntax-highlighter/

Bernardo
Bernardo
Reply to  Diego Sueiro
05/05/2015 22:23

Obrigado Diego !!!

Henrique Frank W. Puhlmann
Reply to  Bernardo
06/05/2015 19:39

Bons tempos, Bernardo.
Abraço

Home » Software » Firmware » Módulo de Display LCD

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: