2. I2C总线协议详解:起始条件、停止条件、数据有效性、应答机制与三种模式

I2C总线,说白了就是两根线(SCL时钟线、SDA数据线)搞定多个设备通信。我刚开始接触时也觉得简单,但真正做低功耗项目时才发现,协议细节没吃透,功耗根本压不下去。咱们今天就把I2C的骨架子拆开看。

2.1 起始条件与停止条件

总线空闲时,SCL和SDA都是高电平。这是规矩,谁也别动。

起始条件(S): SCL为高电平时,SDA从高切换到低。这个下降沿告诉所有从机:“注意,要开始传数据了!”

停止条件(P): SCL为高电平时,SDA从低切换到高。这个上升沿表示传输结束,总线释放。

关键点: 起始和停止条件必须由主机产生。从机没这个权限。

我的习惯: 写驱动时,我会把起始和停止条件封装成独立函数。这样代码复用率高,调试也方便。比如检测到总线忙时,先发一个停止条件复位总线,再重新开始。

避坑指南: 我曾经在高速模式下漏掉了起始条件的建立时间(tHD;STA),结果从机死活不响应。查了两天,发现是SCL下降沿到SDA下降沿的时间间隔不够。记住:高速模式下这个时间只有0.6μs,别踩雷。

2.2 数据有效性

I2C的数据采样有个铁律:SDA上的数据必须在SCL低电平时变化,在SCL高电平时被采样。

为什么这样设计?说白了就是为了抗干扰。SCL高电平时SDA保持稳定,接收方在这个窗口内采样,误码率最低。

具体规则:

  • SCL为低电平:SDA允许变化(数据准备阶段)
  • SCL为高电平:SDA必须稳定(数据采样阶段)
  • 每个SCL脉冲传输1位数据
  • MSB(最高位)先传

你想想看,如果SCL高电平时SDA还在跳变,接收方采到的数据就是错的。我见过不少新手在这里翻车,尤其是做软件模拟I2C时,时序控制不好就容易出问题。

2.3 应答机制

I2C的应答机制是它的精髓。每传输完一个字节(8位),接收方必须在第9个SCL周期拉低SDA,表示“收到了”。

应答类型:

应答类型 SDA状态(第9个SCL) 含义
ACK(应答) 低电平 接收成功,继续传输
NACK(非应答) 高电平 接收失败,或传输结束

注意: 应答信号由接收方产生。主机发送数据时,从机应答;主机接收数据时,主机应答。

我做过一个项目,从机是温度传感器,读数据时它突然不ACK了。查了半天,原来是传感器正在转换温度,忙状态不响应。解决办法:读之前先查状态寄存器,或者加超时重试。

2.4 标准模式、快速模式与高速模式

I2C有三种速度模式,选哪个直接影响功耗和吞吐量。咱们直接看对比:

参数 标准模式(Sm) 快速模式(Fm) 高速模式(Hs)
最大时钟频率 100 kHz 400 kHz 3.4 MHz
最大传输速率 100 kbit/s 400 kbit/s 3.4 Mbit/s
上拉电阻典型值 4.7 kΩ 1.5 kΩ 0.5 kΩ
总线电容限制 400 pF 400 pF 100 pF
从机地址 7位/10位 7位/10位 7位/10位

标准模式: 最常用,兼容性最好。功耗也最低,因为频率低,动态功耗小。我一般用在电池供电的传感器采集场景。

快速模式: 速度提升4倍,但上拉电阻要减小,静态功耗会增大。适合对吞吐量有要求的场景,比如音频数据流。

高速模式: 速度飙到3.4 MHz,但限制很多。总线电容不能超过100 pF,意味着走线要短,从机数量要少。而且高速模式下需要额外的“高速使能”信号(SDAH和SCLH),不是所有MCU都支持。

避坑指南: 我曾经在一个项目里把快速模式的上拉电阻用成了4.7 kΩ,结果SCL上升沿太慢,波形像正弦波,从机采样出错。记住:频率越高,上拉电阻越小,否则边沿时间会超标。

2.5 三种模式的选择策略

选哪种模式,我一般看三个因素:

  1. 功耗预算: 电池供电优先标准模式,频率低,动态功耗小
  2. 数据量: 每次传输超过几十字节,考虑快速模式或高速模式
  3. 总线长度: 走线超过10 cm,老老实实用标准模式,别挑战高速

我的经验: 低功耗设计里,I2C的功耗大头其实不在传输,而在上拉电阻的静态电流。标准模式下4.7 kΩ上拉,3.3 V供电,静态电流约0.7 mA。如果总线空闲时间长,这个电流很可观。我一般会在空闲时关掉上拉电阻的电源,或者用GPIO模拟上拉。

2.6 知识结构图

下面这张图把I2C协议的核心要素串起来了,方便你记忆:

I2C总线协议核心结构图 I2C总线协议核心要素 I2C总线 起始/停止条件 SDA边沿触发 数据有效性 SCL高电平采样 应答机制 第9个SCL脉冲 三种速度模式 Sm / Fm / Hs 设计要点 起始/停止条件决定传输边界 | 数据有效性保证采样正确 | 应答机制实现流控 | 速度模式影响功耗与吞吐量 低功耗设计:优先标准模式,合理选择上拉电阻,空闲时关断上拉电源

2.7 实战要点总结

做I2C低功耗设计,记住这几条:

  • 起始/停止条件: 每次传输前检查总线状态,避免冲突
  • 数据有效性: 确保SCL高电平时SDA稳定,特别是软件模拟I2C时
  • 应答机制: 从机不ACK时别死等,加超时处理
  • 速度模式: 能慢则慢,标准模式功耗最低
  • 上拉电阻: 根据速度和总线电容计算,别凭感觉选

我的习惯: 每次画板子前,我都会用示波器看I2C波形。SCL上升沿太缓就减小上拉电阻,有毛刺就加小电容滤波。嗯,这一步省不了,否则量产时哭都来不及。