Uso do LCD (tutorial)

Ver o tópico anterior Ver o tópico seguinte Ir em baixo

Uso do LCD (tutorial)

Mensagem  Bruno S. Avelar em Ter Maio 11, 2010 4:02 pm

Como haviam vários e-mails na minha caixa de e-mail com dúvidas como trabalhar com LCD em sistemas microcontrolados em especial com PICs e com o KIT PIC MINAS decidi fazer um post longo, mas completo, de como funciona e como se trabalha com estes periféricos tão úteis.

LCD de A a Z + caracteres especiais:


Pré-requisitos para o bom entendimento deste post:

  1. Saber trabalhar com postas I/O digitais.
  2. Saber trabalhar com delays.
  3. Saber programação básica em C.
  4. Recomendável saber trabalhar com strings em C.

Considerações:

  1. Utilizaremos o PIC18F4550 com clock de 48Mhz (se você usar outro clock terá que mudar os delays) e basearemos no KIT PIC MINAS V3.0, seguindo o objetivo de criação do fórum. Caso você não use o KIT você terá que fazer pequenas adaptações, mas acredito que a teoria aqui apresentada será útil.
  2. Os exemplos e a aplicação pronta em si serão feitos com base no compilador C18 disponibilizado pela Microchip. Não é difícil a adaptação para outros compiladores.
  3. É altamente recomendado que você tenha o datasheet do LDC que vai usar.
  4. No curso de microcontroladores do PIC Minas possui uma aula exclusiva para tratar sobre display LCD. Este tutorial não objetiva substituir .


Introdução:


Existem vários tipos de LCD no mercado atualmente e são geralmente descritos por AxB onde A é o numero de linhas e B o número de colunas. Por exemplo:
08x02 – oito colunas e duas linhas.
16x01 – dezesseis colunas e uma linha.
16x02 – dezesseis colunas e duas linhas. (presente no KIT)
20x01, 20x02, 20x04.
Existem também modelos com back-light e sem back-light. O Back-light é um LED ou conjunto de LEDs no fundo do display que permite que o escrito possa ser lido em ambientes de baixa ou nenhuma luminosidade.
Os modelos mais comuns comunicam através de pinos de I/O de seu microcontrolador chamados de LCDs paralelos. Irei focar nestes modelos que são os mais utilizados, mas também existem modelos que comunicam via serial seja I2C, SPI ou outro protocolo.
Além disto, você encontrará diversas cores de escrito e de fundo. Alguns possuem os pinos de conexão na parte de cima do LCD outros ao lado e outros em baixo. Então você pode escolher o LCD que melhor sirva para seu projeto. A boa notícia é que todos seguem o mesmo protocolo de funcionamento que vou explicar logo mais adiante.

Teoria:

1.0 - Um pouco sobre o Hardware:
O LCD é formado por “células” onde ficam os caracteres. Por exemplo, um display de 16x2 possui 32 “células”. Cada “célula” é composta por uma matriz de 8x5 pontos (pixels) como mostrado na figura abaixo:


Existe uma interface padrão de hardware que todos os fabricantes de LCD utilizam. Em geral um LCD possui 14 pinos quando não possui back-light e 16 pinos quando possui. De forma resumida a função de cada pino:


O pino 3 normalmente não é ligado ao microcontrolador e sim a um potenciômetro. Ele é usado para controlar o contraste do LCD, geralmente uma vez regulado não necessita de mudanças. No KIT PICMINAS V3.0 está ligado a um potenciômetro.
Quando alimentamos o LCD, normalmente com 5V, a primeira linha fica toda preenchida para regular o contraste e para saber que ele está “funcionando”.
O pino 5 possui a função de selecionar o modo escrita e leitura. Para esmagadora parte dos projetos utilizamos apenas a função de escrita então este pino também não é, necessariamente, conectado ao microcontrolador. No caso do KIT PIC MINAS 3.0 o pino é aterrado deixando o LCD somente como escrita.
O backlight possui um consumo grande e não é recomendado ligar-lo a um pino de I/O do microcotrolador. Caso queria controlar o backlight você pode usar um transistor como chave para controlar a passagem de corrente da fonte de alimentação para o LCD. Devido ao KIT PIC Minas funcionar na USB do computador ou com uma fonte externa que em geral é uma bateria e também por não haver nenhum conhecimento novo neste controle do backlight nós optamos por não implementar o backlight.

2.0 – Comunicação:
O LCD possui um microcontrolador soldado a sua placa. O que temos que fazer é comunicar com este para passar configurações de como queremos que ele funcione e dados que queremos que ele apresente na tela. A comunicação com o LCD é feita através dos pinos de I/O digitais do seu microcontrolador. O diagrama de blocos abaixo esclarece:


Para haver compatibilidade com firmwares que usavam LDCs antigos existem duas formas de comunicação:
1- Enviar um byte (8 bits) por vez com a configuração ou caractere a ser escrito.
2- Enviar dois nibbles (4 bits) com a configuração ou caractere a ser escrito.
O modo de transferência por 2 nibbles foi feito para diminuir o número de portas usadas do microcontrolador. É este modo que usamos para comunicar com o LCD no KIT PIC Minas V3.0.
Em ambos os casos a comunicação é feita setando os pinos de dados (DB0 a DB7 com byte e DB4 a DB7 com 2 nibbles), o RS e o R/W com zeros e uns e informando ao controlador que os pinos devem ser lidos pois existe uma configuração ou comando para ser executado. Este informe é feito elevando o nível do pino de enable de 0 para 1 e retornando-o para 0.
Quando trabalhamos com a comunicação através de 2 nibbles colocamos dividimos o byte que desejamos em 2 nibbles. Então enviamos o nibble mais significativo (fazendo enable = 1 e enable = 0) e então enviamos o nibble menos significativo.
Cada “célula” do display é associada a um endereçamento e a um espaço de memória (de 8 bits). Este endereçamento, permite que escolhamos um lugar especifico no display para escrita. O endereçamento começa na primeira linha primeira coluna como 0x00 e vai incrementando a cada caractere. A segunda linha primeira coluna é o 0x40 e cada célula subseqüente é incrementado 1. A figura abaixo ilustra o endereçamento:


