#include <stdio.h>
#include "driver/i2c.h"
#include "esp_err.h"
#include <string.h>
// Definições do Master
#define I2C_MASTER_SDA 21 // Pino SDA do ESP32
#define I2C_MASTER_SCL 22 // Pino SCL do ESP32
#define I2C_MASTER_FREQ_HZ 100000 // Frequência I2C (100kHz padrão)
#define I2C_PORT I2C_NUM_0 // Usando o controlador I2C 0
#define LCD_ADDR 0x27 // Endereço I2C do LCD (ajuste conforme necessário)
#define I2C_TIMEOUT (200 / portTICK_PERIOD_MS) //tempo i2c
#define ENABLE 0x04 // BYTE ENABLE
#define BACKLIGHT 0x08 //BACKLIGHT LIGADO
#define COMAND_BYTE 0x00 // BYTE COMANDO RS = 0
#define DATA_BYTE 0x01 // BYTE DADO = RS = 1
//Definição dos comandos
#define TELABLINK 0x0F //Tela com blink piscando
#define LIMPATELA 0x01 // Limpa tela
#define BITOPERACAO_4 0X03 //OPERA O DISPLAY EM 4 BITS
#define ATIVA_4BIT 0x02 // Ativa o modo 4 bits
#define CONFIG_DISPLAY 0x28 //Configura display com duas linhas e font 5 x 8 dot
#define DISPLAY_OFF 0x08 //Display off
#define DESLOCAMENTO_CURSOR 0x06 //Configura o cursor para mover a direta a incrementar sem mover o display
esp_err_t init_lcd(); //função que inicia o lcd de acordo com o datasheet HD44780
esp_err_t write_lcd_comand(uint8_t write_buffer); //função que escreve um comando no display
esp_err_t write_lcd_data(uint8_t write_data); //função que envia um dado para o display
esp_err_t write_lcd_str(const char *str); //função que envia uma string
esp_err_t clear_lcd(); //função que limpa a tela
static const char *TAG = "I2C_DRIVER"; // Para identificar o driver
const char str[] = "Ola mundo";
void app_main() {
printf("Iniciando LCD...\n");
vTaskDelay(pdMS_TO_TICKS(15)); // Pausa de 5 ms entre os comandos
esp_err_t ret = init_lcd();
if (ret != ESP_OK) {
printf("Erro na inicialização do LCD: %s\n", esp_err_to_name(ret));
} else {
printf("LCD inicializado com sucesso!\n");
}
// write_lcd_str(str); // funcao str
//write_lcd_data(data_1); // funcao dado
while(1){
write_lcd_str(str); // funcao str
vTaskDelay(pdMS_TO_TICKS(1000)); // Pausa de 5 ms entre os comandos
clear_lcd();
vTaskDelay(pdMS_TO_TICKS(1000)); // Pausa de 5 ms entre os comandos
}
}
esp_err_t init_lcd() {
esp_err_t ret;
// Configuração do I2C
i2c_config_t config = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA,
.scl_io_num = I2C_MASTER_SCL,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
// Configura o I2C
ret = i2c_param_config(I2C_PORT, &config);
if (ret != ESP_OK) {
printf("Erro ao configurar o I2C: %s\n", esp_err_to_name(ret));
return ret;
}
// Instala o driver I2C
ret = i2c_driver_install(I2C_PORT, config.mode, 0, 0, 0);
if (ret != ESP_OK) {
printf("Erro ao instalar o driver I2C: %s\n", esp_err_to_name(ret));
return ret;
}
// Envia comandos de inicialização
printf("Enviando comandos de inicialização para o LCD...\n");
vTaskDelay(pdMS_TO_TICKS(15)); // Pausa de 15 ms entre os comandos
write_lcd_comand(BITOPERACAO_4 ); //comandos iniciais pag 46 datasheet HD44780
vTaskDelay(pdMS_TO_TICKS(5)); // Pausa de 5 ms entre os comandos
write_lcd_comand(BITOPERACAO_4 ); //comandos iniciais pag 46 datasheet HD44780
vTaskDelay(pdMS_TO_TICKS(1)); // Pausa de 1 ms entre os comandos
write_lcd_comand(BITOPERACAO_4 ); //comandos iniciais pag 46 datasheet HD44780
vTaskDelay(pdMS_TO_TICKS(1)); // Pausa de 1 ms entre os comandos
write_lcd_comand(ATIVA_4BIT );
write_lcd_comand(CONFIG_DISPLAY);
write_lcd_comand(DISPLAY_OFF);
write_lcd_comand(LIMPATELA);
write_lcd_comand(DESLOCAMENTO_CURSOR);
write_lcd_comand(TELABLINK);
return ret;
}
esp_err_t write_lcd_comand(uint8_t write_buffer) {
esp_err_t ret;
uint8_t data_msb = (write_buffer & 0xF0) | BACKLIGHT; //take the nibble MSB
uint8_t data_lsb = ((write_buffer & 0x0F) << 4) | BACKLIGHT; //take the nible LSB
uint8_t data[] = {
data_msb | ENABLE, data_msb, //envia o nibble mais significativo com o ativação e desativação do enable
data_lsb | ENABLE, data_lsb //envia o nibble menos significativo com a ativação e desativação do enable
};
// Envia cada byte de data para o LCD
for (size_t i = 0; i < (sizeof(data)/ sizeof(data[0])); i++) {
ret = i2c_master_write_to_device(I2C_PORT, LCD_ADDR, &data[i], 1, I2C_TIMEOUT);
if (ret != ESP_OK) {
printf("Erro ao escrever no LCD (byte %zu): %s\n", i, esp_err_to_name(ret));
return ret;
}
printf("Byte %zu enviado: 0x%X\n", i, data[i]);
vTaskDelay(pdMS_TO_TICKS(1)); // Pausa de 5 ms entre os comandos
}
return ESP_OK;
}
esp_err_t write_lcd_data(uint8_t write_data) {
esp_err_t ret;
uint8_t data_msb = (write_data & 0xF0) | BACKLIGHT | DATA_BYTE; //take the nibble MSB
uint8_t data_lsb = ((write_data & 0x0F) << 4) | BACKLIGHT | DATA_BYTE; //take the nible LSB
uint8_t data[] = {
data_msb | ENABLE, data_msb, //envia o nibble mais significativo com o ativação e desativação do enable
data_lsb | ENABLE, data_lsb //envia o nibble menos significativo com a ativação e desativação do enable
};
// Envia cada byte de data para o LCD
for (size_t i = 0; i < (sizeof(data)/ sizeof(data[0])); i++) {
ret = i2c_master_write_to_device(I2C_PORT, LCD_ADDR, &data[i], 1, I2C_TIMEOUT);
if (ret != ESP_OK) {
printf("Erro ao escrever no LCD (byte %zu): %s\n", i, esp_err_to_name(ret));
return ret;
}
printf("Byte %zu enviado: 0x%X\n", i, data[i]);
vTaskDelay(pdMS_TO_TICKS(1)); // Pausa de 5 ms entre os comandos
}
return ESP_OK;
}
esp_err_t write_lcd_str(const char *str){
for(size_t i = 0; i < strlen(str); i++){
write_lcd_data(str[i]);
}
return ESP_OK;
}
esp_err_t clear_lcd(){
write_lcd_comand(LIMPATELA);
return ESP_OK;
}