ESP32S3通过I2C驱动IS31FL3236A LED无响应问题排查求助
问题描述
我有一块基于ESP32S3的自定义LED开发板,需要编写程序通过I2C总线让MCU与LED驱动芯片IS31FL3236A通信。我把找到的Arduino示例代码转为ESP-IDF标准库的C/C++代码,但LED无法正常工作(Arduino版本代码可正常运行)。引脚配置和Arduino完全一致,确认SDA、SCL、LED引脚都正确。
程序代码
#include "esp_log.h" #include "driver/i2c.h" static const char *TAG = "i2c-simple-example"; #define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL #define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA #define I2C_MASTER_NUM 0 #define I2C_MASTER_FREQ_HZ 400000 #define OUT_CURRENT 0x02 #define LED_DRIVER_ADDR 0x3C #define IS31FL3236A_UPDATE_REG 0x25 #define IS31FL3236A_SHUTDOWN_REG 0x00 esp_err_t i2c_master_init(void) { int i2c_master_port = I2C_MASTER_NUM; i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .scl_io_num = I2C_MASTER_SCL_IO, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = I2C_MASTER_FREQ_HZ, }; i2c_param_config(i2c_master_port, &conf); return i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0); } void send_data(uint8_t ledDriverRegister, unsigned char data) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); ESP_ERROR_CHECK(i2c_master_start(cmd)); ESP_ERROR_CHECK(i2c_master_write_byte(cmd, LED_DRIVER_ADDR, true)); ESP_ERROR_CHECK(i2c_master_write_byte(cmd, ledDriverRegister, true)); ESP_ERROR_CHECK(i2c_master_write_byte(cmd, data, true)); ESP_ERROR_CHECK(i2c_master_stop(cmd)); i2c_cmd_link_delete(cmd); } void update_shutdown_register_to_normal_operation() { send_data(IS31FL3236A_SHUTDOWN_REG, 0x01); } void update_register() { send_data(IS31FL3236A_UPDATE_REG, 0x00); } void init() { ESP_LOGI(TAG, "Init current for leds"); for (uint8_t i = 0x26; i <= 0x49; i++) { send_data(i, ((OUT_CURRENT << 1) | 0x01)); // enable all leds } for (uint8_t i = 0x01; i <= 0x24; i++) { send_data(i, 0x00); // set PWM for all leds to 0 } ESP_LOGI(TAG, "Updated register"); update_register(); update_shutdown_register_to_normal_operation(); } _Noreturn void app_main(void) { ESP_ERROR_CHECK(i2c_master_init()); ESP_LOGI(TAG, "I2C initialized successfully GPIO SDA %d SCL %d", I2C_MASTER_SDA_IO, I2C_MASTER_SCL_IO); init(); send_data(0x8, 0x63); // I my board LED is on OUT on port 8 and value 63 max update_register(); ESP_LOGI(TAG, "End Test"); vTaskDelay(3000 / portTICK_RATE_MS); }
串口日志
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- ESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x1 (POWERON),boot:0x9 (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:2 load:0x3fce3808,len:0x1664 load:0x403c9700,len:0xbb8 load:0x403cc700,len:0x2e8c entry 0x403c9954 I (29) boot: ESP-IDF v4.4.3-dirty 2nd stage bootloader I (29) boot: compile time 22:27:17 I (30) boot: chip revision: 0 I (32) boot.esp32s3: Boot SPI Speed : 40MHz I (36) boot.esp32s3: SPI Mode : DIO I (41) boot.esp32s3: SPI Flash Size : 8MB I (46) boot: Enabling RNG early entropy source... I (51) boot: Partition Table: I (55) boot: ## Label Usage Type ST Offset Length I (62) boot: 0 nvs WiFi data 01 02 00009000 00006000 I (70) boot: 1 phy_init RF data 01 01 0000f000 00001000 I (77) boot: 2 factory factory app 00 00 00010000 00100000 I (84) boot: End of partition table I (89) esp_image: segment 0: paddr=00010020 vaddr=3c020020 size=088c8h ( 35016) map I (106) esp_image: segment 1: paddr=000188f0 vaddr=3fc91f90 size=02614h ( 9748) load I (109) esp_image: segment 2: paddr=0001af0c vaddr=40374000 size=0510ch ( 20748) load I (120) esp_image: segment 3: paddr=00020020 vaddr=42000020 size=182f8h ( 99064) map I (147) esp_image: segment 4: paddr=00038320 vaddr=4037910c size=08e84h ( 36484) load I (158) esp_image: segment 5: paddr=000411ac vaddr=50000000 size=00010h ( 16) load I (164) boot: Loaded app from partition at offset 0x10000 I (164) boot: Disabling RNG early entropy source... I (178) cpu_start: Pro cpu up. I (178) cpu_start: Starting app cpu, entry point is 0x403751e4 0x403751e4: call_start_cpu1 at /home/rafal/esp/esp-idf/components/esp_system/port/cpu_start.c:148 I (0) cpu_start: App cpu up. I (192) cpu_start: Pro cpu start user code I (192) cpu_start: cpu freq: 160000000 I (192) cpu_start: Application information: I (195) cpu_start: Project name: i2c-simple I (200) cpu_start: App version: v4.4.3-dirty I (206) cpu_start: Compile time: Nov 25 2022 22:18:32 I (212) cpu_start: ELF file SHA256: a7bcfcfcba18ab90... I (218) cpu_start: ESP-IDF: v4.4.3-dirty I (223) heap_init: Initializing. RAM available for dynamic allocation: I (230) heap_init: At 3FC94F98 len 00054778 (337 KiB): D/IRAM I (237) heap_init: At 3FCE9710 len 00005724 (21 KiB): STACK/DRAM I (243) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM I (250) heap_init: At 600FE000 len 00002000 (8 KiB): RTCRAM I (257) spi_flash: detected chip: generic I (261) spi_flash: flash io: dio I (266) cpu_start: Starting scheduler on PRO CPU. I (0) cpu_start: Starting scheduler on APP CPU. I (286) i2c-simple-example: I2C initialized successfully GPIO SDA 10 SCL 9 I (286) i2c-simple-example: Init current for leds I (296) i2c-simple-example: Updated register I (296) i2c-simple-example: Set min value for pwm I (306) i2c-simple-example: End Test
问题排查与解决方案
核心问题点
- I2C设备地址格式错误:
i2c_master_write_byte的第二个参数需要是带读写位的7位地址。原代码直接传入LED_DRIVER_ADDR(0x3C),但ESP-IDF API要求将7位地址左移1位,再加上写位(0),正确格式应为(0x3C << 1) | 0即0x78。 - 缺少I2C命令执行步骤:原代码创建命令链、添加指令后,未调用
i2c_master_cmd_begin发送指令,导致所有寄存器写入操作未生效。 - 寄存器初始化顺序错误:IS31FL3236A需先退出关断模式,再配置其他寄存器。原代码先配置电流和PWM,再设置关断寄存器,可能导致配置不生效。
修改后的代码
#include "esp_log.h" #include "driver/i2c.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" static const char *TAG = "i2c-simple-example"; #define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL #define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA #define I2C_MASTER_NUM 0 #define I2C_MASTER_FREQ_HZ 400000 #define OUT_CURRENT 0x02 #define LED_DRIVER_ADDR 0x3C // 7位地址 #define IS31FL3236A_UPDATE_REG 0x25 #define IS31FL3236A_SHUTDOWN_REG 0x00 esp_err_t i2c_master_init(void) { int i2c_master_port = I2C_MASTER_NUM; i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .scl_io_num = I2C_MASTER_SCL_IO, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = I2C_MASTER_FREQ_HZ, }; i2c_param_config(i2c_master_port, &conf); return i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0); } esp_err_t send_data(uint8_t ledDriverRegister, unsigned char data) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); ESP_ERROR_CHECK(i2c_master_start(cmd)); // 修正地址格式:7位地址左移1位 + 写位 ESP_ERROR_CHECK(i2c_master_write_byte(cmd, (LED_DRIVER_ADDR << 1) | I2C_MASTER_WRITE, true)); ESP_ERROR_CHECK(i2c_master_write_byte(cmd, ledDriverRegister, true)); ESP_ERROR_CHECK(i2c_master_write_byte(cmd, data, true)); ESP_ERROR_CHECK(i2c_master_stop(cmd)); // 执行I2C命令链 esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS); i2c_cmd_link_delete(cmd); return ret; } void update_shutdown_register_to_normal_operation() { ESP_ERROR_CHECK(send_data(IS31FL3236A_SHUTDOWN_REG, 0x01)); vTaskDelay(10 / portTICK_RATE_MS); // 等待芯片退出关断模式 } void update_register() { ESP_ERROR_CHECK(send_data(IS31FL3236A_UPDATE_REG, 0x00)); } void init() { ESP_LOGI(TAG, "Init current for leds"); // 先退出关断模式,再配置其他寄存器 update_shutdown_register_to_normal_operation(); for (uint8_t i = 0x26; i <= 0x49; i++) { ESP_ERROR_CHECK(send_data(i, ((OUT_CURRENT << 1) | 0x01))); // 启用所有LED vTaskDelay(1 / portTICK_RATE_MS); // 避免I2C总线拥堵 } for (uint8_t i = 0x01; i <= 0x24; i++) { ESP_ERROR_CHECK(send_data(i, 0x00)); // 设置所有LED初始PWM为0 vTaskDelay(1 / portTICK_RATE_MS); } ESP_LOGI(TAG, "Updated register"); update_register(); } void app_main(void) { ESP_ERROR_CHECK(i2c_master_init()); ESP_LOGI(TAG, "I2C initialized successfully GPIO SDA %d SCL %d", I2C_MASTER_SDA_IO, I2C_MASTER_SCL_IO); init(); ESP_ERROR_CHECK(send_data(0x08, 0x63)); // 设置第8路LED的PWM值为63 update_register(); ESP_LOGI(TAG, "End Test"); vTaskDelay(3000 / portTICK_RATE_MS); }
修改说明
- 地址格式修正:将设备地址转换为ESP-IDF要求的带写位格式,确保I2C通信能正确寻址到IS31FL3236A。
- 添加命令执行:调用
i2c_master_cmd_begin实际发送I2C指令链,让寄存器写入操作生效。 - 调整初始化顺序:先退出关断模式,再配置电流和PWM寄存器,符合芯片操作时序要求。
- 增加延时:在多次I2C操作之间添加短暂延时,避免总线拥堵导致通信失败。
- 错误返回处理:让
send_data返回错误码,便于排查通信问题。
内容的提问来源于stack exchange,提问作者Mbded
相关产品推荐
相关产品推荐

