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基础有个全局视图,我画了张框架图。这张图把总线特点、电气连接、起始/停止条件、数据格式串到一起,并且标出了时钟拉伸在整个流程中的触发位置。你对照着看,后面几章就更有方向感了。

I2C协议基础与时钟拉伸触发位置 I2C协议基础框架(含时钟拉伸触发点) 总线特点 电气连接 起始条件 & 停止条件 数据格式 地址 + R/W + 数据 + ACK/NACK 时钟拉伸触发点 ACK阶段SCL被拉低 ⚠ 核心知识点 • I2C只有两根线:SDA(数据)、SCL(时钟) • 开漏输出 + 上拉电阻 → 线与逻辑,多设备可共存 • 起始/停止条件全由SDA在SCL高电平时跳变定义 • 时钟拉伸:从设备在ACK期间拉低SCL,让主设备等待(本节课核心)

这张图把你今天学到的所有知识都串起来了:从左边的总线特点、电气连接、起始/停止条件,汇聚到核心的“数据格式”,再引出时钟拉伸触发点。你会发现,时钟拉伸不是凭空出现的,它就藏在ACK阶段里。