O módulo de display TFT LCD touchscreen de 2.4 polegadas é uma opção popular para projetos Arduino que requerem uma interface gráfica colorida e interativa. Este módulo é compatível diretamente com placas Arduino UNO e Mega2560, eliminando a necessidade de fiação complexa e simplificando a prototipagem. Ele oferece uma resolução de 320x240 pixels com suporte a 65 mil cores (16-bit RGB), proporcionando uma visualização clara e vibrante. A comunicação é realizada através de um barramento paralelo de 8 bits, o que garante uma taxa de atualização mais rápida em comparação com as interfaces SPI seriais. Além disso, o módulo possuii um conversor de nível integrado (5V/3.3V) e um slot para cartão SD para expansão de armazenamento.
Características Principais do Módulo
- Compatibilidade direta com Arduino UNO R3 e Mega2560.
- Resolução de 320x240 pixels.
- Suporte a 16-bit RGB (65.536 cores).
- Interface de barramento paralelo de 8 bits para alta velocidade.
- Conversor de nível 5V/3.3V integrado.
- Slot para cartão SD integrado para armazenamento de dados ou imagens.
- Disponibilidade de bibliotecas e exemplos para Arduino.
Conexão com Arduino UNO
Para o Arduino UNO, a conexão direta utiliza os seguintes pinos:
| Pino do Módulo LCD | Pino Arduino Uno |
|---|---|
| LCD_CS | A3 |
| LCD_CD (RS) | A2 |
| LCD_WR | A1 |
| LCD_RD | A0 |
| LCD_RST | A4 |
| SD_SS | 10 |
| SD_DI | 11 |
| SD_DO | 12 |
| SD_SCK | 13 |
| LCD_D0 | 8 |
| LCD_D1 | 9 |
| LCD_D2 | 2 |
| LCD_D3 | 3 |
| LCD_D4 | 4 |
| LCD_D5 | 5 |
| LCD_D6 | 6 |
| LCD_D7 | 7 |
Exemplo de Código 1: Controle de Baixo Nível e Desenho de Formas
Este exemplo demonstra o controle direto do display LCD utilizando manipulação de portas e implemanta funções básicas de desenho, como linhas e retângulos, além de preenchimento de tela. Ele ilustra como interagir com o controlador do display em um nível mais fundamental.
// Definições dos pinos de controle do LCD no Arduino Uno
#define PINO_LEITURA_DADO A0 // RD - Read Data
#define PINO_ESCRITA_DADO A1 // WR - Write Data
#define PINO_REG_DADO A2 // RS - Register Select (Data/Command)
#define PINO_CHIP_SELEC A3 // CS - Chip Select
#define PINO_RESET A4 // RST - Reset
// Função de baixo nível para escrever um byte no barramento de dados do LCD
void escreverBarramentoDados(unsigned char byteDado) {
// Mapeia os bits 2-7 do byteDado para os bits 2-7 do PORTD (pinos digitais 2-7)
PORTD = (PORTD & B00000011) | ((byteDado) & B11111100);
// Mapeia os bits 0-1 do byteDado para os bits 0-1 do PORTB (pinos digitais 8-9)
PORTB = (PORTB & B11111100) | ((byteDado) & B00000011);
// Pulsa o pino de escrita (WR) para registrar o dado no LCD
digitalWrite(PINO_ESCRITA_DADO, LOW);
digitalWrite(PINO_ESCRITA_DADO, HIGH);
}
// Envia um comando para o controlador LCD
void enviarComandoLCD(unsigned char comando) {
// Define o pino RS (Data/Command) para modo comando (LOW)
*(portOutputRegister(digitalPinToPort(PINO_REG_DADO))) &= ~digitalPinToBitMask(PINO_REG_DADO);
escreverBarramentoDados(comando);
}
// Envia um dado para o controlador LCD
void enviarDadoLCD(unsigned char dado) {
// Define o pino RS (Data/Command) para modo dado (HIGH)
*(portOutputRegister(digitalPinToPort(PINO_REG_DADO))) |= digitalPinToBitMask(PINO_REG_DADO);
escreverBarramentoDados(dado);
}
// Envia um comando seguido por um dado
void escreverComandoDadoLCD(unsigned char comando, unsigned char dado) {
enviarComandoLCD(comando);
enviarDadoLCD(dado);
}
// Define a área de endereçamento para operações de escrita (coordenadas X e Y)
void definirAreaEndereco(unsigned int xInicial, unsigned int yInicial, unsigned int xFinal, unsigned int yFinal) {
enviarComandoLCD(0x2a); // Comando de set column address
enviarDadoLCD(xInicial >> 8); // Coordenada X inicial (byte alto)
enviarDadoLCD(xInicial); // Coordenada X inicial (byte baixo)
enviarDadoLCD(xFinal >> 8); // Coordenada X final (byte alto)
enviarDadoLCD(xFinal); // Coordenada X final (byte baixo)
enviarComandoLCD(0x2b); // Comando de set page address
enviarDadoLCD(yInicial >> 8); // Coordenada Y inicial (byte alto)
enviarDadoLCD(yInicial); // Coordenada Y inicial (byte baixo)
enviarDadoLCD(yFinal >> 8); // Coordenada Y final (byte alto)
enviarDadoLCD(yFinal); // Coordenada Y final (byte baixo)
enviarComandoLCD(0x2c); // Comando de write to RAM (ativa escrita de pixel)
}
// Inicializa o painel LCD com uma sequência de comandos específicos do controlador ILI9341
void inicializarLCD() {
// Sequência de reset de hardware
digitalWrite(PINO_RESET, HIGH);
delay(5);
digitalWrite(PINO_RESET, LOW);
delay(15);
digitalWrite(PINO_RESET, HIGH);
delay(15);
// Desativa Chip Select (CS) e Write (WR) antes de iniciar
digitalWrite(PINO_CHIP_SELEC, HIGH);
digitalWrite(PINO_ESCRITA_DADO, HIGH);
digitalWrite(PINO_CHIP_SELEC, LOW); // Ativa Chip Select
// Configurações de inicialização do ILI9341
enviarComandoDadoLCD(0xCB, 0x39); enviarDadoLCD(0x2C); enviarDadoLCD(0x00); enviarDadoLCD(0x34); enviarDadoLCD(0x02);
enviarComandoDadoLCD(0xCF, 0x00); enviarDadoLCD(0XC1); enviarDadoLCD(0X30);
enviarComandoDadoLCD(0xE8, 0x85); enviarDadoLCD(0x00); enviarDadoLCD(0x78);
enviarComandoDadoLCD(0xEA, 0x00); enviarDadoLCD(0x00);
enviarComandoDadoLCD(0xED, 0x64); enviarDadoLCD(0x03); enviarDadoLCD(0X12); enviarDadoLCD(0X81);
enviarComandoDadoLCD(0xF7, 0x20);
enviarComandoDadoLCD(0xC0, 0x23); // Power Control 1
enviarComandoDadoLCD(0xC1, 0x10); // Power Control 2
enviarComandoDadoLCD(0xC5, 0x3e); // VCOM Control 1
enviarDadoLCD(0x28);
enviarComandoDadoLCD(0xC7, 0x86); // VCOM Control 2
enviarComandoDadoLCD(0x36, 0x08); // Memory Access Control (BGR=1, MX=0, MY=0, MV=0)
enviarComandoDadoLCD(0x3A, 0x55); // Pixel Format Set (16-bit/pixel)
enviarComandoDadoLCD(0xB1, 0x00); // Frame Rate Control
enviarDadoLCD(0x18);
enviarComandoDadoLCD(0xB6, 0x08); // Display Function Control
enviarDadoLCD(0x82);
enviarDadoLCD(0x27);
enviarComandoLCD(0x11); // Exit Sleep Mode
delay(120);
enviarComandoLCD(0x29); // Display ON
enviarComandoLCD(0x2c); // Write to RAM (prepara para receber dados de pixel)
}
// Desenha uma linha horizontal
void desenharLinhaHorizontal(unsigned int x, unsigned int y, unsigned int comprimento, unsigned int cor) {
definirAreaEndereco(x, y, x + comprimento - 1, y);
for (unsigned int i = 0; i < comprimento; i++) {
enviarDadoLCD(cor >> 8); // Bits mais significativos da cor (RGB565)
enviarDadoLCD(cor); // Bits menos significativos da cor (RGB565)
}
}
// Desenha uma linha vertical
void desenharLinhaVertical(unsigned int x, unsigned int y, unsigned int comprimento, unsigned int cor) {
definirAreaEndereco(x, y, x, y + comprimento - 1);
for (unsigned int i = 0; i < comprimento; i++) {
enviarDadoLCD(cor >> 8);
enviarDadoLCD(cor);
}
}
// Desenha um retângulo vazado
void desenharRetanguloVazado(unsigned int x, unsigned int y, unsigned int largura, unsigned int altura, unsigned int cor) {
desenharLinhaHorizontal(x , y , largura, cor);
desenharLinhaHorizontal(x , y + altura, largura, cor);
desenharLinhaVertical(x , y , altura, cor);
desenharLinhaVertical(x + largura, y , altura, cor);
}
// Desenha um retângulo preenchido
void desenharRetanguloPreenchido(unsigned int x, unsigned int y, unsigned int largura, unsigned int altura, unsigned int cor) {
for (unsigned int i = 0; i < altura; i++) {
desenharLinhaHorizontal(x , y + i, largura, cor);
}
}
// Preenche a tela inteira com uma cor específica (RGB565)
void limparTelaLCD(unsigned int cor) {
digitalWrite(PINO_CHIP_SELEC, LOW);
definirAreaEndereco(0, 0, 239, 319); // Display 240x320 pixels
for (unsigned int i = 0; i < 320; i++) { // Iterar pelas linhas
for (unsigned int m = 0; m < 240; m++) { // Iterar pelas colunas
enviarDadoLCD(cor >> 8);
enviarDadoLCD(cor);
}
}
digitalWrite(PINO_CHIP_SELEC, HIGH);
}
void setup() {
Serial.begin(9600);
// Configura todos os pinos de dados e controle como OUTPUT
for (int p = 2; p <= 9; p++) pinMode(p, OUTPUT); // Pinos D0-D7
pinMode(PINO_LEITURA_DADO, OUTPUT);
pinMode(PINO_ESCRITA_DADO, OUTPUT);
pinMode(PINO_REG_DADO, OUTPUT);
pinMode(PINO_CHIP_SELEC, OUTPUT);
pinMode(PINO_RESET, OUTPUT);
// Garante que os pinos de controle estejam em estado HIGH inicialmente (inativos)
digitalWrite(PINO_LEITURA_DADO, HIGH);
digitalWrite(PINO_ESCRITA_DADO, HIGH);
digitalWrite(PINO_REG_DADO, HIGH);
digitalWrite(PINO_CHIP_SELEC, HIGH);
digitalWrite(PINO_RESET, HIGH);
inicializarLCD(); // Inicializa o painel LCD
Serial.println("Display TFT LCD de 2.4 polegadas pronto.");
}
void loop() {
// Cores 16-bit RGB565: Vermelho (0xF800), Verde (0x07E0), Azul (0x001F)
limparTelaLCD(0xF800); // Preenche a tela com vermelho
delay(1000);
limparTelaLCD(0x07E0); // Preenche a tela com verde
delay(1000);
limparTelaLCD(0x001F); // Preenche a tela com azul
delay(1000);
// Desenha retângulos vazados aleatórios
Serial.println("Desenhando retângulos vazados...");
for (int i = 0; i < 15; i++) {
unsigned int x = random(0, 180); // Garante que a origem do retângulo esteja na tela
unsigned int y = random(0, 260);
unsigned int largura = random(20, 60); // Largura entre 20 e 60 pixels
unsigned int altura = random(20, 60); // Altura entre 20 e 60 pixels
unsigned int cor = random(65535); // Cor 16-bit aleatória
desenharRetanguloVazado(x, y, largura, altura, cor);
Serial.print("Retângulo vazado #"); Serial.println(i + 1);
delay(50);
}
delay(2000);
// Desenha retângulos preenchidos aleatórios
Serial.println("Desenhando retângulos preenchidos...");
for (int i = 0; i < 8; i++) {
unsigned int x = random(0, 180);
unsigned int y = random(0, 260);
unsigned int largura = random(20, 60);
unsigned int altura = random(20, 60);
unsigned int cor = random(65535);
desenharRetanguloPreenchido(x, y, largura, altura, cor);
Serial.print("Retângulo preenchido #"); Serial.println(i + 1);
delay(100);
}
delay(3000);
}
Exemplo de Código 2: Uso de Biblioteca Simplificada
Este exemplo utiliza as bibliotecas LCDWIKI_GUI.h e LCDWIKI_KBV.h, que fornecem uma camada de abstração para facilitar o controle do display. Com estas bibliotecas, operações como inicialização e preenchimento de tela tornam-se muito mais simples, abstraindo os detalhes de baixo nível.
#include <LCDWIKI_GUI.h> // Biblioteca para funções gráficas
#include <LCDWIKI_KBV.h> // Biblioteca para drivers de hardware específicos (ex: ILI9341)
// Instancia o objeto do display LCD para um controlador ILI9341
// Parâmetros: Modelo IC, CS, RS (CD), WR, RD, RST
LCDWIKI_KBV meuDisplay(ILI9341, A3, A2, A1, A0, A4);
void setup() {
Serial.begin(9600);
meuDisplay.Init_LCD(); // Inicializa o display LCD
Serial.print("ID do controlador LCD: 0x");
Serial.println(meuDisplay.Read_ID(), HEX); // Lê e imprime o ID do controlador em formato hexadecimal
meuDisplay.Fill_Screen(0xFFFF); // Preenche a tela com branco (0xFFFF é branco em RGB565)
delay(1000);
}
void loop() {
// Preenche a tela sequencialmente com preto, branco, vermelho, verde e azul
// Usando componentes RGB (0-255)
meuDisplay.Fill_Screen(0, 0, 0); // Preto
delay(1500);
meuDisplay.Fill_Screen(255, 255, 255); // Branco
delay(1500);
meuDisplay.Fill_Screen(255, 0, 0); // Vermelho
delay(1500);
meuDisplay.Fill_Screen(0, 255, 0); // Verde
delay(1500);
meuDisplay.Fill_Screen(0, 0, 255); // Azul
delay(1500);
// Também é possível usar códigos de cor hexadecimal RGB565 diretamente
meuDisplay.Fill_Screen(0x0000); // Preto
delay(1000);
meuDisplay.Fill_Screen(0xFFFF); // Branco
delay(1000);
meuDisplay.Fill_Screen(0xF800); // Vermelho
delay(1000);
meuDisplay.Fill_Screen(0x07E0); // Verde
delay(1000);
meuDisplay.Fill_Screen(0x001F); // Azul
delay(1000);
}