当前位置: 首页 > backend >正文

ESP32- 开发笔记- 软件开发 5 -I2C

1 I2C 背景介绍

ESP32 的 I²C(Inter-Integrated Circuit)总线是一个非常常用的串行通信接口,广泛用于与各种外围设备(如传感器、显示屏、EEPROM 等)进行通信。

1.1 I²C 基本原理

I²C 是一种 双线通信协议,使用两根线进行主从式通信:

  1. SDA(Serial Data):数据线

  2. SCL(Serial Clock):时钟线

  3. 特点包括:

支持多个主机和多个从设备

每个设备通过地址区分(7 位或 10 位地址)

半双工通信(主机控制通信过程)

1.2 ESP32 上的 I²C 特点

1.2.1 控制器

支持多达两个硬件 I²C 控制器:I2C_NUM_0 和 I2C_NUM_1。 可以使用任意 GPIO 引脚作为 SDA 和 SCL(自由配置)。

| I²C 通道 | SDA 默认引脚 | SCL 默认引脚 |
| ------   | --------    | --------    |
| I2C0     | GPIO21      | GPIO22      |

1.2.2 速率

ESP32 支持以下 I²C 速度:

标准模式:100 kHz

快速模式:400 kHz

高速模式:ESP32 不原生支持 3.4 MHz(需扩展)

1.3 应用范围

  1. OLED 显示屏(如 SSD1306)
  2. 温湿度传感器(如 SHT30、BME280)
  3. EEPROM(如 AT24C32)
  4. IO 扩展芯片(如 PCF8574)

2 配置流程

包含常用的头文件

#include "driver/i2c.h"

2.1 初始化配置结构体

2.1.1 配置函数

esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf);

作用:配置 I²C 控制器的参数,比如 SDA/SCL 引脚、通信速率、主从模式等。

参数:

i2c_num: 控制器编号(如 I2C_NUM_0)

i2c_conf: 配置结构体 i2c_config_t

返回值:成功返回 ESP_OK

2.1.2 例子

i2c_config_t conf = {.mode = I2C_MODE_MASTER,.sda_io_num = GPIO_NUM_21,.scl_io_num = GPIO_NUM_22,.sda_pullup_en = GPIO_PULLUP_ENABLE,.scl_pullup_en = GPIO_PULLUP_ENABLE,.master.clk_speed = 100000, // 100kHz
};
i2c_param_config(I2C_NUM_0, &conf);
ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &conf));

2.2 安装驱动

2.2.1 i2c_driver_install

esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode,size_t slv_rx_buf_len, size_t slv_tx_buf_len, int intr_alloc_flags);

作用:安装 I²C 驱动程序,使配置生效。

参数:

i2c_num: I²C 控制器编号

mode: 通信模式(I2C_MODE_MASTER 或 I2C_MODE_SLAVE)

slv_rx_buf_len / slv_tx_buf_len: 从机接收/发送缓冲区大小(主机模式下设为 0)

intr_alloc_flags: 中断分配标志(通常设为 0)

返回值:成功返回 ESP_OK

2.2.2 案例说明

i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0);

2.3 通信操作

2.3.1 i2c_cmd_link_create

 i2c_cmd_handle_t i2c_cmd_link_create();

作用:创建一个 I²C 命令链接句柄,用于构建一次传输过程。
返回值:返回句柄,用于后续写入、读、发送起始信号等操作。

2.3.2 i2c_master_start()

esp_err_t i2c_master_start(i2c_cmd_handle_t cmd_handle);

作用:添加 I²C 起始条件(Start condition),开启通信。
参数:命令句柄 cmd_handle
必须是第一个操作

2.3.3 i2c_master_write_byte()

esp_err_t i2c_master_write_byte(i2c_cmd_handle_t cmd_handle, uint8_t data, bool ack_en);

作用:写入一个字节(通常是地址 + 读写位,或数据)
参数:
data: 要写的字节
ack_en: 是否期望 ACK 应答(设为 true)

2.3.4 i2c_master_write()

esp_err_t i2c_master_write(i2c_cmd_handle_t cmd_handle, const uint8_t *data,size_t data_len, bool ack_en);

作用:连续写多个字节数据

参数:

data: 数据指针

data_len: 长度

ack_en: 每个字节是否检查 ACK

2.3.5 i2c_master_read()

esp_err_t i2c_master_read(i2c_cmd_handle_t cmd_handle, uint8_t *data,size_t data_len, i2c_ack_type_t ack);

作用:读取多个字节的数据

参数:

data: 接收缓冲区

ack: 最后一个字节是否发送 ACK(通常最后一个字节发送 NACK)