2.1 - Inicialização do LCD
O LCD precisa ser inicializado. Esta inicialização irá configurá-lo para funcionar com um byte ou dois nibbles e deixá-lo pronto para receber um comando ou uma configuração.

A - Comunicação em dois Nibles:
1- Após o LCD ser energizado deve esperar um tempo maior que 15 ms.
2- Enviar para o LCD: Rs = 0, R/W = 0, DB7 = 0, DB6 = 0, DB5 = 1, DB4 = 1
3- Aguardar um tempo maior do que 4,1 milissegundos.
4- Enviar para o LCD: Rs = 0, R/W = 0, DB7 = 0, DB6 = 0, DB5 = 1, DB4 = 1
5- Aguardar um tempo maior do que 100 microssegundos.
6- Enviar para o LCD: Rs = 0, R/W = 0, DB7 = 0, DB6 = 0, DB5 = 1, DB4 = 1
7- Enviar para o LCD: Rs = 0, R/W = 0, DB7 = 0, DB6 = 0, DB5 = 1, DB4 = 0
8- Enviar configurações de tamanho de caractere.
9- Enviar Display off
10- Limpar o LCD

B - Comunicação em um Byte:
1- Após o LCD ser energizado deve esperar um tempo maior que 15 ms.
2- Enviar para o LCD: Rs = 0, R/W = 0, DB7 = 0, DB6 = 0, DB5 = 1, DB4 = 1, DB3 = X, DB2 = X, DB1 = X, DB0 = X, onde X pode ser tanto 1 quanto 0.
3- Aguardar um tempo maior do que 4,1 milissegundos.
4- Enviar para o LCD: Rs = 0, R/W = 0, DB7 = 0, DB6 = 0, DB5 = 1, DB4 = 1, DB3 = X, DB2 = X, DB1 = X, DB0 = X, onde X pode ser tanto 1 quanto 0.
5- Aguardar um tempo maior do que 100 microssegundos.
6- Enviar para o LCD: Rs = 0, R/W = 0, DB7 = 0, DB6 = 0, DB5 = 1, DB4 = 1, DB3 = X, DB2 = X, DB1 = X, DB0 = X, onde X pode ser tanto 1 quanto 0.
7- Enviar para o LCD: Rs = 0, R/W = 0, DB7 = 0, DB6 = 0, DB5 = 1, DB4 = 1, DB3 = N, DB2 = F, DB1 = X, DB0 = X. (N e F serao explicados abaixo.)
8- Enviar Display off
9- Limpar o LCD

2.2 – Comandos do LCD:
O pino RS é quem define se os bits a serem enviados para o LCD serão configurações ou dados. Quando RS = 0 o controlador do LCD interpreta os bits enviados para ele como configurações. Quando RS = 1 o controlador do LCD interpreta os bits como dados e os escreve no display.
Os comandos mais importantes são listados na tabela abaixo:



2.3 – Escrita no LCD:
A escrita no LCD é feita setando RS como 1 e R/W como 0 e o código ASCII do caractere nos dados.



Muitas vezes utilizamos o comando ST CGRAM Address para informá-lo a posição onde deve ser feita a próxima escrita e, em seguida, enviamos o dado para ser ecrito.
Os dados são passados de acordo com a tabela abaixo que coincide em grande parte com a tabela ASCII:



Como os principais caracteres estão de acordo com a tabela ASCII podemos usar a biblioteca string.h de C para manipular os strings de texto e mandá-los para o LCD sem precisar de nenhum tipo de conversão.
Existem espaços de memória reservados para o usuário desenhar um símbolo que desejar.

Programação:

Escrevemos uma biblioteca para trabalhar com o LCD que pode ser vista e copiada abaixo. Ela foi feita para funcionar com dois nibbles, mas não é difícil modificá-la para funcionar com byte. A biblioteca está extremamente comentada e segue a lógica escrita na seção acima.

my_xlcd.h
Código:

