esp-iot-solution 的 i2c_bus 组件演进史与源码剖析:从硬件 I2C 到软件 I2C 的完整实践指南
esp-iot-solution 的 i2c_bus 组件演进史与源码剖析从硬件 I2C 到软件 I2C 的完整实践指南【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution导读本文以 esp-iot-solution 仓库中 components/i2c_bus/CHANGELOG.md 的版本演进为主线系统梳理i2c_bus组件从 v0.1.0 到 v1.5.2 的核心能力变化并结合 include/i2c_bus.h、i2c_bus.c、i2c_bus_v2.c 与 i2c_bus_soft.c 等源码讲解其总线/设备两级抽象模型、线程安全机制、动态配置、软件 I2C 扩展等设计。读完本文你将掌握i2c_bus的完整 API 用法、Kconfig 配置含义、驱动选型规则driver/i2c与esp_driver_i2c并能理解每次版本更新背后的实现细节。一、组件定位构建在 ESP-IDF 驱动之上的 I2C 总线抽象层i2c_bus是 esp-iot-solution 的核心基础设施组件之一位于 components/i2c_bus。根据 README.md 的定位它是一套构建在 ESP-IDF 外设驱动之上的应用层代码主要用于 ESP 芯片与外部设备之间的总线通信面向应用开发提供五项关键特性简化外设初始化流程线程安全的设备操作简单灵活的读写操作同时兼容driver/i2c与esp_driver_i2c两代驱动支持额外的软件 I2CSoft I2C。组件抽象了两个核心概念Bus总线设备通信期间共享的资源和配置选项Device设备设备自身特有的资源和通信配置选项。在电气条件允许的前提下一条物理外设总线可以挂载一个或多个设备I2C 总线按地址寻址从而实现了同一总线上不同设备之间的软件独立性。这一抽象是理解组件所有 API 设计的基础。组件通过 idf_component.yml 声明依赖要求idf: 4.0并依赖cmake_utilities当前版本为 1.5.2。可通过组件管理器一键引入idf.py add-dependency espressif/i2c_bus*二、版本演进总览从首版到 v1.5.2 的能力路线图CHANGELOG.md 完整记录了组件从 2024 年 5 月的首版到 2026 年 6 月 v1.5.2 的演进过程核心能力变化可归纳为下表版本时间类型核心变更v0.1.02024-05-27首发支持 I2C 总线基础功能v1.0.02024-09-19增强组件版本维护与文档增强支持esp_driver_i2c新驱动v1.1.02024-11-22增强IDF v5.3 及以上支持手动选择driver/i2c或esp_driver_i2cv1.2.02025-01-14增强支持启用软件 I2C 以扩展 I2C 端口数量v1.3.02025-02-13增强i2c_bus_v2支持使用esp_driver_i2c提供的 bus_handle 初始化也支持返回内部 bus_handlev1.4.02025-03-13增强支持解除NULL_I2C_MEM_ADDR限制允许访问任意合法寄存器地址v1.4.12025-08-14修复软件 I2C 也支持解除NULL_I2C_MEM_ADDR限制修改 Kconfig 中ESP_IDF_VERSION命名避免与其他组件冲突v1.4.22025-08-26修复解除I2C_BUS_BACKWARD_CONFIG对 IDF 版本的依赖并为 I2C 驱动信息增加 CMake 提示v1.4.32025-09-26修复同步 cmake_utilities 的版本信息v1.5.12026-03-18修复修复i2c_bus_v2中 LP I2C 端口默认时钟源选择改用LP_I2C_SCLK_DEFAULTv1.5.22026-06-08修复修复 IDF v6 下软件 I2C 的编译错误下文将沿着这条演进线逐项讲解每条变更背后的技术与使用方法。三、驱动选型兼容driver/i2c与esp_driver_i2c的两代实现3.1 双实现文件的构建机制v1.0.0 引入esp_driver_i2c支持、v1.1.0 支持手动选型之后组件在构建层形成了一组件两实现的结构。查看 CMakeLists.txt 可见其编译期选型逻辑if(${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR} VERSION_LESS 5.3 OR CONFIG_I2C_BUS_BACKWARD_CONFIG) set(SRC_FILE i2c_bus.c) set(REQ driver) message(STATUS Using driver/i2c (SRC_FILEi2c_bus.c, REQdriver)) else() set(SRC_FILE i2c_bus_v2.c) set(REQ esp_driver_i2c driver) if(${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR} VERSION_GREATER_EQUAL 6.0) list(APPEND REQ esp_driver_gpio) endif() endif() if (CONFIG_I2C_BUS_SUPPORT_SOFTWARE) list(APPEND SRC_FILE i2c_bus_soft.c) endif()选型规则清晰可见IDF 版本低于 5.3编译 i2c_bus.c旧版driver/i2c实现IDF 5.3 及以上且未开启向后兼容编译 i2c_bus_v2.c新版esp_driver_i2c实现并额外依赖esp_driver_i2cIDF v6.0 起还追加esp_driver_gpio依赖这正是 v1.5.2 修复软件 I2C 编译问题的关联项之一开启CONFIG_I2C_BUS_SUPPORT_SOFTWARE追加编译软件 I2C 实现 i2c_bus_soft.c。CMake 还会通过message(STATUS ...)打印当前实际选用的源文件方便构建日志中确认对应 v1.4.2 的为 I2C 驱动信息增加 CMake 提示。头文件侧的兼容逻辑位于 include/i2c_bus.h 开头IDF ≥ 5.3 且未开启CONFIG_I2C_BUS_BACKWARD_CONFIG时引入driver/i2c_master.h否则引入driver/i2c.h。3.2 向后兼容开关I2C_BUS_BACKWARD_CONFIGv1.4.2 之前I2C_BUS_BACKWARD_CONFIG与特定 IDF 版本强绑定该版本起解除了这一绑定并配套输出 CMake 信息。该配置项定义在 Kconfigconfig I2C_BUS_BACKWARD_CONFIG bool Enable backward compatibility for the I2C driver (force use of the old i2c_driver above v5.3) default n help Enable this option for backward compatibility with the old I2C driver (only valid in IDF v5.3 and above).它只对 IDF v5.3 及以上有效置y时即使使用新版本 IDF也强制走旧的driver/i2c实现i2c_bus.c。对于维护旧工程、或对老驱动 API 有依赖的项目这是一个低成本平滑迁移的开关。3.3 两套实现的差异从源码对比看两套实现都维护相同的s_i2c_bus[port]全局数组与引用计数ref_counter但底层句柄不同i2c_bus.c旧实现结构体保存i2c_port_t i2c_port、is_init、conf_active、mutex、ref_counter设备结构体保存dev_addr与设备自身配置驱动安装/卸载调用的是i2c_driver_install/i2c_driver_delete系列i2c_bus_v2.c新实现结构体保存i2c_master_bus_config_t bus_config、i2c_master_bus_handle_t bus_handle、i2c_device_config_t device_config驱动安装/卸载调用i2c_new_master_bus/i2c_del_master_bus并在创建设备时调用i2c_master_bus_add_device。值得注意的细节i2c_bus_v2.c在创建总线时设置bus_config.glitch_ignore_cnt 7以配置主机总线毛刺过滤周期并将enable_internal_pullup置为(conf-scl_pullup_en | conf-sda_pullup_en)即只要 SCL 或 SDA 任一开启内部上拉就使能总线内部上拉。四、v1.3.0 特性复用与导出esp_driver_i2c的 bus_handlev1.3.0 为i2c_bus_v2增加了两个方向的能力外部句柄初始化如果用户已经通过esp_driver_i2c的i2c_new_master_bus创建过总线那么i2c_bus_create会通过i2c_master_get_bus_handle(port, ...)探测到已存在的外部总线句柄直接复用并返回组件句柄日志打印I2C Bus V2 uses the externally initialized bus handle见 i2c_bus_v2.c。这一能力避免了同一端口二次安装驱动导致的冲突。内部句柄导出通过新 APIi2c_bus_get_internal_bus_handle(i2c_bus_handle_t bus_handle)返回组件内部持有的i2c_master_bus_handle_t让上层应用可以调用esp_driver_i2c原生的高级接口如直接i2c_master_probe等。对应测试用例 I2C bus uses external bus handle test 位于 test_apps/main/test_i2c_bus.c先用i2c_new_master_bus创建原生总线再调用i2c_bus_create随后正常创建设备并完成读写最后i2c_bus_delete验证了复用外部句柄的完整生命周期。五、v1.4.0/v1.4.1 特性解除NULL_I2C_MEM_ADDR寄存器地址限制5.1 背景无内部寄存器地址的设备的约定很多 I2C 器件如 EEPROM 类存储、部分传感器没有内部寄存器/内存地址概念读写时不应在数据前附加地址字节。为此 include/i2c_bus.h 定义了三个特殊宏#define NULL_I2C_MEM_ADDR 0xFF /*! 8-bit mem_address 置此值表示设备无内部地址 */ #define NULL_I2C_MEM_16BIT_ADDR 0XFFFF /*! 16-bit mem_address 置此值表示设备无内部地址 */ #define NULL_I2C_DEV_ADDR 0xFF /*! 非法设备地址 */在默认行为下当mem_address NULL_I2C_MEM_ADDR0xFF时组件会跳过地址字节直接发送/接收数据。但 0xFF 恰好也是某些设备合法的寄存器地址导致这些设备无法访问。5.2 解除限制的方式v1.4.0 为硬件 I2C、v1.4.1 为软件 I2C 分别补齐了解除限制的能力开关为 Kconfig 中的I2C_BUS_REMOVE_NULL_MEM_ADDRconfig I2C_BUS_REMOVE_NULL_MEM_ADDR bool Remove the limitation of NULL_MEM_ADDR, any register address will be sent default n help Enable this option to disable NULL_MEM_ADDR. This allows any register address to be sent.开启后mem_address参数将原样作为寄存器地址发送0x00~0xFF含 0xFF全部可访问。源码中的实现体现在读/写路径的条件编译上例如 i2c_bus_v2.c 的i2c_bus_read_reg8#if !CONFIG_I2C_BUS_REMOVE_NULL_MEM_ADDR if (mem_address ! NULL_I2C_MEM_ADDR) { #endif ret i2c_master_transmit_receive(i2c_device-dev_handle, mem_address, 1, data, data_len, I2C_BUS_TICKS_TO_WAIT); #if !CONFIG_I2C_BUS_REMOVE_NULL_MEM_ADDR } else { ESP_LOGD(TAG, register address 0x%X is skipped and will not be sent, NULL_I2C_MEM_ADDR); ret i2c_master_receive(i2c_device-dev_handle, data, data_len, I2C_BUS_TICKS_TO_WAIT); } #endif写路径 i2c_bus_write_reg8 的处理类似默认情况下为数据前拼接mem_address字节需要malloc(data_len 1)内存申请失败会立即释放互斥锁并返回ESP_ERR_NO_MEM当地址等于NULL_I2C_MEM_ADDR时直接发送裸数据。16 位地址路径i2c_bus_read_reg16/i2c_bus_write_reg16则对应NULL_I2C_MEM_16BIT_ADDR。对应测试 I2C bus register address restriction test 见 test_i2c_bus.c。注意该配置同时影响硬件与软件 I2C软件 I2C 实现在 i2c_bus_soft.c 中有同样逻辑这是 v1.4.1 与 v1.4.0 的差异点。六、v1.2.0 特性软件 I2C 扩展端口数量6.1 适用场景与启用方式ESP32 各芯片的硬件 I2C 外设数量有限典型为 1~2 个当需要挂载大量不同电压域或不同速率的总线时硬件端口往往不够用。v1.2.0 引入软件 I2C用 GPIO 位操作模拟 I2C 时序从而把端口数量扩展到 5 个。启用步骤如下menuconfig 中打开CONFIG_I2C_BUS_SUPPORT_SOFTWARE默认n按需设置CONFIG_I2C_BUS_SOFTWARE_MAX_PORT默认 2范围 1~5。Kconfig 原文config I2C_BUS_SUPPORT_SOFTWARE bool Enable software I2C support default n help Enable this option to use a software-implemented I2C driver. This can be useful for scenarios where hardware I2C is unavailable or additional I2C buses are needed beyond the hardware support. config I2C_BUS_SOFTWARE_MAX_PORT int Maximum number of software I2C ports default 2 range 1 5 depends on I2C_BUS_SUPPORT_SOFTWARE6.2 端口编号与 API 一致性开启后include/i2c_bus.h 定义扩展端口枚举i2c_sw_port_t从I2C_NUM_MAX 1起递增到I2C_NUM_SW_0~I2C_NUM_SW_4数量由CONFIG_I2C_BUS_SOFTWARE_MAX_PORT决定。因此i2c_bus_create的port参数既可以传硬件端口I2C_NUM_0/I2C_NUM_1也可以传I2C_NUM_SW_0等软件端口上层 API读写、扫描、建删设备完全一致实现了接口透明的端口扩展。i2c_bus_v2.c中通过bus_config.i2c_port I2C_NUM_MAX判断当前走软件总线路径调用 private_include/i2c_bus_soft.h 中声明的i2c_new_master_soft_bus、i2c_master_soft_bus_read_reg8/write_reg8等软总线接口。软件总线的核心结构体仅含三项scl_io、sda_io与time_delay_usSCL 翻转间隔微秒决定 SCL 频率。每次传输前会调用i2c_master_soft_bus_change_frequency将总线切到目标设备频率从而支持同一条软件总线上不同速率设备混挂。6.3 实测验证test_i2c_bus.c 在CONFIG_I2C_BUS_SUPPORT_SOFTWARE下提供了软总线 init/deinit、设备增删、扫描、异频写等完整测试例如I2C soft bus write under different frequency test在同一软总线上先后以 100kHz 与 4kHz40 * 100向不同设备写数据。七、v1.5.x 维护LP I2C 时钟源与 IDF v6 兼容v1.5.1 与 v1.5.2 是两个值得留意的维护性修复体现了组件对新型号芯片与新版 IDF 的跟进v1.5.1LP I2C 默认时钟源部分新芯片如 ESP32-C6 等SOC_LP_I2C_NUM 0带低功耗 I2C 控制器LP I2C端口号位于LP_I2C_NUM_0到I2C_NUM_MAX之间。修复前i2c_bus_v2对这些端口错误地使用I2C_CLK_SRC_DEFAULTv1.5.1 在 i2c_bus_v2.c 的i2c_bus_set_default_clk_source中按端口区分LP I2C 端口使用LP_I2C_SCLK_DEFAULT普通端口使用I2C_CLK_SRC_DEFAULT。v1.5.2IDF v6 软件 I2C 编译修复IDF v6 中 GPIO 相关头文件/接口有调整软件 I2C 编译报错该版本修复此问题同时在 CMakeLists 中为 IDF v6 追加esp_driver_gpio依赖。八、核心 API 全景与源码级解析8.1 总线生命周期与单例语义i2c_bus_create(i2c_port_t port, const i2c_config_t *conf)创建总线实例并返回句柄。每个端口呈单例模式——同一端口重复调用时若配置未变化则直接返回既有句柄若配置变化则重装驱动旧配置覆盖新配置。源码依据见 i2c_bus_v2.c 与 i2c_bus.c。注意组件仅支持主机模式conf-mode ! I2C_MODE_MASTER会直接返回 NULL。i2c_bus_delete(i2c_bus_handle_t *p_bus_handle)释放总线资源成功后句柄置 NULL。仅当ref_counter 0时才真正卸载驱动否则打印警告并直接返回保证总线上还有设备时不会被误删。i2c_bus_get_current_clk_speed/i2c_bus_get_created_device_num查询当前生效时钟频率与已创建设备数即ref_counter。i2c_bus_scan(i2c_bus_handle_t bus_handle, uint8_t *buf, uint8_t num)扫描总线上从 1 到 126 的 7 位地址返回发现设备总数传入非空buf可保存地址列表num限制保存数量。扫描期间持有互斥锁。8.2 设备管理与动态配置i2c_bus_device_create(i2c_bus_handle_t bus_handle, uint8_t dev_addr, uint32_t clk_speed)在总线上创建设备。clk_speed为设备专用时钟频率传 0 表示沿用总线频率非 0 时会在该设备每次传输时切换频率从而实现同一条总线上多设备异频前提是开启动态配置。源码中限制clk_speed 400000i2c_bus_v2.c内部通过i2c_master_bus_add_device注册到esp_driver_i2c。i2c_bus_device_delete/i2c_bus_device_get_address删除设备必须与 create 成对使用与查询设备地址。动态配置由 Kconfig 控制config I2C_BUS_DYNAMIC_CONFIG bool enable dynamic configuration default y help If enable, i2c_bus will dynamically check configs and re-install i2c driver before each transfer, hence multiple devices with different configs on a single bus can be supported.默认开启其代价是每次传输前可能重装驱动适合设备配置差异大的场景对配置单一的总线可关闭以减小开销。8.3 读写 API寄存器级与位级操作组件提供两套层次分明的读写接口见 include/i2c_bus.h字节/多字节级i2c_bus_read_byte、i2c_bus_read_bytes、i2c_bus_write_byte、i2c_bus_write_bytes均带 8 位内部寄存器地址参数位级i2c_bus_read_bit、i2c_bus_read_bits、i2c_bus_write_bit、i2c_bus_write_bits用于精确操作寄存器中的某一位或多位。位操作内部是读-改-写先读回整字节再按bit_startMSB 为 0与length构造掩码修改最后写回16 位地址低层接口i2c_bus_read_reg16、i2c_bus_write_reg16适用于内部寄存器地址为 16 位的器件如部分 EEPROM/传感器地址按大端拆分两个字节发送命令链i2c_bus_cmd_begin可发送由i2c_cmd_link_create构建的排队命令适用于标准接口无法满足的复杂时序场景。所有读写接口的返回值统一为ESP_OK成功、ESP_ERR_INVALID_ARG参数错误、ESP_FAIL从机未 ACK、ESP_ERR_INVALID_STATE驱动未安装或非主机模式、ESP_ERR_TIMEOUT总线忙超时。8.4 线程安全机制组件的线程安全通过每端口 FreeRTOS 互斥锁xSemaphoreCreateMutex实现。以 i2c_bus_v2.c 的宏定义为例#define I2C_BUS_MUTEX_TAKE(mutex, ret) if (!xSemaphoreTake(mutex, I2C_BUS_MUTEX_TICKS_TO_WAIT)) { \ ESP_LOGE(TAG, i2c_bus take mutex timeout, max wait %PRIu32ms, I2C_BUS_MUTEX_TICKS_TO_WAIT); \ return (ret); \ }普通传输使用I2C_BUS_MUTEX_TAKE阻塞时间为CONFIG_I2C_MS_TO_WAIT对应的 ticks总线/设备创建删除使用I2C_BUS_MUTEX_TAKE_MAX_DELAYportMAX_DELAY避免资源管理半途而废。CONFIG_I2C_MS_TO_WAIT对应 Kconfig 中的I2C_MS_TO_WAITconfig I2C_MS_TO_WAIT int mutex block time default 200 range 50 5000 help task block time when try to take the bus, unit:milliseconds默认 200ms可调范围 50~5000ms。多个 RTOS 任务同时访问同一总线时互斥锁保证每次传输原子执行防止总线时序被并发打断。九、从零开始一个可直接运行的完整示例以下示例取自 README.md展示总线创建、设备创建、批量写入与资源释放的完整流程示例以标准 100kHz、GPIO15/16 为例#include stdio.h #include freertos/FreeRTOS.h #include freertos/task.h #include i2c_bus.h #define I2C_MASTER_SCL_IO (gpio_num_t)15 /*! gpio number for I2C master clock */ #define I2C_MASTER_SDA_IO (gpio_num_t)16 /*! gpio number for I2C master data */ #define I2C_MASTER_FREQ_HZ 100000 /*! I2C master clock frequency */ #define ESP_SLAVE_ADDR 0x28 /*! ESP32 slave address, you can set any 7bit value */ #define DATA_LENGTH 64 /*! Data buffer length for test buffer*/ void app_main(void) { uint8_t *data_wr (uint8_t *)malloc(DATA_LENGTH); i2c_config_t conf { .mode I2C_MODE_MASTER, .sda_io_num I2C_MASTER_SDA_IO, .sda_pullup_en GPIO_PULLUP_ENABLE, .scl_io_num I2C_MASTER_SCL_IO, .scl_pullup_en GPIO_PULLUP_ENABLE, .master.clk_speed I2C_MASTER_FREQ_HZ, }; i2c_bus_handle_t i2c0_bus i2c_bus_create(I2C_NUM_0, conf); i2c_bus_device_handle_t i2c0_device1 i2c_bus_device_create(i2c0_bus, ESP_SLAVE_ADDR, 0); for (int i 0; i DATA_LENGTH; i) { data_wr[i] i; } i2c_bus_write_bytes(i2c0_device1, NULL_I2C_MEM_ADDR, DATA_LENGTH, data_wr); free(data_wr); i2c_bus_device_delete(i2c0_device1); i2c_bus_delete(i2c0_bus); }要点注释i2c_config_t的mode必须为I2C_MODE_MASTERsda_pullup_en/scl_pullup_en决定是否使能内部上拉总线上无外部上拉电阻时必须开启master.clk_speed为总线默认时钟硬件 I2C 一般不高于 1MHz设备级clk_speed上限 400kHz见 i2c_bus.h 与 i2c_bus_v2.ci2c_bus_device_create第三参传 0 表示沿用总线频率目标器件无内部寄存器地址时mem_address传NULL_I2C_MEM_ADDR地址字节会被跳过资源释放顺序为先删设备、再删总线与创建顺序相反。9.1 测试用例速查仓库 test_apps 中的测试覆盖了总线 init/deinit 与配置变更、设备增删、主机写从机读、主机读从机写、异频写、外部 bus_handle 复用、总线扫描、NULL 地址限制、软件 I2C 全套流程以及setUp/tearDown中的内存泄漏检测阈值-460字节。pytest 脚本 pytest_i2c_bus.py 与 sdkconfig.ci.software 提供了软件 I2C 的 CI 构建配置可作为验证组件行为的参考。十、配置项速查表与最佳实践综合 Kconfig组件的全部配置项汇总如下配置项类型默认值作用与建议I2C_BUS_DYNAMIC_CONFIGbooly每次传输前动态检查并重装驱动支持同总线多设备异配置配置单一可关闭I2C_MS_TO_WAITint200范围 50~5000获取总线互斥锁的阻塞时间msI2C_BUS_BACKWARD_CONFIGboolnIDF ≥ 5.3 时强制使用旧driver/i2c实现I2C_BUS_SUPPORT_SOFTWAREbooln启用软件 I2C 扩展端口I2C_BUS_SOFTWARE_MAX_PORTint2范围 1~5软件 I2C 最大端口数I2C_BUS_REMOVE_NULL_MEM_ADDRbooln解除 0xFF 地址限制允许发送任意寄存器地址实践建议均有源码依据多设备异速总线上挂载保持I2C_BUS_DYNAMIC_CONFIGy为慢速/快速设备分别i2c_bus_device_create时指定各自clk_speed组件会在每次传输前自动切换频率测试用例 I2C master write under different frequency test 即验证了 100kHz 与 4kHz 混挂设备无内部寄存器地址默认行为下传NULL_I2C_MEM_ADDR即可若目标器件 0xFF 是合法寄存器且必须访问再开启I2C_BUS_REMOVE_NULL_MEM_ADDR硬件端口不足开启I2C_BUS_SUPPORT_SOFTWARE并按需调大I2C_BUS_SOFTWARE_MAX_PORT用I2C_NUM_SW_x端口替代注意软件 I2C 频率由 GPIO 翻转延时决定适用于对时序精度要求不苛刻的外设与原生esp_driver_i2c代码混用IDF ≥ 5.3 时可通过i2c_bus_get_internal_bus_handle取回原生句柄或在外部先创建总线后交由组件接管多任务并发访问不要调小I2C_MS_TO_WAIT至 50ms 以下避免高负载下取锁超时组件内部所有传输路径都持有互斥锁业务层无需再加锁。十一、小结i2c_bus组件以总线/设备两级抽象为骨架通过 v0.1.0→v1.5.2 的迭代逐步补齐了esp_driver_i2c新驱动支持、驱动手动选型、软件 I2C 端口扩展、外部 bus_handle 复用、NULL 地址限制解除、LP I2C 时钟源修复与 IDF v6 兼容等能力其演进史本身即是 ESP-IDF I2C 生态迁移的缩影。对应用开发者而言include/i2c_bus.h 是接口权威i2c_bus_v2.c 与 i2c_bus.c 是行为权威而 test_apps 是验证组件语义最直接的可运行范例。建议在实际项目中以idf.py add-dependency espressif/i2c_bus*引入组件并结合本文的配置项速查表按需裁剪。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考