1. I2C协议基础概述
各位同学好。今天咱们正式开始聊I2C时钟拉伸对通信可靠性的影响。不过别急,先得把地基打牢——I2C协议本身长什么样、怎么握手、怎么传数据,这些弄不清楚,后面讲时钟拉伸你听得也糊涂。我最早接触I2C是在一个温湿度传感器项目上,当时连起始条件都忘了判断,抓了三天波形才发现是SCL被拉死了。嗯,从那以后我再也不敢跳过基础了。
1.1 I2C总线特点
I2C(Inter-Integrated Circuit)是飞利浦(现NXP)在1980年代发明的同步串行总线。它只有两根线:串行数据线SDA、串行时钟线SCL。靠两线完成多主多从通信,你想想看,这得多巧妙。每条线上都有上拉电阻,空闲时都是高电平。
- 同步串行:时钟由主设备产生,从设备只能在时钟边沿采样或输出。
- 多主多从:多个设备可以挂在同一条总线上,每个设备有唯一7位或10位地址。
- 低引脚数:两线搞定,省IO口,特别适合嵌入式和传感器场景。
- 速率可调:标准模式100kbps,快速模式400kbps,高速模式3.4Mbps。
个人习惯:我设计I2C从设备时,一定会检查SCL空闲高电平时间是否满足最小保持时间。很多同学只关注速率,忽略了时序窗口,导致通信间歇性失败。这点后面讲时钟拉伸时还会再提。
1.2 电气连接
I2C总线用开漏输出结构。什么意思呢?就是每个设备的SDA和SCL引脚内部只能拉到GND,不能主动输出高电平。高电平由外部上拉电阻提供。这样做的好处是多个设备可以“线与”——谁都可以把线拉低,谁都不怕冲突。
| 参数 | 标准模式 | 快速模式 | 高速模式 |
|---|---|---|---|
| 上拉电阻典型值 | 4.7kΩ | 1.5kΩ~2.2kΩ | 0.5kΩ~1.0kΩ |
| 总线电容上限 | 400pF | 400pF | 100pF |
| 最大从设备数 | 由地址和电容决定 | 由地址和电容决定 | 由地址和电容决定 |
我曾经踩过的坑:在一条长走线的I2C总线上用了10kΩ上拉,结果上升沿缓得跟乌龟一样,SCL边沿变慢,从设备采样出错。后来改成2.2kΩ才稳定。记住,上拉电阻不是越大越好,要匹配总线电容。
1.3 起始条件与停止条件
I2C通信的开始和结束有特定的信号,叫起始条件(S)和停止条件(P)。其实这两个信号才是协议里最核心的同步标记。
- 起始条件(S):SCL为高电平时,SDA从高切换到低。标志总线从空闲变成忙碌。
- 停止条件(P):SCL为高电平时,SDA从低切换到高。标志总线从忙碌变回空闲。
为什么我强调这个?因为时钟拉伸现象就发生在一个起始条件之后,从设备在SCL低电平时拉低SCL不放,导致主设备无法产生下一个时钟脉冲。这个咱们后面会详细拆解。
记住一条原则:任何总线上的数据变化都必须发生在SCL为低时(除了起始和停止)。否则从设备会误判为异常起始或停止,直接跑飞。我在多主环境中就吃过这个亏——主设备1发完地址后,主设备2抢在SCL变高前改变了SDA,结果两个设备都乱了套。
1.4 数据格式
I2C的数据传输以字节为单位,每字节8位,后面紧跟一个应答位(ACK/NACK)。发送方在SCL的第9个脉冲期间释放SDA,接收方拉低SDA表示ACK,保持高电平表示NACK。嗯,这里有个细节:地址字节的最后一bit是读写方向(0写1读)。
// I2C主机写一个字节到从设备(伪代码)
1. 主产生起始条件(S)
2. 主发送7位从地址 + 写位(0)
3. 从设备应答ACK(拉低SDA)
4. 主发送8位数据
5. 从设备应答ACK
6. 主产生停止条件(P)
当时钟拉伸发生时,步骤3或步骤5可能被无限拖延:从设备不产生ACK,而是拉低SCL不放。主设备检测到SCL被拉低后会等待,直到从设备释放SCL才继续。这正是时钟拉伸的本质——从设备主动拉长时钟周期。
1.5 本章知识体系
为了让你对I2C基础有个全局视图,我画了张框架图。这张图把总线特点、电气连接、起始/停止条件、数据格式串到一起,并且标出了时钟拉伸在整个流程中的触发位置。你对照着看,后面几章就更有方向感了。
这张图把你今天学到的所有知识都串起来了:从左边的总线特点、电气连接、起始/停止条件,汇聚到核心的“数据格式”,再引出时钟拉伸触发点。你会发现,时钟拉伸不是凭空出现的,它就藏在ACK阶段里。