/******************************************************************************
 *
 *            Curso PICMINAS de Microcontroladores (PIC18F4550)
 *
 ******************************************************************************
 * Nome do Arquivo:    my_xlcd.h
 * Dependencias:       Veja seção INCLUDES
 * Processador:         PIC18F4550
 * Opção de Clock:      HS 20MHz (externo) - CPU: 48MHz   
 * Compilador:           C18 v3.20 ou superior
 * Empresa:           PICMINAS - Axoon - UFMG
 *
 * Plataforma:         Kit PICMINAS v3.0
 *
 * Autor:            M.Sc. Henrique Resende Martins
 *                   Mauricio Ferrari Santos Corrêa
 * Data:            v1 - 15/Fev/2009
 *                  v2 - 28/Abr/2009
 *                  v3 - 16/Jun/2009
 *                  v4 - 18/Nov/2009
 *                  v5 - 28/fev/2010 (Bruno S. Avelar)
 *
 * Descrição:         Modificação da biblioteca xlcd.h forncedida com o compilador
 *                  C18 da Microchip. A biblioteca xlcd.h trata da comunicação
 *                  com display de LCD por meio de 4-bits (length), utilizando o
 *                  PORTB tanto para os 4 bits de dados quanto para os 3 bits de
 *                  controle (RS, RW e E).
 *                  No projeto do Kit PICMINAS o display LCD é ligado a portas
 *                  digitais diversas do PIC 18F4550. O Kit PICMINAS v3.0 utiliza
 *                  os seguintes pinos para comunicação com o display LCD:
 *                     PIC18F4550(pino):: Display LCD
 *                        RD4 (27)     ::     D4
 *                        RD5 (28)     ::     D5
 *                        RD6 (29)     ::     D6
 *                        RD7 (30)     ::     D7
 *                        RD2 (21)     ::      RS
 *                        RD3 (22)     ::     E
 *                         GND      ::     R/W
 *                  OBS: o pino R/W do display é ligado no  Kit PICMINAS ao GND
 *                  através de um resistor de pull-down, assim o LCD opera no
 *                  modo escrite(Write) o tempo todo. No entando o código C foi
 *                  escrito mostrando a imlementação onde um pino do PIC é
 *                  utilizado para a função R/W, assim comentando o inicio das
 *                  linhas correspondentes com "//não usado //".
 *  Notas:
 *      - Essa bliblioteca de rotinas foi escrita pensando em um LCD
 *        16x2 FDCC1602E implementado com o controlador SPLC780D, mas pode
 *         ser utilizado com qualquer LCD 16x2 com controladores equivalentes
 *        como, por exemplo, o controlador Hitachi HD44780 LCD controller.
 *
 *      - O usuário deve definir os seguintes itens:
 *         -- O tipo de interface de comunicação do LDC com o PIC (4 ou 8-bits):
 *            Se for o modo 4-bit, utilizar o upper nibble (nibble é metade de um Byte)
 *           , ou seja, enviar primeiro os 4 bits mais significativos (upper nibble)
 *           e depois os 4 bits menos sgnificativos (lower nibble).
 *
 *          -- Cursor e/ou Blink:
 *            O usuário poderá definir se quer visualizar cursor, blink
 *           ou nenhum dos dois.
 *         
 *         -- O sincronismo da comunicação com o LCD:
 *            As temporizações entre o envio de comandos, não foi utilizado
 *           o bit de Busy do LCD, mas sim, através de funções de atraso.
 *           A função utilizada foi a Delay10KTCYx() da bilioteca padrão C18
 *           delays.h que aparece na seção INCLUDE deste arquivo.
 *            Os tempos de delay escolhidos estão colocados nos defines:
 *           DELAY_SINC e DELAY_INICIO, que foram ecolhidos bem acima do
 *           tempo mínimo requerido pelo display de LCD (5ms o de sincronismo e
 *           15ms o inicial).
 *****************************************************************************/

/** I N C L U D E S **********************************************************/
#include <p18cxxx.h>   // Biblioteca com as definições do PIC selecionado
                  //no projeto, neste caso, o modelo 18F4550.

#include <delays.h>      // Biblioteca padrão C18 Microchip para uso de rotinas de atraso (delay)
                  // mais informações nos arquivos de ajuda da biblioteca C18
                  // presentes na propria pasta de instalação, por exemplo,
                  // C:\MCC18\doc\hlpC18Lib.chm
                  // Procure pelo item: "Delay Functions"


// Define os pinos de DADOS do LCD para o KIT PIC V2.0 da AXOON MED
#define D4      PORTDbits.RD4      // Define a porta RB1 como D4
#define D5      PORTDbits.RD5      // Define a porta RC6 como D5
#define D6       PORTDbits.RD6      // Define a porta RB0 como D6
#define D7      PORTDbits.RD7      // Define a porta RC7 como D7
// Define os TRIS dos pinos de DADOS do LCD para o KIT PIC V2.0 da AXOON MED
#define TRIS_D4  TRISDbits.TRISD4   // Define o TRIS RB1 para D4
#define TRIS_D5  TRISDbits.TRISD5   // Define o TRIS RC6 para D5
#define TRIS_D6  TRISDbits.TRISD6   // Define o TRIS RB0 para D6
#define TRIS_D7  TRISDbits.TRISD7   // Define o TRIS RC7 para D7

// Define os pinos de CONTROLE do LCD para o KIT PIC V2.0 da AXOON MED
#define RS_PIN  PORTDbits.RD2     // Define a porta RD2 como RS_PIN
//não usado // #define RW_PIN  PORTBbits.RB2     // Define a porta RB2 como RW_PIN
#define E_PIN    PORTDbits.RD3     // Define a porta RD3 como E_PIN
// Define os TRIS dos pinos de DADOS do LCD para o KIT PIC V2.0 da AXOON MED
#define TRIS_RS  DDRDbits.RD2       // Define o TRIS RD2 para RS_PIN
//não usado // #define TRIS_RW  DDRBbits.RB2       // Define o TRIS RB2 para RW_PIN
#define TRIS_E  DDRDbits.RD3       // Define o TRIS RD3 para E_PIN

// Define o valor dos delays baseado no clock da CPU de 48 MHz
#define DELAY_SINC      6   //(5ms)
#define DELAY_INICIO   18   //(15ms)

/**  P R O T O T I P O  D E  F U N C O E S  **********************************/
/******************************************************************************
 * Funcao:      void OpenXLCD(void)
 * Entrada:      Nenhuma (void)
 * Saída:      Nenhuma (void)
 * Descrição:    Configura portas do PIC 18F4550 que estão conectadas ao
 *            display LCD como saida. Essa rotina é baseada no controlador
 *            de LCD Hitachi HD44780. Configura os parametros de comunicação
 *            com o display, tais como:
 *               - modo de operação (4 ou 8 data bits)
 *               - tipo de cursor
 *               - tamanho da fonte
 *            Ao final da configuração limpa o display.
 *****************************************************************************/
void OpenXLCD(void);



/******************************************************************************
 * Funcao:      void SetDDRamAddr(unsigned char DDaddr)
 * Entrada:      DDaddr: endereço da memoria de dados do display que se deseja apontar
 * Saída:      Nenhuma (void)
 * Descrição:    (Set the Display Data RAM Address)
 *            Essa rotina seta o endereço da memoria RAM de dados do
 *            display LCD para o endereço   que se deseja escrever um caracter
 *            usando a função WriteDataXLCD().
 *****************************************************************************/
