1. I2C协议基础:从一根线到一套生态

各位同学,咱们今天聊聊I2C。这玩意儿在嵌入式开发里太常见了——传感器、触摸屏、EEPROM、音频Codec,十有八九都挂在这两根线上。我刚开始做驱动时,总觉得I2C协议简单,不就是两根线嘛。结果有一次调一个触摸屏,死活读不到设备ID,折腾了两天才发现是应答时序差了半个时钟周期……嗯,从那以后我再也不敢小看这个“简单”协议了。

1.1 I2C总线的起源

I2C(Inter-Integrated Circuit)是飞利浦公司在1982年搞出来的。说白了,就是为了解决板级芯片之间的通信问题——那时候芯片引脚多、走线乱,飞利浦想了个办法:只用两根线,把所有外设串起来。

我个人习惯把I2C理解成“芯片间的电话线”。主设备拨号(起始条件),从设备接听(应答),然后开始通话(数据传输)。挂断(停止条件)后,其他人才能用这条线。

特性 说明
发明时间 1982年,飞利浦(现NXP)
物理层 2线制:SDA(数据线)+ SCL(时钟线)
拓扑结构 多主多从,总线式连接
最大速率 标准模式100kHz,快速模式400kHz,高速模式3.4MHz
最大设备数 受限于总线电容(通常不超过400pF)

1.2 物理层特性:SDA与SCL

I2C的物理层就两根线:SDA(串行数据线)和SCL(串行时钟线)。这两根线都是开漏输出,需要外部上拉电阻拉到VCC。

为什么用开漏?你想想看,如果多个设备同时拉低一根线,用推挽输出就直接短路了。开漏就不一样——谁想拉低就拉低,谁想释放就释放,大家共用一根线,互不打架。

关键参数:上拉电阻选择

上拉电阻太小,功耗大;太大,上升沿太慢。我一般按这个经验公式估算:

  • 标准模式(100kHz):4.7kΩ ~ 10kΩ
  • 快速模式(400kHz):1.5kΩ ~ 4.7kΩ
  • 高速模式(3.4MHz):几百Ω级别

具体选多大,还得看总线电容。我在T113上挂过6个I2C设备,总线电容大概150pF,用的4.7kΩ上拉,跑400kHz没问题。

避坑指南

我曾经遇到过一个问题:板子上I2C设备不多,但SCL波形上升沿特别缓。查了半天,发现是PCB走线太长,寄生电容太大。后来把上拉电阻从10kΩ换成3.3kΩ,波形立马干净了。所以——示波器是调I2C的必备工具,别省。

1.3 协议层:时序与握手

I2C的协议层其实就几个基本动作:起始、停止、数据收发、应答。把这些动作组合起来,就能完成一次完整的通信。

1.3.1 起始条件与停止条件

这两个条件定义了通信的边界:

  • 起始条件(S):SCL为高电平时,SDA从高电平切换到低电平
  • 停止条件(P):SCL为高电平时,SDA从低电平切换到高电平

说白了,起始条件就是“我要开始说话了”,停止条件就是“我说完了,你们聊”。

注意:起始和停止条件只能由主设备产生。从设备没有这个权限。如果从设备想主动发数据?不行,它只能等主设备来读。

1.3.2 数据有效性

I2C的数据传输有个铁律:数据在SCL高电平时有效,在SCL低电平时变化。

为什么这样设计?你想想看,如果数据在SCL高电平时变化,那接收方就搞不清楚当前到底是数据还是起始/停止条件了。所以协议规定:

  • SCL高电平期间,SDA必须保持稳定
  • SCL低电平期间,SDA可以变化(准备下一位数据)

每次传输8位数据(一个字节),高位在前(MSB first)。

1.3.3 应答机制

每发送完一个字节,接收方必须回复一个应答位(ACK)。这是I2C协议里我最喜欢的设计——每步都有反馈,出了问题立刻知道。

应答机制是这样的:

  1. 发送方在第9个时钟周期释放SDA(拉高)
  2. 接收方如果正常接收,在第9个时钟周期拉低SDA(ACK)
  3. 接收方如果不想接收或出错了,保持SDA高电平(NACK)

我在T113上调试I2C时,经常用逻辑分析仪看应答位。如果看到NACK,基本就是设备地址错了或者设备没上电。

1.4 7位地址与10位地址

I2C总线上每个设备都有一个唯一地址。地址分两种:7位和10位。

地址类型 地址范围 最大设备数 兼容性
7位地址 0x00 ~ 0x7F 112(保留16个) 所有设备都支持
10位地址 0x000 ~ 0x3FF 1024 需要主从设备都支持

7位地址是最常用的。地址的高4位通常由芯片厂商固定,低3位由硬件引脚决定。比如AT24C02的地址是0x50(固定)+ A2/A1/A0(引脚电平)。

10位地址用得少,我做了这么多年驱动,也就用过一两次。它的格式比较特殊:

  • 第一个字节:1111 0XX + R/W(XX是地址的高2位)
  • 第二个字节:地址的低8位

说白了,10位地址就是用一个特殊标记(1111 0)告诉从设备:“后面还有8位地址,别急着应答”。

经验之谈

在T113上,I2C控制器默认只支持7位地址。如果你要用10位地址,得在设备树里配一下,或者驱动里手动设置。我个人建议:能用7位就别用10位,省心。

1.5 知识结构总览

下面这张图把I2C协议的核心知识点串起来了。我画这张图时,特意把物理层、协议层、地址体系分成了三个层次——你从上往下看,就是I2C从硬件到软件的完整脉络。

I2C协议知识体系 物理层 SDA(数据线) 双向、开漏、上拉 SCL(时钟线) 主设备驱动、同步 上拉电阻 1.5kΩ ~ 10kΩ 协议层 起始条件 SCL高→SDA下降 通信开始 数据有效性 SCL高时稳定 SCL低时变化 应答机制 ACK = 0 NACK = 1 停止条件 SCL高→SDA上升 通信结束 地址体系 7位地址(0x00 ~ 0x7F) 最多112个设备,最常用 10位地址(0x000 ~ 0x3FF) 最多1024个设备,较少用

从这张图你能看到,I2C协议其实不复杂。物理层搞定两根线的电气特性,协议层定义通信的时序规则,地址体系解决“谁跟谁说话”的问题。三层加起来,就是I2C的全部。

1.6 小结

这一章我们聊了I2C协议的来龙去脉。从飞利浦的初衷,到SDA/SCL的物理特性,再到起始、停止、数据、应答这些基本动作,最后是7位和10位地址的区别。