#include "driver/i2c.h" #include "esp_err.h" #include "esp_log.h" #include "driver/gpio.h" #include "esp_rom_sys.h" #define SDA_PIN 21 #define SCL_PIN 22 #define I2C_PORT I2C_NUM_0 static const char *TAG_I2C = "I2C"; static void i2c_bus_reset(void) { // Solta o bus: gera 9 clocks em SCL para libertar SDA se algum escravo ficou preso gpio_config_t io = { .pin_bit_mask = (1ULL << SDA_PIN) | (1ULL << SCL_PIN), .mode = GPIO_MODE_OUTPUT_OD, .pull_up_en = GPIO_PULLUP_ENABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, .intr_type = GPIO_INTR_DISABLE }; gpio_config(&io); gpio_set_level(SDA_PIN, 1); gpio_set_level(SCL_PIN, 1); esp_rom_delay_us(5); for (int i = 0; i < 9; i++) { gpio_set_level(SCL_PIN, 0); esp_rom_delay_us(5); gpio_set_level(SCL_PIN, 1); esp_rom_delay_us(5); } // STOP gpio_set_level(SDA_PIN, 0); esp_rom_delay_us(5); gpio_set_level(SCL_PIN, 1); esp_rom_delay_us(5); gpio_set_level(SDA_PIN, 1); esp_rom_delay_us(5); // devolve os pinos ao I2C driver depois } esp_err_t i2c_init(void) { // se já estava instalado, limpa e volta a instalar i2c_driver_delete(I2C_PORT); i2c_bus_reset(); i2c_config_t cfg = { .mode = I2C_MODE_MASTER, .sda_io_num = SDA_PIN, .scl_io_num = SCL_PIN, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = 100000, // começa seguro .clk_flags = 0 }; esp_err_t err; err = i2c_param_config(I2C_PORT, &cfg); if (err != ESP_OK) { ESP_LOGE(TAG_I2C, "i2c_param_config falhou: %s", esp_err_to_name(err)); return err; } err = i2c_driver_install(I2C_PORT, cfg.mode, 0, 0, 0); if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { ESP_LOGE(TAG_I2C, "i2c_driver_install falhou: %s", esp_err_to_name(err)); return err; } ESP_LOGI(TAG_I2C, "I2C OK (SDA=%d SCL=%d) freq=100kHz", SDA_PIN, SCL_PIN); return ESP_OK; }