void SetDDRamAddr(unsigned char DDAddr);



/******************************************************************************
 * Funcao:      void WriteCmdXLCD(unsigned char cmd)
 * Entrada:      cmd: comando que será enviado para o LCD
 * Saída:      Nenhuma (void)
 * Descrição:    (Write a command to the LCD)
 *            Escreve um comando no display de LCD.
 *****************************************************************************/
void WriteCmdXLCD(unsigned char cmd);



/******************************************************************************
 * Funcao:      void WriteDataXLCD(unsigned char data)
 * Entrada:      data: Byte de dados para ser escrito na memoria RAM do LCD
 * Saída:      Nenhuma (void)
 * Descrição:    (Write a Data byte to the LCD)
 *            Essa rotina escreve um byte de dados na posição da memoria RAM setada
 *             anteriormente com a função SetDDRamAddr().
 *****************************************************************************/
void WriteDataXLCD(unsigned char data);



/******************************************************************************
 * Funcao:      void putsXLCD(char *buffer)
 * Entrada:      *buffer: apontador para string na memoria de dados(RAM)
 * Saída:      Nenhuma (void)
 * Descrição:    Essa rotina copia uma string terminada com caracter nulo
 *            da memoria de dados do microcontrolador para o display de LCD.
 *            A string apontada por *buffer é copiada no display a partir da
 *            posição da memoria RAM do display escolhida com a função
 *            SetDDRamAddr().
 *****************************************************************************/
void putsXLCD(char *buffer);



/******************************************************************************
 * Funcao:      void putrsXLCD(const rom char *buffer)
 * Entrada:      *buffer: apontador para string na memoria de programa(ROM)
 * Saída:      Nenhuma (void)
 * Descrição:    Essa rotina copia uma string terminada com caracter nulo
 *            da memoria de programa do microcontrolador para o display de LCD.
 *            A string apontada por *buffer é copiada no display a partir da
 *            posição da memoria RAM do display escolhida com a função
 *            SetDDRamAddr().
 *****************************************************************************/
void putrsXLCD(const rom char *buffer);
my_xlcd.c
Código:

/******************************************************************************
 *
 *            Curso PICMINAS de Microcontroladores (PIC18F4550)
 *
 ******************************************************************************
 * Nome do Arquivo:    my_xlcd.c
 * Dependencias:       Veja arquivo "my_xlcd.h"
 * Processador:         PIC18F4550
 * Opção de Clock:      HS 20MHz (externo) - CPU: 48MHz   
 * Compilador:           C18 v3.20 ou superior
 * Empresa:           PICMINAS - Axoon - UFMG
 *
 * Plataforma:         Kit PICMINAS v3.0
 *
 * Autor:            M.Sc. Henrique Resende Martins
 *                   Mauricio Ferrari Santos Corrêa
 * Data:            v1 - 15/Fev/2009
 *                  v2 - 28/Abr/2009
 *                  v3 - 16/Jun/2009
 *                  v4 - 18/Nov/2009
 *                  v5 - 28/fev/2010 (Bruno S. Avelar)
 *
 * Descrição:         Modificação da biblioteca xlcd.h forncedida com o compilador
 *                  C18 da Microchip. A biblioteca xlcd.h trata da comunicação
 *                  com display de LCD por meio de 4-bits (length), utilizando o
 *                  PORTB tanto para os 4 bits de dados quanto para os 3 bits de
 *                  controle (RS, RW e E).
 *                  No projeto do Kit PICMINAS o display LCD é ligado a portas
 *                  digitais diversas do PIC 18F4550. O Kit PICMINAS v3.0 utiliza
 *                  os seguintes pinos para comunicação com o display LCD:
 *                     PIC18F4550(pino):: Display LCD
 *                        RD4 (27)     ::     D4
 *                        RD5 (28)     ::     D5
 *                        RD6 (29)     ::     D6
 *                        RD7 (30)     ::     D7
 *                        RD2 (21)     ::      RS
 *                        RD3 (22)     ::     E
 *                         GND      ::     R/W
 *                  OBS: o pino R/W do display é ligado no  Kit PICMINAS ao GND
 *                  através de um resistor de pull-down, assim o LCD opera no
 *                  modo escrite(Write) o tempo todo. No entando o código C foi
 *                  escrito mostrando a imlementação onde um pino do PIC é
 *                  utilizado para a função R/W, assim comentando o inicio das
 *                  linhas correspondentes com "//não usado //".
 *  Notas:
 *      - Essa bliblioteca de rotinas foi escrita pensando em um LCD
 *        16x2 FDCC1602E implementado com o controlador SPLC780D, mas pode
 *         ser utilizado com qualquer LCD 16x2 com controladores equivalentes
 *        como, por exemplo, o controlador Hitachi HD44780 LCD controller.
 *
 *      - O usuário deve definir os seguintes itens:
 *         -- O tipo de interface de comunicação do LDC com o PIC (4 ou 8-bits):
 *            Se for o modo 4-bit, utilizar o upper nibble (nibble é metade de um Byte)
 *           , ou seja, enviar primeiro os 4 bits mais significativos (upper nibble)
 *           e depois os 4 bits menos sgnificativos (lower nibble).
 *
 *          -- Cursor e/ou Blink:
 *            O usuário poderá definir se quer visualizar cursor, blink
 *           ou nenhum dos dois.
 *         
 *         -- O sincronismo da comunicação com o LCD:
 *            As temporizações entre o envio de comandos, não foi utilizado
 *           o bit de Busy do LCD, mas sim, através de funções de atraso.
 *           A função utilizada foi a Delay10KTCYx() da bilioteca padrão C18
 *           delays.h que aparece na seção INCLUDE deste arquivo.
 *            Os tempos de delay escolhidos estão colocados nos defines:
 *           DELAY_SINC e DELAY_INICIO, que foram ecolhidos bem acima do
 *           tempo mínimo requerido pelo display de LCD (5ms o de sincronismo e
 *           15ms o inicial).
 *****************************************************************************/


