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 三种模式的选择策略
选哪种模式,我一般看三个因素:
- 功耗预算: 电池供电优先标准模式,频率低,动态功耗小
- 数据量: 每次传输超过几十字节,考虑快速模式或高速模式
- 总线长度: 走线超过10 cm,老老实实用标准模式,别挑战高速
我的经验: 低功耗设计里,I2C的功耗大头其实不在传输,而在上拉电阻的静态电流。标准模式下4.7 kΩ上拉,3.3 V供电,静态电流约0.7 mA。如果总线空闲时间长,这个电流很可观。我一般会在空闲时关掉上拉电阻的电源,或者用GPIO模拟上拉。
2.6 知识结构图
下面这张图把I2C协议的核心要素串起来了,方便你记忆:
2.7 实战要点总结
做I2C低功耗设计,记住这几条:
- 起始/停止条件: 每次传输前检查总线状态,避免冲突
- 数据有效性: 确保SCL高电平时SDA稳定,特别是软件模拟I2C时
- 应答机制: 从机不ACK时别死等,加超时处理
- 速度模式: 能慢则慢,标准模式功耗最低
- 上拉电阻: 根据速度和总线电容计算,别凭感觉选
我的习惯: 每次画板子前,我都会用示波器看I2C波形。SCL上升沿太缓就减小上拉电阻,有毛刺就加小电容滤波。嗯,这一步省不了,否则量产时哭都来不及。