LED_shit/main/i2c_helper.c

87 lines
2.0 KiB
C

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