/** I N C L U D E S **********************************************************/
#include "my_xlcd.h"


/** F U N C O E S ************************************************************/

/******************************************************************************
 * Funcao:      void OpenXLCD(void)
 * Entrada:      Nenhuma (void)
 * Saída:      Nenhuma (void)
 * Descrição:    Configura portas do PIC 18F4550 que estão conectadas ao
 *            display LCD como saida. Essa rotina é baseada no controlador
 *            de LCD Hitachi HD44780. Configura os parametros de comunicação
 *            com o display, tais como:
 *               - modo de operação (4 ou 8 data bits)
 *               - tipo de cursor
 *               - tamanho da fonte
 *            Ao final da configuração limpa o display.
 *
 *****************************************************************************/
void OpenXLCD(void)
{
// Configura as portas digitais do PIC que serão utilizadas na comunicação com como
// o display LCD alfa-numerico

// Configura todas as 13 portas analógicas ANx (portas do conversor A/D) como pinos digitais
   ADCON1 |= 0x0F;            // Todos os pinos como digital
// No PIC18F4550 temos:
// AN0=RA0
// AN1=RA1
// AN2=RA2
// AN3=RA3
// AN4=RA5
// AN5=RE0
// AN6=RE1
// AN7=RE2
// AN8=RB2
// AN9=RB3
// AN10=RB1
// AN11=RB4
// AN12=RB0

   // Configura os pinos de controle (RW,RS,E) como saída.
//não usado //    TRIS_RW = 0;
   TRIS_RS = 0;
   TRIS_E = 0;

   // Configura os pinos de dados (D4,D5,D6,D7) como saída.
   TRIS_D4=0;
   TRIS_D5=0;
   TRIS_D6=0;
   TRIS_D7=0;

   E_PIN =  0;    // Desabilita a leitura até que as funções a habilitem novamente.
//não usado //    RW_PIN = 0;    // Seleciona sempre o modo de escrita no LCD

// ESCREVE NOS REGISTRADORES DE COMANDO 3 VEZES SEGUIDAS A PALAVRA 0b0011XXXX DE ACORDO COM
// O DATASHEET DO CONTROLADOR DO LCD UTILIZADO (SPLC789D CONTROLLER) -> PG.11.
   // Configura os bits de controle RS e RW para escrita (RW=0) nos reg. de instrucao (RS=0)
//não usado //   RW_PIN = 0;                   
   RS_PIN = 0;
   
   Delay10KTCYx(DELAY_INICIO);   // Delay de aproximadamente 30ms para sincronismo. Maior que o DELAY_SINC.

   // PRIMEIRA VEZ
   // Joga o valor 0b0011 no Nible (meio byte) mais significativo. Os outros serão Don't Care
   D4=0;
   D5=1;
   D6=0;
   D7=0;

   // Espera aproximadamente 8ms para os valores nos pinos do PIC estabilizarem.
    Delay10KTCYx(DELAY_SINC);   // Tem de ser maior que o Tsp1 (Address Setup Time = 40ns) do diagrama 6.5.6 do datasheet do controller
   // Autoriza a escrita
   E_PIN = 1;               // Sinal de Início da escrita de dados
    Delay10KTCYx(DELAY_SINC);   // Tem de ser maior que o Tpw ('E' Pulse Width = 230ns) do diagrama 6.5.6 do datasheet do controller
   E_PIN = 0;
   Delay10KTCYx(DELAY_SINC);   // Tem de ser maior que o Tpw ('E' Pulse Width = 230ns) do diagrama 6.5.6 do datasheet do controller
   
   // SEGUNDA VEZ
   // Joga o valor 0b0011 no Nible (meio byte) mais significativo. Os outros seram DontCare
   D4=0;
   D5=1;
   D6=0;
   D7=0;

   // Espera aproximadamente 8ms para os valores nos pinos do PIC estabilizarem.
    Delay10KTCYx(DELAY_SINC);   // Tem de ser maior que o Tsp1 (Address Setup Time = 40ns) do diagrama 6.5.6 do datasheet do controller
   // Autoriza a escrita
   E_PIN = 1;               // Sinal de Início da escrita de dados
    Delay10KTCYx(DELAY_SINC);   // Tem de ser maior que o Tpw ('E' Pulse Width = 230ns) do diagrama 6.5.6 do datasheet do controller
   E_PIN = 0;
   Delay10KTCYx(DELAY_SINC);   // Tem de ser maior que o Tpw ('E' Pulse Width = 230ns) do diagrama 6.5.6 do datasheet do controller

   // TERCEIRA VEZ
   // Joga o valor 0b0011 no Nible (meio byte) mais significativo. Os outros seram DontCare
   D4=1;
   D5=1;
   D6=0;
   D7=0;

   // Espera aproximadamente 8ms para os valores nos pinos do PIC estabilizarem.
    Delay10KTCYx(DELAY_SINC);   // Tem de ser maior que o Tsp1 (Address Setup Time = 40ns) do diagrama 6.5.6 do datasheet do controller
   // Autoriza a escrita
   E_PIN = 1;               // Sinal de Início da escrita de dados
    Delay10KTCYx(DELAY_SINC);   // Tem de ser maior que o Tpw ('E' Pulse Width = 230ns) do diagrama 6.5.6 do datasheet do controller
   E_PIN = 0;
   Delay10KTCYx(DELAY_SINC);   // Tem de ser maior que o Tpw ('E' Pulse Width = 230ns) do diagrama 6.5.6 do datasheet do controller

// ENVIA AS CONFIGURAÇÕES PARA O LCD

   WriteCmdXLCD(0b00101000);   // Set 2 lines, font 5x8 Dots 
   WriteCmdXLCD(0b00001000);   // Display OFF/Cursor OFF/Blink OFF
   WriteCmdXLCD(0b00000001);   // Clear display
   WriteCmdXLCD(0b00000111);   // Entry mode set
   WriteCmdXLCD(0b00001110);   // Display ON
   WriteCmdXLCD(0b00000110);   // Set Display data ram address to 0

   return;
}

