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

ESP32学习-I2C(IIC)通信详解与实践

I2C(又称 IIC)是嵌入式开发中最常见的通信协议之一,广泛应用于传感器、显示屏、存储芯片等设备。ESP32 提供了灵活的 I2C 硬件接口,今天我们就来深入学习 I2C 的基本概念、使用流程及 ESP32 实践。


一、基本概念

✅ 什么是 I2C?

I2C(Inter-Integrated Circuit) 是一种由 Philips(飞利浦)发明的串行通信协议,用于主控与多个从设备之间的数据通信。它具有以下特点:

特性说明
通信方式串行通信(同步)
连接方式只需两根信号线:SCL(时钟)和 SDA(数据)
主从结构一个主控(如 ESP32)控制多个从设备
唯一地址每个从设备有唯一的 7 位或 10 位地址
半双工通信数据是双向的,但一次只能一个方向传输


❓ I2C 与 SPI 的区别

对比项I2CSPI
信号线2 根(SDA, SCL)4 根(MOSI, MISO, SCLK, CS)
速率一般 100kHz~400kHz更高,几 MHz 甚至几十 MHz
结构多主多从通常为一主多从(点对点)
成本引脚少,布线简单引脚多,布线复杂
应用场景简单控制/低速设备,如传感器高速传输,如屏幕、Flash


二、使用流程(ESP32 I2C 主机模式)

ESP32 的 I2C 驱动使用 主设备模式(Master) 最多可挂载两个 I2C 接口(I2C_NUM_0 和 I2C_NUM_1),流程如下:

  1. 配置 I2C 接口参数(GPIO、速率等)

  2. 安装 I2C 驱动

  3. 使用 i2c_master_write / read 等函数读写设备

  4. 完成通信后可卸载驱动(可选)


三、I2C 端口配置

ESP32 的 I2C 引脚是可选的(不是固定的),你可以选择任意空闲 GPIO 作为 SDA 和 SCL,只要设备支持。

例如我们选:

  • SDA:GPIO21

  • SCL:GPIO22

#include "driver/i2c.h"#define I2C_MASTER_NUM              I2C_NUM_0   // 使用 I2C0
#define I2C_MASTER_SDA_IO           21
#define I2C_MASTER_SCL_IO           22
#define I2C_MASTER_FREQ_HZ          400000      // 400kHz
#define I2C_MASTER_TX_BUF_DISABLE   0
#define I2C_MASTER_RX_BUF_DISABLE   0void i2c_master_init()
{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_NUM, &conf);  // 选定iic控制器为I2C0,再配置对应端口信息i2c_driver_install(I2C_MASTER_NUM, conf.mode,I2C_MASTER_RX_BUF_DISABLE,I2C_MASTER_TX_BUF_DISABLE, 0);
}

🔍 SDA/SCL 需要接 上拉电阻(如 4.7kΩ),部分板子已内置。

🔧 I2C_MASTER_RX_BUF_DISABLETX_BUF_DISABLE 是什么?

这两个宏值为 0,表示:

  • 你不需要缓冲区(你是主机,数据是你主动读写的,不需要控制器中先存一堆数据)

  • 如果你要使用从机模式(I2C_MODE_SLAVE),那就必须配置非零缓冲区长度


💡 一句话总结

i2c_driver_install() 的作用是真正启用 I2C 控制器,它必须在 i2c_param_config() 之后调用,且主机模式下接收/发送缓冲区长度必须设为 0。


四、源代码示例(读写一个设备寄存器)

假设我们有一个从设备地址为 0x68,我们要向其写入一个寄存器,然后再读回来:

#define DEVICE_ADDR  0x68
#define REGISTER_ADDR 0x01// 写一个字节到指定寄存器
esp_err_t i2c_write_byte(uint8_t reg_addr, uint8_t data)
{i2c_cmd_handle_t cmd = i2c_cmd_link_create();i2c_master_start(cmd);i2c_master_write_byte(cmd, (DEVICE_ADDR << 1) | I2C_MASTER_WRITE, true);i2c_master_write_byte(cmd, reg_addr, true);i2c_master_write_byte(cmd, data, 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;
}// 从指定寄存器读取一个字节
esp_err_t i2c_read_byte(uint8_t reg_addr, uint8_t *data)
{i2c_cmd_handle_t cmd = i2c_cmd_link_create();i2c_master_start(cmd);i2c_master_write_byte(cmd, (DEVICE_ADDR << 1) | I2C_MASTER_WRITE, true);i2c_master_write_byte(cmd, reg_addr, true);i2c_master_start(cmd); // 重启i2c_master_write_byte(cmd, (DEVICE_ADDR << 1) | I2C_MASTER_READ, true);i2c_master_read_byte(cmd, data, 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;
}

五、问题

1.为什么既要指定iic控制器,又可以随意选择端口,STM32中的硬件IIC不是直接与端口绑定了吗?

该处是硬件IIC实现,ESP32几乎所有引脚都是通用的,因此需要手动指定。而stm32固定就映射好了,因此可以不用指定。


六、总结

I2C 是 ESP32 最常用的外设通信协议之一,掌握它是开发各种传感器模块的基础。

http://www.xdnf.cn/news/16894.html

相关文章:

  • Azure DevOps — Kubernetes 上的自托管代理 — 第3部分
  • GB 44496-2024《汽车软件升级通用技术要求》对行业从业者的变革性影响
  • 13-day10生成式任务
  • 从Docker衔接到导入黑马商城以及前端登录显示用户或密码错误的相关总结(个人理解,仅供参考)
  • 【AI编程工具IDE/CLI/插件专栏】-国外IDE与Cursor能力对比
  • 【openlayers框架学习】九:openlayers中的交互类(select和draw)
  • 【LLM】 BaseModel的作用
  • MySQL面试题及详细答案 155道(021-040)
  • Spring Cloud微服务中的内存泄漏问题定位与解决方案
  • SelectDB数据库,新一代实时数据仓库的全面解析与应用
  • Linux 环境下 Docker 安装与简单使用指南
  • 百度招黑产溯源安全工程师
  • 《软件测试与质量控制》实验报告二 单元测试
  • MSQL-聚簇索引与非聚簇索引的比较
  • Python编程基础与实践:Python文件处理入门
  • SpringBoot 信用卡检测、OpenAI gym、OCR结合、DICOM图形处理、知识图谱、农业害虫识别实战
  • 【7.5 Unity AssetPostprocessor】
  • 【自动化运维神器Ansible】YAML支持的数据类型详解:构建高效Playbook的基石
  • linux ext4缩容home,扩容根目录
  • Trae + Notion MCP:将你的Notion数据库升级为智能对话机器人
  • 元宇宙重构未来交通新图景
  • 无人机光伏巡检漏检率↓78%!陌讯多模态融合算法实战解析
  • 机试备考笔记 2/31
  • Agentic RAG:自主检索增强生成的范式演进与技术突破
  • 深入 Go 底层原理(二):Channel 的实现剖析
  • 深入 Go 底层原理(十四):timer 的实现与高性能定时器
  • cuda编程笔记(12)--学习cuFFT的简单使用
  • 【机器学习】非线性分类算法(上):KNN(基于距离相似度)与朴素(特征独立)贝叶斯(基于概率统计)
  • Lock 接口及实现类详解:从 ReentrantLock 到并发场景实践
  • Node.js 操作 MongoDB