Analisando o controlador de LCD Hitachi HD44780
- Publicado em Eletrônica
Neste texto, analisaremos a comunicação digital entre um sistema embarcado Arduino e um display LCD alfanumérico com 2 linhas de 16 caracteres cada com controlador Hitachi HD44780 por meio de um analisador lógico com decodificador paralelo para facilitar a validação dos dados (4 bits). Conforme demais artigos referentes a outras aplicações com o Arduino, o firmware foi desenvolvido por meio do Visual Studio, com a extensão Visual Micro, e foi empregada a biblioteca padrão LiquidCrystal.
Considerações gerais
O controlador de telas de cristal líquido HD44780 alfa-numérico foi desenvolvido pela Hitachi e possui um conjunto de instruções/códigos que se estabeleceram como padrão "de fato" na comunicação entre sistemas microcontrolados e telas alfa-numéricas.
As telas de cristal líquido com controlador HD44780 podem ser interfaceadas em dois modos de transferência de dados (quatro ou oito bits) e possuem três entradas de controle: a Register Select (RS) cujo nível baixo (0V) representa uma operação de comando e um nível alto (5V) representa a transferênica de dados, Read/Write (RW) cujo nível baixo (0V) representa uma operação de escrita no controlador e o nível alto (5V) representa uma leitura e Enable (E), cujo nível baixo (0) ativa a transmissão de dados entre os dispositivos e trabalha como um sinal de sincronização. Nesta aplicação, a entrada Read/Write é configurada como escrita e o modo de transferência configurado como quatro bits.
O código-fonte do firmware para análise dessa comunicação digital consiste apenas na inicialização do LCD por meio da função lcd.begin(16,2) da biblioteca LiquidCrystal e execução em loop de um comando setCursor(0,0) para posicionamento do cursor na primeira linha e caractere, impressão de variável numérica inteira formatada por meio da configuração "%3d" (no mínimo, 3 dígitos), acréscimo unitário dessa variável, comando setCursor(0,1) para posicionamento do cursor na segunda linha e primeiro caractere, impressão da variável numérica atualizada com formatação "%3d" e posteriormente um atraso de tempo de 500ms.
Início comunicação HD44780
Por meio de um analisador lógico, configuramos o sinal Register Select (RS) na cor preta, o sinal Enable (EN) na cor marrom, o bit de dados D4 menos significativo como amarelo, o bit de dados D5 como verde, o bit de dados D6 como azul e o bit de dados D7 como roxo. Por fim, o barramento digital decodificado em um número hexadecimal ou binário referente aos quatro bits de dados para facilitar a visualização dos dados em cor marrom:
Na etapa de inicialização por instruções do controlador HD44780, composto por cerca de 10 etapas principais, visualizamos 22 pulsos no sinal Enable (E) que serão analisados a seguir, sendo que na maioria deles o sinal Register Select é configurado em nível baixo (execução de comandos e não apenas transferência de dados):
Reset
Conforme imagens abaixo, os três primeiros pulsos Enable (E) são gerados com o sinal Register Select (RS) em nível baixo, D6 e D7 em nível baixo e D4 e D5 em nível alto (D=0011b). Os três comandos são emitidos com o controlador ainda em modo de 8 bits e o mesmo simplesmente descarta os quatro bits menos significativos e conforme o datasheet do fabricante, é necessário aguardar mais de 4,1ms entre o primeiro e segundo pulsos e pelo menos 100us entre o segundo e terceiro pulsos.
Esses três comandos visam o reset e inicialização do dispositivo (os pulsos são do mesmo comprimento e a diferença apresentada se refere apenas à configuração de zoom no software do analisador lógico):
Modo de comunicação (4 bits)
Após os três pulsos Enable (E) com os bits D5 e D4 ativos (D=0011b) para o reset do controlador, visualizamos na imagem abaixo que o quatro pulso Enable (E) é emitido apenas com o bit 5 em nível alto (D=0010b) para configurar o modo de comunicação de 4 bits. Essa configuração não exige o envio de um byte completo como as demais, que demandam a transferência de dados/comandos em duas parcelas (envio de quatro bits de cada vez, sendo os bits mais significativos enviados primeiro).
Comando Function Set
O quinto e sexto pulsos Enable (E) especificam o número de linhas (D=0010b) e a fonte dos caracteres (D=0000b), compondo na verdade a configuração de 8 bits "001DNF**" (instrução conhecida como "Function Set"), sendo "D" a especificação do tamanho dos dados (0 representa 4 bits), "N" o número de linhas, "F" a fonte dos caracteres e os astericos indicam que o estado desses bits é irrelevante. Essa função deve ser executada apenas neste momento da inicialização e essas configurações não poderão ser refeitas posteriormente.
Display Control
O sétimo (D=0000b) e oitavo (D=1100b) pulsos Enable (E) representam o código com dados "00001DCBb", sendo que o bit "D" ativa (1) ou desativa (0) o display inteiro, o bit "C" ativa (1) ou desativa o cursor (0) e o bit "B" configura o cursor para piscar (1) ou não (0).
Clear Display
O nono (D=0000b) e décimo (D=0001b) pulsos Enable (E) representam o código com dados "00000001b", que apaga a tela e retorna o curso para a posição inicial de endereço 0.
Entry Mode Set
O décimo primeiro (D=0000b) e décimo segundo (D = 0110b) pulsos Enable (E) representam o comando "entry mode set" cujos dados são formatados como "000001ISb", sendo o bit "I" utilizado para definir se uma operação de escrita ou leitura irá incrementar (I = 1) ou decrementar (I = 0) o endereço atual do cursor/memória e o bit "S" utilizado para especificar o deslocamento de todos os dados em relação ao cursor nos casos de entrada de dados, sendo que S=0 determina o deslocamento apenas do cursor e não da tela inteira (comportamento usual):
A partir deste instante, o dispositivo já pode ser considerado devidamente iniciado conforme especificações do datasheet.
Todavia, para a nossa supresa, constatamos que o dispositivo é novamente inicializado devido à existência de três comandos "0011b" e posteriores comandos de configuração. A princípio, pensamos que se tratava de alguma instabilidade do botão de reset do sistema embarcado Arduino, mas analisando o código-fonte do firmware, verificamos que o construtor da biblioteca LiquidCrystal faz uma chamada à função begin(16,1), enquanto precisamos chamar essa função também no setup para especificar um LCD com 16 caracteres mas 2 linhas [begin(16,2)], o que explica a sequência de inicialização detectada por meio do analisador lógico:
Para demonstrar esse fato, alteramos o código-fonte do firmware suprimindo a chamada à função begin(16,2) e constatamos a ocorrência de apenas uma sequência de inicialização do dispositivo que foi explanada anteriormente:
Escrevendo dados na DDRAM do HD44780
Após a execução dos bits da imagem anterior, ainda há um comando de configuração "Entry Mode set" já descrito anteriormente e somente após o mesmo, temos o comando "Set DDRAM address" com o código "1XXXXXXXb", sendo a combinação "XXXXXXXb" referente ao endereço da memória DDRAM, que neste caso é o endereço "0000000b" referente ao primeiro caractere da primeira linha. Esse comando tem a função de especificar a posição para escrita de dados, sendo que após essa escrita, o endereço será atualizado para a próxima posição conforme a configuração de "cursor/display shift" já efetuada.
Após a configuração do endereço DDRAM, visualizamos que são escritos três dígitos 001, conforme a tabela de códigos de caracteres especificada no datasheet e com reprodução parcial referente aos códigos de números abaixo:
Dígito | Código em binário | Código em hexadecimal |
0 | 00110000 | 0x30 |
1 | 00110001 | 0x31 |
2 | 00110010 | 0x32 |
3 | 00110011 | 0x33 |
4 | 00110100 | 0x34 |
5 | 00110101 | 0x35 |
6 | 00110110 | 0x36 |
7 | 00110111 | 0x37 |
8 | 00111000 | 0x38 |
9 | 00111001 | 0x39 |
A seguir, temos a configuração do endereço DDRAM "11000000b" referente à segunda linha do display e a escrita do número "001":
Em loop, visualizamos que após o período de tempo de atraso de loop de 500ms, o firmware começa a escrever continuamente no display a variável com 3 dígitos em ambas as linhas (linha 1 e 2):
Temporização
Conforme supramencionado, entre as operações de escrita no display em loop, o código do firmware estabelece um atraso de tempo de 500ms, o qual foi confirmado por meio do cursor a seguir:
Em relação aos pulsos no sinal Enable (E), conforme o datasheet, o atraso de tempo deve ser no mínimo de 37 us, mas a biblioteca foi programada com um atraso de tempo nominal de 100us. Associado ao atraso no processamento dos demais comandos, tempos a distância de 173,66us entre os pulsos Enable(E):