/******************************************************************************
 * Funcao:      void SetDDRamAddr(unsigned char DDaddr)
 * Entrada:      DDaddr: endereço da memoria de dados do display que se deseja apontar
 * Saída:      Nenhuma (void)
 * Descrição:    (Set the Display Data RAM Address)
 *            Essa rotina seta o endereço da memoria RAM de dados do
 *            display LCD para o endereço   que se deseja escrever um caracter
 *            usando a função WriteDataXLCD().
 *****************************************************************************/
void SetDDRamAddr(unsigned char DDaddr)
{
// AJUSTA OS BITS DE CONTROLE
//não usado //   RW_PIN = 0;      // Habilita Escrita
   RS_PIN = 0;      // Seleciona os Registradores de Instrução
   D7 = 1;   
// NIBLE HIGH
   if(DDaddr&0b00010000){D4=1;}
   else {D4=0;}
   if(DDaddr&0b00100000){D5=1;}
   else {D5=0;}
   if(DDaddr&0b01000000){D6=1;}
   else {D6=0;}
   
   Delay10KTCYx(DELAY_SINC);
   E_PIN = 1;               // Clock the cmd and address in
    Delay10KTCYx(DELAY_SINC);
   E_PIN = 0;

// NIBLE LOW
   if(DDaddr&0b00000001){D4=1;}
   else {D4=0;}
   if(DDaddr&0b00000010){D5=1;}
   else {D5=0;}
   if(DDaddr&0b00000100){D6=1;}
   else {D6=0;}
   if(DDaddr&0b00001000){D7=1;}
   else {D7=0;}

    Delay10KTCYx(DELAY_SINC);
   E_PIN = 1;               // Clock the cmd and address in
    Delay10KTCYx(DELAY_SINC);
   E_PIN = 0;

   return;
}

/******************************************************************************
 * Funcao:      void WriteCmdXLCD(unsigned char cmd)
 * Entrada:      cmd: comando que será enviado para o LCD
 * Saída:      Nenhuma (void)
 * Descrição:    (Write a command to the LCD)
 *            Escreve um comando no display de LCD.
 *****************************************************************************/
void WriteCmdXLCD(unsigned char cmd)
{
 // AJUSTA OS BITS DE CONTROLE
//não usado //   RW_PIN = 0;      // Habilita Escrita
   RS_PIN = 0;      // Escrita nos Registradores de Instrução

 // NIBLE HIGH
   if(cmd&0b00010000){D4=1;}
   else {D4=0;}
   if(cmd&0b00100000){D5=1;}
   else {D5=0;}
   if(cmd&0b01000000){D6=1;}
   else {D6=0;}
   if(cmd&0b10000000){D7=1;}
   else {D7=0;}
   
   Delay10KTCYx(DELAY_SINC);
   E_PIN = 1;               // Clock the cmd and address in
    Delay10KTCYx(DELAY_SINC);
   E_PIN = 0;

 // NIBLE LOW
   if(cmd&0b00000001){D4=1;}
   else {D4=0;}
   if(cmd&0b00000010){D5=1;}
   else {D5=0;}
   if(cmd&0b00000100){D6=1;}
   else {D6=0;}
   if(cmd&0b00001000){D7=1;}
   else {D7=0;}   

   Delay10KTCYx(DELAY_SINC);   
   E_PIN = 1;               // Clock nibble into LCD
    Delay10KTCYx(DELAY_SINC);
   E_PIN = 0;

   return;
}
/******************************************************************************
 * Funcao:      void WriteDataXLCD(unsigned char data)
 * Entrada:      data: Byte de dados para ser escrito na memoria RAM do LCD
 * Saída:      Nenhuma (void)
 * Descrição:    (Write a Data byte to the LCD)
 *            Essa rotina escreve um byte de dados na posição da memoria RAM setada
 *             anteriormente com a função SetDDRamAddr().
 *****************************************************************************/
void WriteDataXLCD(unsigned char data)
{
// AJUSTA OS BITS DE CONTROLE
//não usado //   RW_PIN = 0;      // Habilita Escrita
   RS_PIN = 1;      // Escrita nos Registradores de Dados

// NIBLE HIGH
   if(data&0b00010000){D4=1;}
   else {D4=0;}
   if(data&0b00100000){D5=1;}
   else {D5=0;}
   if(data&0b01000000){D6=1;}
   else {D6=0;}
   if(data&0b10000000){D7=1;}
   else {D7=0;}
   
   Delay10KTCYx(DELAY_SINC);
   E_PIN = 1;               // Clock the cmd and address in
    Delay10KTCYx(DELAY_SINC);
   E_PIN = 0;

// NIBLE LOW
   if(data&0b00000001){D4=1;}
   else {D4=0;}
   if(data&0b00000010){D5=1;}
   else {D5=0;}
   if(data&0b00000100){D6=1;}
   else {D6=0;}
   if(data&0b00001000){D7=1;}
   else {D7=0;}   

   Delay10KTCYx(DELAY_SINC);   
   E_PIN = 1;               // Clock nibble into LCD
    Delay10KTCYx(DELAY_SINC);
   E_PIN = 0;

   return;
}

/******************************************************************************
 * Funcao:      void putsXLCD(char *buffer)
 * Entrada:      *buffer: apontador para string na memoria de dados(RAM)
 * Saída:      Nenhuma (void)
 * Descrição:    Essa rotina copia uma string terminada com caracter nulo
 *            da memoria de dados do microcontrolador para o display de LCD.
 *            A string apontada por *buffer é copiada no display a partir da
 *            posição da memoria RAM do display escolhida com a função
 *            SetDDRamAddr().
 *****************************************************************************/
