2. I2C 总线协议详解:物理层、时序、起始/停止条件、数据有效性、地址与读写位
I2C(Inter-Integrated Circuit)总线是一种由 Philips(现 NXP)公司开发的两线式串行通信协议,广泛应用于嵌入式系统中连接微控制器与低速外设(如传感器、EEPROM、ADC/DAC、RTC 等)。本章将深入剖析 I2C 协议的物理层特性、时序要求、关键信号条件以及数据帧结构,为后续实现基于 DMA 的高效驱动打下坚实基础。
2.1 物理层:两线制与开漏架构
I2C 总线仅使用两条双向信号线:
- SCL(Serial Clock Line):串行时钟线,由主设备产生,用于同步数据传输。
- SDA(Serial Data Line):串行数据线,用于传输地址和数据。
两条线均采用开漏(Open-Drain)输出结构,并通过外部上拉电阻连接到 VDD(通常为 1.8V、3.3V 或 5V)。开漏结构允许多个设备共享总线,实现“线与”逻辑:任何设备拉低总线时,总线即为低电平;只有当所有设备释放总线时,总线才被上拉电阻拉至高电平。
I2C 总线支持多主设备,但同一时刻只能有一个主设备控制总线。每个从设备拥有唯一的 7 位或 10 位地址。
2.2 总线时序与信号条件
I2C 协议定义了严格的时序要求,以确保数据在总线上的可靠传输。所有时序参数均以 SCL 时钟为基准。
2.2.1 起始条件(START Condition)
当 SCL 为高电平时,SDA 从高电平切换到低电平,表示一次传输的开始。起始条件由主设备产生,所有从设备在检测到起始条件后复位内部逻辑,准备接收地址。
2.2.2 停止条件(STOP Condition)
当 SCL 为高电平时,SDA 从低电平切换到高电平,表示一次传输的结束。停止条件后,总线恢复空闲状态(SCL 和 SDA 均为高电平)。
2.2.3 重复起始条件(Repeated START)
在一次传输过程中,主设备可以在不产生停止条件的情况下,再次产生一个起始条件。这通常用于改变数据传输方向(例如从写模式切换到读模式),而无需释放总线控制权。
2.3 数据有效性
I2C 协议规定,在 SCL 时钟的高电平期间,SDA 上的数据必须保持稳定。只有在 SCL 为低电平时,SDA 上的数据才允许发生变化。这一规则确保了数据在时钟上升沿被可靠采样。
- 数据采样: 接收方在 SCL 的上升沿锁存 SDA 上的数据。
- 数据变化: 发送方只能在 SCL 为低电平时改变 SDA 状态。
- 例外: 起始条件和停止条件不受此规则约束,它们是在 SCL 高电平时改变 SDA。
2.4 地址与读写位:数据帧结构
I2C 协议的数据传输以帧为单位。一个完整的 I2C 传输帧包含以下部分:
- 起始条件(S)
- 7 位从设备地址(或 10 位地址,此处以 7 位为例)
- 读写位(R/W):0 表示主设备写数据到从设备,1 表示主设备从从设备读取数据。
- 应答位(ACK/NACK):从设备在接收到地址后,必须拉低 SDA 以产生应答(ACK),表示确认。
- 数据字节:每个字节 8 位,MSB 先传输。每传输一个字节后,接收方需产生应答位。
- 停止条件(P) 或 重复起始条件(Sr)
2.5 应答机制(ACK/NACK)
应答位是 I2C 协议中确保数据可靠传输的关键机制。每传输一个字节(8 位)后,接收方必须在第 9 个 SCL 时钟周期内产生应答:
- ACK(应答):接收方在第 9 个时钟周期拉低 SDA,表示“已收到,请继续发送”。
- NACK(非应答):接收方在第 9 个时钟周期保持 SDA 为高电平,表示“未准备好”或“传输结束”。主设备在收到 NACK 后通常会产生停止条件。
- 地址阶段: 从设备必须发送 ACK 以确认地址匹配。若总线上无设备响应,主设备会收到 NACK。
- 数据阶段(主设备写): 从设备每接收一个字节后发送 ACK。若从设备无法接收更多数据,则发送 NACK。
- 数据阶段(主设备读): 主设备在接收每个字节后发送 ACK 以表示“继续发送”,在接收最后一个字节后发送 NACK 以表示“停止发送”。
2.6 通信速率与模式
I2C 协议定义了多种工作模式,以适应不同外设的速度需求:
| 模式 | 最大时钟频率 | 典型应用 |
|---|---|---|
| 标准模式(Standard-mode) | 100 kHz | 传统传感器、EEPROM |
| 快速模式(Fast-mode) | 400 kHz | 大多数现代外设 |
| 快速模式+(Fast-mode Plus) | 1 MHz | 高数据量传感器、显示驱动 |
| 高速模式(High-speed mode) | 3.4 MHz | 视频、高速 ADC |
| 超快速模式(Ultra Fast-mode) | 5 MHz | 单向传输(仅写),无需上拉电阻 |
2.7 多字节传输与复合操作
I2C 协议支持在一个传输帧内连续发送多个数据字节,无需重新发送地址。这在读写大块数据(如 EEPROM 页写入、传感器多通道读取)时非常高效。
典型复合操作示例: 读取 EEPROM 指定地址的数据
- 主设备发送起始条件(S)
- 主设备发送从设备地址 + 写位(R/W=0)
- 从设备应答(ACK)
- 主设备发送要读取的内存地址(1 或 2 字节)
- 从设备应答(ACK)
- 主设备发送重复起始条件(Sr)
- 主设备发送从设备地址 + 读位(R/W=1)
- 从设备应答(ACK)
- 从设备发送数据字节,主设备应答(ACK)
- ...(重复步骤 9 直到读取完成)
- 主设备发送 NACK 表示读取结束
- 主设备发送停止条件(P)