一、I2C协议概述:从历史到物理层
各位同学,咱们今天正式开讲I2C。这个协议在嵌入式世界里太常见了——传感器、EEPROM、ADC、触摸屏,几乎每个板子上都能找到它的影子。我最早接触I2C是在做一款工业采集卡的时候,当时被一根线上挂8个从机折腾得够呛。从那以后,我对这个协议就多了几分敬畏。
1.1 I2C总线历史:飞利浦的“小发明”
I2C全称是Inter-Integrated Circuit,字面意思就是“集成电路之间的总线”。1982年,飞利浦半导体(现在的NXP)为了简化电视机的内部通信,搞出了这个东西。你想想看,那时候的电路板走线密密麻麻,能省两根线都是天大的好事。
发展历程其实很简单:
- 1982年:飞利浦推出I2C总线,最初只用在自家产品里
- 1992年:发布第一版标准化规范,支持100kHz标准模式
- 1998年:加入400kHz快速模式
- 2007年:NXP推出1MHz快速模式+(Fm+)
- 2012年:高速模式达到3.4MHz,超快速模式达到5MHz
我个人习惯把I2C比作“串行通信里的瑞士军刀”——功能多、体积小、够用。虽然现在SPI、UART各有拥趸,但I2C在低引脚数、多从机场景下依然无可替代。
核心认知:I2C不是最快的,也不是最远的,但它是最“省线”的。两根线搞定所有通信,这在板级设计中是巨大的优势。
1.2 物理层特性:SDA和SCL的故事
I2C总线只有两根线:
- SDA(Serial Data Line):数据线,双向传输
- SCL(Serial Clock Line):时钟线,由主机驱动
这两根线都是开漏输出结构。什么叫开漏?说白了,就是芯片只能把线拉低,不能主动拉高。拉高的工作交给外部的上拉电阻完成。
为什么这么设计?我举个例子你就明白了。假设总线上挂了3个设备,如果每个设备都能主动拉高,那一个设备输出高、另一个输出低,直接就短路了。开漏结构配合“线与”逻辑,任何设备拉低总线,整条线就是低电平——这才是多主机通信的基础。
避坑指南:我曾经在一个项目里把SDA和SCL接反了,结果调了两天才发现。嗯,别笑,很多人犯过这个错。上电前用万用表量一下,确认SDA接SDA、SCL接SCL,这是最基本的检查。
1.3 电气特性与上拉电阻:选对阻值很重要
上拉电阻是I2C总线里最容易忽视、也最容易出问题的地方。阻值选大了,信号上升沿变缓,通信容易出错;选小了,功耗增加,驱动能力可能不够。
标准I2C规范里,上拉电阻的推荐值如下:
| 模式 | 最大频率 | 推荐上拉电阻(5V) | 推荐上拉电阻(3.3V) |
|---|---|---|---|
| 标准模式(Sm) | 100 kHz | 4.7 kΩ | 4.7 kΩ |
| 快速模式(Fm) | 400 kHz | 2.2 kΩ | 1.8 kΩ |
| 快速模式+(Fm+) | 1 MHz | 1.0 kΩ | 680 Ω |
| 高速模式(Hs) | 3.4 MHz | 200 Ω | 200 Ω |
实际选型时,我一般按这个公式估算:
R_min = Vcc / I_ol_max
R_max = t_r / (0.8473 × C_bus)
其中:
- Vcc:总线电压
- I_ol_max:器件最大灌电流(通常3-20 mA)
- t_r:允许的最大上升时间(标准模式1000 ns,快速模式300 ns)
- C_bus:总线总电容(包括引脚、走线、过孔)
重要提醒:总线电容是上拉电阻选型的最大变量。每增加一个从设备,总线电容大约增加5-10 pF。如果总线上挂了8个从机,再加上PCB走线,电容很容易超过100 pF。这时候还用4.7 kΩ上拉,上升沿会变得很慢,通信必然失败。
我做过一个项目,板子上挂了6个传感器,总线上拉用了10 kΩ。结果400kHz模式下数据经常出错,用示波器一看,SCL的上升沿都快赶上半个时钟周期了。换成2.2 kΩ后,问题立刻解决。所以,上拉电阻不是随便焊一个就能用的。
1.4 电气参数速查表
下面这几个参数,做驱动开发时经常要用到:
| 参数 | 标准模式 | 快速模式 | 说明 |
|---|---|---|---|
| SCL时钟频率 | 100 kHz | 400 kHz | 主机控制 |
| SCL低电平时间 | ≥ 4.7 μs | ≥ 1.3 μs | 时钟低电平保持 |
| SCL高电平时间 | ≥ 4.0 μs | ≥ 0.6 μs | 时钟高电平保持 |
| 数据建立时间 | ≥ 250 ns | ≥ 100 ns | SDA在SCL上升沿前稳定 |
| 数据保持时间 | ≥ 0 ns | ≥ 0 ns | SDA在SCL下降沿后保持 |
| 总线电容 | ≤ 400 pF | ≤ 400 pF | 包括所有负载 |
这些时序参数在写驱动时,尤其是做软件模拟I2C时,必须严格遵守。我见过有人用GPIO模拟I2C,延时随便写个几微秒,结果某些器件就是死活不响应——时序不对,协议层再对也没用。
1.5 I2C总线结构图
下面这张图展示了I2C总线的典型结构。主机和多个从机通过SDA和SCL连接,每个从机有唯一的地址。上拉电阻挂在总线上,保证空闲时总线为高电平。
这张图里,主机负责产生时钟、发起通信;从机监听地址、响应数据。上拉电阻Rₚ挂在VCC和总线之间,保证空闲时总线电平为高。每个从机都有唯一地址,主机通过地址来选择要通信的对象。
个人经验:画PCB时,SDA和SCL走线尽量等长、平行,远离时钟信号和电源开关管脚。我吃过一次亏——I2C走线紧挨着一路DC-DC的电感,结果通信时断时续,查了三天才发现是电磁干扰。后来加了一根地线隔离,世界清净了。
1.6 本章小结
这一章我们聊了I2C的来龙去脉、物理层原理和电气参数。记住几个关键点:
- I2C是两根线的串行总线,SDA传数据,SCL传时钟
- 开漏输出 + 上拉电阻是I2C的核心结构
- 上拉电阻选型要看总线电容和工作频率
- 时序参数是驱动开发的硬约束,不能马虎