void putsXLCD(char *buffer)
{
        while(*buffer)                  // escreve dados no LCD ate achar caracter nulo
        {
                WriteDataXLCD(*buffer); // escreve caracter no LCD
                buffer++;              // incrementa apontador
        }
}

/******************************************************************************
 * Funcao:      void putrsXLCD(const rom char *buffer)
 * Entrada:      *buffer: apontador para string na memoria de programa(ROM)
 * Saída:      Nenhuma (void)
 * Descrição:    Essa rotina copia uma string terminada com caracter nulo
 *            da memoria de programa do microcontrolador para o display de LCD.
 *            A string apontada por *buffer é copiada no display a partir da
 *            posição da memoria RAM do display escolhida com a função
 *            SetDDRamAddr().
 *****************************************************************************/
void putrsXLCD(const rom char *buffer)
{
        while(*buffer)                  // escreve dados no LCD ate achar caracter nulo
        {
                WriteDataXLCD(*buffer); // escreve caracter no LCD
                buffer++;              // incrementa apontador
        }
}

Então agora eu irei comentar apenas as partes mais complicadas e importantes.
No arquivo my_xlcd.h existem os defines dos pinos utilizados de acordo com o KIT PIC MINAS V3.0. Caso esteja usando outro hardware você pode precisar mudar estes defines.
Para enviar dois nibbles, seja no envio de comandos ou dados dividimos o byte da seguinte forma:
Código:

// NIBLE HIGH
   if(BYTE&0b00010000){D4=1;}
   else {D4=0;}
   if(BYTE &0b00100000){D5=1;}
   else {D5=0;}
   if(BYTE &0b01000000){D6=1;}
   else {D6=0;}
   
Envia o nibble high.

// NIBLE LOW
   if(BYTE &0b00000001){D4=1;}
   else {D4=0;}
   if(BYTE &0b00000010){D5=1;}
   else {D5=0;}
   if(BYTE &0b00000100){D6=1;}
   else {D6=0;}
   if(BYTE &0b00001000){D7=1;}
   else {D7=0;}

Envia o nibble low.

1.0 Função: void OpenXLCD(void);
Esta função configura as portas utilizadas como saídas digitais e faz a inicialização do LCD.

Para envio de dados ou comandos é feito:
Código:
E_PIN = 1;
Delay10KTCYx(DELAY_SINC);
E_PIN = 0;
Delay10KTCYx(DELAY_SINC);
No final desta função ele configura o display para duas linhas com fonte 5x8 dots, cursor e blink off.

1.1 Função void SetDDRamAddr(unsigned char DDaddr)
A função seta o endereço da memoria RAM de dados do display LCD para o endereço que se deseja escrever um caracter usando a função WriteDataXLCD().

Primeiro devemos dividir o byte de configuração em dois nibles. Isto é feito :
Código:
// NIBLE HIGH
   if(DDaddr&0b00010000){D4=1;}
   else {D4=0;}
   if(DDaddr&0b00100000){D5=1;}
   else {D5=0;}
   if(DDaddr&0b01000000){D6=1;}
   else {D6=0;}
   
Envia o nibble high.

// NIBLE LOW
   if(DDaddr&0b00000001){D4=1;}
   else {D4=0;}
   if(DDaddr&0b00000010){D5=1;}
   else {D5=0;}
   if(DDaddr&0b00000100){D6=1;}
   else {D6=0;}
   if(DDaddr&0b00001000){D7=1;}
   else {D7=0;}

Envia o nibble low.

Lembre-se que cada “célula” do LCD possui um endereço seguindo a tabela abaixo:



1.2 – Função void WriteCmdXLCD(unsigned char cmd)

A função escreve um comando para o LCD.
O pino RS_PIN é colocado em 0 inciando que é um comando.

1.3 – Função void WriteDataXLCD(unsigned char data)

Identica a função WriteCmdLCD(unsigned char cmd) exeto que RS_PIN é colocado em 1 avisando que é uma escrita nos registradores de dados do LCD.

1.4 – Função void putsXLCD(char *buffer)

Escreve o vetor de caracter recebido como parametro no LCD.
A string em linguagem C deve terminar em ‘\n’. A função percorre a string elemento a elemento chamando a funçao de escrever um caractere na tela (WriteDataXLCD(unsigned char data)) até encontrar o ‘/n’ onde ela para.

1.5 – Função void putrsXLCD(const rom char *buffer)

Funciona de maneira identica a putsXLCD(char *buffer), mas recebe como parametro de entrada uma string que esteja na memoria de programa do microcontrolador.

Comentários finais:

Estou passando o código fonte da biblioteca neste post para vocês. Peço para que ao utilizarem a biblioteca deêm os devidos créditos para seus criadores.

Aproveitem.

Bruno S. Avelar
avatar
Bruno S. Avelar
Admin

Mensagens : 74
Data de inscrição : 26/07/2009
Idade : 33
Localização : Belo Horizonte MG

Ver perfil do usuário http://picminas.forumeiros.com

Voltar ao Topo Ir em baixo

URGENTE!!!Mostrar no LCD uma variavel

Mensagem  espinal em Qua Maio 19, 2010 8:18 pm

Ola estou fazendo um trabalho no SENAI e preciso de fazer uma programação e estamos usando a linguagem C. porém esbarramos em um problema, precisamos mostrar uma variavel no LCD e não estamos conseguindo.
Por Favor me respondam como posso fazer isso.

espinal

Mensagens : 3
Data de inscrição : 19/05/2010

Ver perfil do usuário

Voltar ao Topo Ir em baixo

Re: Uso do LCD (tutorial)

Mensagem  Bruno S. Avelar em Qui Maio 20, 2010 7:28 am