2.3.6 i2c_master_stop()

esp_err_t i2c_master_stop(i2c_cmd_handle_t cmd_handle);

作用:添加停止条件(Stop condition),终止通信

2.3.7 i2c_master_cmd_begin()

esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle,TickType_t ticks_to_wait);

作用:执行上述构建好的命令链

参数:

ticks_to_wait: 超时时间(如 pdMS_TO_TICKS(1000) 表示等待 1000 ms)

2.3.8 i2c_cmd_link_delete()

esp_err_t i2c_cmd_link_delete(i2c_cmd_handle_t cmd_handle);

作用:释放命令链占用的内存资源

2.4 写数据

esp_err_t i2c_master_write_slave(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, size_t len) {i2c_cmd_handle_t cmd = i2c_cmd_link_create();i2c_master_start(cmd);i2c_master_write_byte(cmd, (dev_addr << 1) | I2C_MASTER_WRITE, true);i2c_master_write_byte(cmd, reg_addr, true);i2c_master_write(cmd, data, len, true);i2c_master_stop(cmd);esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);i2c_cmd_link_delete(cmd);return ret;
}

2.5 读数据

esp_err_t i2c_master_read_slave(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, size_t len) {i2c_cmd_handle_t cmd = i2c_cmd_link_create();i2c_master_start(cmd);i2c_master_write_byte(cmd, (dev_addr << 1) | I2C_MASTER_WRITE, true);i2c_master_write_byte(cmd, reg_addr, true);i2c_master_start(cmd);i2c_master_write_byte(cmd, (dev_addr << 1) | I2C_MASTER_READ, true);if (len > 1) {i2c_master_read(cmd, data, len - 1, I2C_MASTER_ACK);}i2c_master_read_byte(cmd, data + len - 1, I2C_MASTER_NACK);i2c_master_stop(cmd);esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);i2c_cmd_link_delete(cmd);return ret;
}

3 其他

3.1 SP_ERROR_CHECK 宏详解

ESP_ERROR_CHECK 是 ESP-IDF 中一个非常有用的错误处理宏,它用于检查 ESP-IDF 函数的返回值并自动处理错误。

基本功能

ESP_ERROR_CHECK 宏会检查传入的表达式(通常是函数调用)的返回值.

如果返回值不是 ESP_OK(即发生了错误),打印错误信息(包括错误代码和错误位置),调用 abort() 终止程序执行

// 普通方式
esp_err_t err = i2c_param_config(I2C_NUM_0, &conf);
if (err != ESP_OK) {ESP_LOGE(TAG, "i2c_param_config failed: %s", esp_err_to_name(err));return;
}// 使用 ESP_ERROR_CHECK 简化
ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &conf));
http://www.xdnf.cn/news/4260.html

相关文章:

  • VMware Fusion安装win11 arm;使用Mac远程连接到Win
  • IBM BAW(原BPM升级版)使用教程:基本概念
  • 设备管理系统的功能架构与核心价值
  • Jesse James Garrett 用户体验方法论
  • 全格式文档转 Markdown 工具,Docker 一键部署,支持 API 调用
  • C# 实现PLC数据自动化定时采集与存储(无需界面,自动化运行)
  • 算法 | 长颖燕麦优化算法AOO,算法原理,公式,深度解析+性能实测(Python代码)
  • linux -c程序开发
  • 双目标清单——AI与思维模型【96】
  • 高等数学第四章---不定积分(§4.3分部积分法4.4有理真分式函数的不定积分)
  • 应对联网汽车带来的网络安全挑战
  • FTPS和SFTP(文件传输安全协议)
  • 拨叉831003加工工艺及钻φ22花键底孔夹具设计
  • 量子跃迁:破解未来计算的“时空密码”​
  • 如何在vscode中set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`
  • Linux下的c/c++开发之操作mysql数据库
  • 【东枫科技】代理英伟达产品:DPU
  • Android View#post()源码分析
  • Android 中解决 annotations 库多版本冲突问题
  • 网络安全等级保护有关工作事项[2025]
  • BGP优化
  • 【计算机网络-应用层】HTTP服务器原理理解以及C++编写
  • 从设备交付到并网调试:CET中电技术分布式光伏全流程管控方案详解
  • QT异步线程通信
  • Linux 更改内存交换 swap 为 zram 压缩,减小磁盘写入
  • Android学习总结之Java和kotlin区别
  • Listremove数据时报错:Caused by: java.lang.UnsupportedOperationException
  • 深度解读 ARM 全新白皮书——《重塑硅基:AI 时代的新基石》
  • RabbitMQ-api开发
  • 美团Java高级配送员面经分享|玩梗版