1. I2C协议基础:从一根线到两根线的故事
各位同学,咱们今天聊聊I2C。这玩意儿在嵌入式开发里太常见了——传感器、EEPROM、ADC、显示屏,十有八九都用它。我刚开始学单片机那会儿,总觉得I2C挺玄乎,两根线就能挂一堆设备,怎么做到的?后来踩了几个坑,才真正搞明白。
说白了,I2C就是飞利浦(现在叫NXP)在80年代搞出来的一种串行通信总线。它只靠两根线——SDA(数据线)和SCL(时钟线)——就能让主设备和从设备之间传数据。你想想看,要是用并行总线,8位数据就得8根线,再加控制信号,板子上全是飞线,多头疼。
核心要点:I2C是同步、半双工、多主从的串行总线。两根线搞定一切。
1.1 物理层特性:开漏输出与上拉电阻
先看物理层。SDA和SCL都是开漏输出结构。什么叫开漏?就是MOS管的漏极直接接到引脚上,没有内部上拉。输出低电平时,管子导通,引脚拉低;输出高电平时,管子截止,引脚悬空。
嗯,这里要注意——悬空的状态是不确定的。所以必须在外部接上拉电阻,把引脚拉到高电平。这样总线空闲时,SDA和SCL都是高电平。
我个人习惯:4.7kΩ上拉电阻是万金油,100kHz标准模式基本都能用。如果总线电容大(线长、设备多),换成2.2kΩ;如果追求低功耗,可以试试10kΩ。但别超过10kΩ,否则上升沿太慢,波形会变“圆”。
开漏结构有个好处:线与。多个设备可以同时拉低总线,不会短路。任何一个设备拉低,总线就是低电平。这为后面讲的多主机仲裁打下了基础。
| 参数 | 标准模式 (100kHz) | 快速模式 (400kHz) | 高速模式 (3.4MHz) |
|---|---|---|---|
| 上拉电阻典型值 | 4.7kΩ | 2.2kΩ | 1kΩ 或更小 |
| 总线电容上限 | 400pF | 400pF | 100pF |
| 上升时间 | ≤1000ns | ≤300ns | ≤120ns |
我在项目里遇到过一件事:一块板子上挂了8个I2C设备,线长大概30cm,用4.7kΩ上拉,400kHz模式下SCL波形上升沿明显变缓,偶尔通信失败。换成2.2kΩ后,波形干净了,问题解决。所以,上拉电阻不是随便选的,得根据总线负载算一下。
1.2 协议层:起始、停止、数据与应答
物理层搞明白了,咱们看协议层。I2C的协议其实就四个核心动作:起始条件、停止条件、数据传送、应答机制。把这四个搞懂,I2C通信你就掌握了八成。
1.2.1 起始条件 (START)
SCL为高电平时,SDA从高电平跳变到低电平。这就是起始条件。
为什么要这么设计?因为SCL高电平时,SDA本应稳定不变。SDA突然变低,就是一个“特殊信号”,告诉所有从设备:注意,要开始传数据了。
我曾经踩过的坑:在STM32上用GPIO模拟I2C时,起始条件的时序没卡好——SCL拉高后,SDA拉低的保持时间太短。结果从设备根本没识别到起始信号,后续所有数据都白传。后来用示波器一看,SDA下降沿离SCL上升沿才几十纳秒,根本不够。标准模式要求至少4.7μs的建立时间。
1.2.2 停止条件 (STOP)
SCL为高电平时,SDA从低电平跳变到高电平。这就是停止条件。
跟起始条件正好相反。从设备检测到这个信号,就知道本次传输结束了,可以释放总线。
1.2.3 数据有效性
数据怎么传?规则很简单:
- SCL为高电平时,SDA上的数据必须稳定(不能变化)
- SCL为低电平时,SDA可以变化(准备下一位数据)
说白了,SCL高电平是“采样窗口”,SCL低电平是“数据切换窗口”。每个SCL时钟脉冲传1位数据,先传最高位(MSB),再传低位。
你想想看,如果SCL高电平时SDA还在跳变,接收方该采样哪个电平?所以这个规则保证了数据采样的确定性。
1.2.4 应答机制 (ACK/NACK)
每传完8位数据(一个字节),第9个SCL时钟周期就是应答位。
- ACK (应答):接收方在第9个时钟周期拉低SDA,表示“收到,请继续”
- NACK (非应答):接收方在第9个时钟周期保持SDA高电平,表示“别再发了”或“我没准备好”
应答机制是I2C可靠性的关键。发送方每发一个字节,都要等接收方回应。如果收到NACK,发送方就知道出问题了——要么地址不对,要么从设备忙,要么传输结束。
实战经验:调试I2C设备时,第一个要看的信号就是应答位。如果从设备地址发出去后,第9个时钟SDA还是高电平,说明从设备没响应。这时候别急着查代码,先量一下从设备的供电和上拉电阻。
1.3 完整数据传输流程
把上面四个动作串起来,一次完整的I2C写操作是这样的:
- 主设备发送起始条件
- 主设备发送7位从设备地址 + 1位读写位(0表示写)
- 从设备回复ACK
- 主设备发送1字节寄存器地址
- 从设备回复ACK
- 主设备发送1字节数据
- 从设备回复ACK
- ……(可以继续发更多数据)
- 主设备发送停止条件
读操作类似,只是读写位改成1,而且最后主设备要发NACK告诉从设备“别发了”。
1.4 知识结构图:I2C协议全景
下面这张图把I2C协议的核心要素串起来了。你可以把它当作本章的“思维导图”。
1.5 本章小结
I2C协议的基础就这些。总结一下:
- 物理层:开漏输出 + 上拉电阻,实现线与逻辑
- 起始/停止:SCL高电平时SDA的跳变沿,是通信的“开始”和“结束”信号
- 数据有效性:SCL高电平采样,SCL低电平切换,MSB先行
- 应答机制:第9个时钟,ACK表示继续,NACK表示停止