Olá Espinal,

Eu não sei qual microcontrolador e qual compilador e quais portas você está usando no seu projeto então vou tentar responder de forma genérica ok?. Aí se você tiver dificuldades você posta novamente a dúvida.

Existe um post aqui no forum sobre como trabalhar com LCD em: http://picminas.forumeiros.com/firmware-f2/uso-do-lcd-tutorial-t25.htm. Realmente este post não fala como mostrar uma variável no LCD. Mas é bem tranqüilo.

Em geral, você manda uma string (vetor de caracteres) para ser escrita no LCD. Então temos que montar esta string com a variável que você deseja por exemplo: "Temperatura = 25" onde 25 é um numero inteiro dentro de uma variável. Se sua variável for inteira como o exemplo é mais fácil se for float (ponto flutuante, com casa decimal) você vai ter que fazer uma lógica um pouco mais apurada.

Caso sua variável seja um int:
A maior parte dos compiladores possui bibliotecas padrões do compilador. Em geral eles possuem uma que chama string.h. Você vai ter que usar a função itoa() para converter o número de int para ascII (ou vetor de char) e usar a função strcat() para concatenar duas strings. Em resumo é usar itoa() para transformar o inteiro em string e concatená-lo na sua string então mandar escrever no LCD.
Abaixo um exemplo usando o compilador C18:

Código:

int  numInt; // número inteiro que voce deseja escrever no LCD
char strNum[4]; // String para armazenar o número em ASCII
char str[17] = "temperatura = "; // String que será mandado para o LCD
itoa(numInt,strNum);
strcat(str,strNum);

SetDDRamAddr(0x00);
putsXLCD(str);

Caso a variável seja um float:
Nosso compilador não possui uma função ftoa (itoa com float) . Para colocarmos o float em um string faremos:
1- Separar a parte inteira da parte decimal.
2- Converter a parte inteira com itoa para string e colocar no vetor de caracteres.
3- Acrescer o caractere ‘,’ (virgula)
4- Multiplicar a parte decimal por 100 (para duas casas decimais, por 1000 para três casas etc.)
5- Truncar o resto das casas decimais transformando em um inteiro
6- Transformar este inteiro em um string com itoa.
7- Concatenar a primeira string que possui a parte inteira com a virgula com a nova string que possui o numero decimal
8- Escrever no LCD.

Uma maneira de implementar isto está abaixo:
Código:

   int  numInt; // Parte inteira do número
   int  numDec; // Parte decimal do número
   char strNumFloat[10]; // Numero em string que será mandado para o LCD
   char strNumDec[4]; // Numero em string da parte decimal temporário.


      // 1- Dividir o número float em dois inteiros:
      numInt = Num_CAD_graus;
      numDec = (Num_CAD_graus-numInt)*100;
      // 2- Colocar numInt no string
      itoa(numInt,strNumFloat);
      // 3- Colocar a vírgula
      strcatpgm2ram(strNumFloat,",");
      // 4- Converter a numDec para string
      itoa(numDec,strNumDec);
      // 5- Concatenar a parte decimal na string      
      strcat(strNumFloat,strNumDec);
      // Escreve no display de LCD o valor da
      // temperatura.
      SetDDRamAddr(0x00);
      putsXLCD(strNumFloat);

Em outros compiladores podem ter algumas diferenças. Para saber como funciona basta dar uma lida na documentação do compilador e procurar na documentação da biblioteca (caso exista) como funcionam as funções de tratamento de strings. (itoa, strcat, strcopy etc.).

Espero ter ajudado,

Bruno S. Avelar

Ps: vou mover em breve seu post para http://picminas.forumeiros.com/firmware-f2/uso-do-lcd-tutorial-t25.htm que é o post que fala de LCD.
avatar
Bruno S. Avelar
Admin

Mensagens : 74
Data de inscrição : 26/07/2009
Idade : 33
Localização : Belo Horizonte MG

Ver perfil do usuário http://picminas.forumeiros.com

Voltar ao Topo Ir em baixo

Re: Uso do LCD (tutorial)

Mensagem  jrgob em Qui Jul 21, 2011 5:38 pm

Olá,

Sou novo aqui no forum... e preciso de uma ajuda, estou tentando implementar o código descrito aqui nesse tópico para ligar um LCD 2x20 com um pic 18f1320... Shocked

Se alguém puder me ajudar.. Very Happy

Se precisarem posto o código e o esquematico...


Abraço

jrgob

Mensagens : 2
Data de inscrição : 21/07/2011

Ver perfil do usuário

Voltar ao Topo Ir em baixo

Teste com pic 18f1320

Mensagem  jrgob em Seg Jul 25, 2011 5:38 pm

Bruno,

modifiquei a biblioteca my_xlcd.h para usar com o pic 18f1320, adicionei um led para picar e testar se o programa roda...ai ta blz, mas quando eu uso a função putsXLCD ou putrsXLCD, o programa não escreve nada no display.... Shocked

não entendo o pq disso... Question



Abraço

jrgob

Mensagens : 2
Data de inscrição : 21/07/2011

Ver perfil do usuário

Voltar ao Topo Ir em baixo

Re: Uso do LCD (tutorial)

Mensagem  brad em Seg Jan 23, 2012 1:44 pm

ola jrgob,
embora já haja algum tempo,
seria legal se voce colocasse o seu código para possível análise,
e, claro, se já resolveu conte-nos como.

brad

Mensagens : 1
Data de inscrição : 03/09/2011

Ver perfil do usuário

Voltar ao Topo Ir em baixo

Re: Uso do LCD (tutorial)

Mensagem  Conteúdo patrocinado


Conteúdo patrocinado


Voltar ao Topo Ir em baixo

Ver o tópico anterior Ver o tópico seguinte Voltar ao Topo


 
Permissão deste fórum:
Você não pode responder aos tópicos neste fórum