Controle de Display TFT LCD Touchscreen de 2.4 Polegadas com Arduino

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);
}

Tags: Arduino TFT LCD ILI9341 Touchscreen

Publicado em 8-2 21:49