I2C通信协议
I2C (Inter-Integrated Circuit) 通信协议,中文常读作“I-方-C”或者“I-二-C”。
如果说串口(UART)是 “一对一打电话”,那么 I2C 就是 “老师在教室里点名提问”。
它是一种 同步、半双工、带应答的总线协议。它的最大特点是: 省引脚!只需要两根线,就能挂载上百个设备。
1. 核心硬件架构:两根线走天下
I2C 只有两根信号线,所有设备都并联在这两根线上:
- SCL (Serial Clock):时钟线。
- 由 主机 (Master) 控制(通常是你的 STM32)。
- 就像老师手里的指挥棒,决定大家说话的 节奏⚠️。
- SDA (Serial Data):数据线。
- 数据传输的通道。
- 主机和从机都可以控制这根线(但在同一时刻只能有一个人说话,所以是 半双工)。
⚠️ 关键电路特性:开漏输出 + 上拉电阻
这是 I2C 最反直觉、也是最重要的物理特性:
- 开漏输出 (Open-Drain): I2C 的引脚无法主动输出高电平(1),它只能输出低电平(0)或者“放手”(高阻态)。
- 上拉电阻 (Pull-up Resistor): 总线上必须接两个电阻(通常 4.7kΩ)拉到 VCC。
- 效果:
- 当大家都不说话(都放手)时,电阻把电压拉高,总线是 高电平 (1)。
- 只要有一个设备把线拉低,整条线就变成了 低电平 (0)。
- 比喻: 公交车上的拉手环。平时弹簧把它拉上去(高电平),谁想下车就用力把它拉下来(低电平)。这就是“线与”逻辑,防止短路。
2. 数据有效性:什么时候能读/写?
这是写代码时最容易出错的时序问题。
- SCL = 1 (高电平) 时: SDA 必须保持稳定! 这时候接收方正在读取数据,如果你这时候变数据,对方会误以为是 Start 或 Stop 信号。
- SCL = 0 (低电平) 时: SDA 允许改变。 发送方只有趁着时钟是低电平的时候,赶紧把数据位(0或1)放上去。
| 状态 | SCL (时钟线) | SDA (数据线) | 含义 |
|---|---|---|---|
| 发送数据 | 低电平 | 可以变(准备 0 或 1) | 装填子弹(调整要发出的电平(数据0/1)) |
| 发送数据 | 高电平 | 不能变(必须稳定) | 发射/读取数据 |
| 开始信号 | 高电平 | 必须变(由高 -> 低) | 这是特殊的“开火”指令 |
| 停止信号 | 高电平 | 必须变(由低 -> 高) | 这是特殊的“停火”指令 |
- 主机发送数据:SCL和SDA都由主机控制
- 主机读取数据(从机发送数据):SCL还是由主机控制、SDA由从机控制。
总结:主机永远掌控 节奏。
3. 通信流程:老师点名的艺术
I2C 的通信过程非常讲究礼貌和规矩。假设 STM32 (主机) 要找 MPU6050 (从机) 说话:
在第 8 个数据位和第 9 个应答位之间,有一个“交接棒”,用来“放手”。 8+1 模式
第一步:起始信号 (Start) —— “同学们注意了!”
- 规则: SCL 保持高电平时
- 关键动作: SDA 由高变低 ⬇️(低电平)
- 只有主机能发出这个信号,这标志着总线被占用了。
第二步:呼叫地址 (Address) —— “MPU6050,在吗?”
每个 I2C 从机都有一个 唯一的 7位地址(比如 MPU6050 是
0x68)。主机发送 8 个位:7位地址 + 1位读写位。
- 最后一位是
0:表示我要 写数据给你。 - 最后一位是
1:表示我要从你那 读数据。
地址+读写位=8位,主机“放手”,SDA 由低变高 ⬆️(高阻态/高电平)
- 最后一位是
第三步:应答信号 (ACK/NACK) —— “到!”
- ACK (应答): 从机听到了自己的名字,会在第 9 个时钟周期立刻把 SDA 拉低 ⬇️(低电平)。主机检测到低电平,就知道“设备在位”。
- NACK (非应答): 如果没人理(SDA ⬆️ 保持高电平/高阻态),说明设备坏了或者不在。
第四步:传输数据 (Data) —— “这是你的作业”
- 主机发送(或接收)8 位数据。↗️↘️↙️↖️↙️↖️↙️↖️
- 在SCL每次高电平期间,SDA 必须保持稳定。
- 每发完一个字节,接收方都要回一个 ACK⬇️(低电平)。
第五步:停止信号 (Stop) —— “下课!”
- 规则: SCL 保持高电平时,SDA 从低变高 ⬆️(高阻态/高电平)。
- 结果: 大家都松手了,总线回到空闲的高电平。
节奏:8+1 模式
情况 A:主机写数据 (Master Write)
- SCL: 主机控制。
- 前 8 拍 (SDA): 主机 在跳舞(发数据)。
- 第 9 拍 (SDA): 从机 拉低(ACK)。
情况 B:主机读数据 (Master Read)
- SCL: 依然是 主机 控制(主机永远掌握时钟节奏)。
- 前 8 拍 (SDA): 从机 在跳舞(从机发送数据给主机)。
- 第 9 拍 (SDA): 主机 拉低(ACK)。
- 闭环:8 位数据传输 + 1 位应答(ACK)反馈,构成一次完整的 “读写数据交互”,缺一不可。
4. STM32 开发中的“软硬之争”
你在做 STM32 项目时,会面临两个选择:
方案 A:硬件 I2C (Hardware I2C)
- 原理: 使用 STM32 芯片内部的 I2C 外设。你配置好寄存器,把数据扔给它,它自动发波形。
- 优点: 速度快,不占用 CPU 资源(配合 DMA 更是起飞)。
- 缺点: STM32F1 系列的硬件 I2C 有著名的设计缺陷(Bug),很容易卡死(Busy 状态),导致程序跑飞。
- 现状: 在 F1 系列上,很多老工程师不敢用。但在 F4/H7 等新系列上已经修好了。
方案 B:软件 I2C (Software I2C / Bit-Banging) —— 强烈推荐新手使用
- 原理: 随便找两个普通的 GPIO 口,用代码控制翻转高低电平,模拟出 I2C 的时序。
GPIO_SetBits-> 拉高Delay_us-> 延时GPIO_ResetBits-> 拉低
- 优点: 极其稳定,逻辑完全可控,移植方便(换任何引脚、任何单片机都能用)。
- 缺点: 稍微占用一点 CPU 时间(微秒级,通常可忽略)。
总结
I2C 就是:
- 物理层: 2 根线 + 上拉电阻(开漏输出)。
- 链路层: 主机控制 SCL,谁说话谁控制 SDA。
- 协议层: 起始 -> 地址(含读写) -> 应答 -> 数据 -> 应答 -> 停止。