Skip to content

I2C通信协议

I2C (Inter-Integrated Circuit) 通信协议,中文常读作“I-方-C”或者“I-二-C”。

如果说串口(UART)是 “一对一打电话”,那么 I2C 就是 “老师在教室里点名提问”

它是一种 同步、半双工、带应答的总线协议。它的最大特点是: 省引脚!只需要两根线,就能挂载上百个设备。

1. 核心硬件架构:两根线走天下

I2C 只有两根信号线,所有设备都并联在这两根线上:

  1. SCL (Serial Clock):时钟线
    • 主机 (Master) 控制(通常是你的 STM32)。
    • 就像老师手里的指挥棒,决定大家说话的 节奏⚠️
  2. 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 就是:

  1. 物理层: 2 根线 + 上拉电阻(开漏输出)。
  2. 链路层: 主机控制 SCL,谁说话谁控制 SDA。
  3. 协议层: 起始 -> 地址(含读写) -> 应答 -> 数据 -> 应答 -> 停止