1. I2C协议基础:总线物理层与时序规范
I2C(Inter-Integrated Circuit)是一种由Philips(现NXP)开发的两线式串行通信协议,广泛应用于MCU与传感器、存储器、IO扩展器等外设之间的短距离通信。理解其物理层和时序是驱动开发的第一步。
1.1 总线物理层结构
I2C总线仅需两根双向信号线:
- SCL(Serial Clock):串行时钟线,由主机(Master)驱动,用于同步数据传输。
- SDA(Serial Data):串行数据线,用于双向传输地址和数据。
总线采用开漏(Open-Drain)输出结构,配合外部上拉电阻实现“线与”逻辑:
关键特性: 空闲时SCL和SDA均为高电平;任何设备拉低其中一条线即可发起操作。这种结构允许多主机仲裁,且无总线冲突风险。
| 参数 | 标准模式(100 kHz) | 快速模式(400 kHz) | 高速模式(3.4 MHz) |
|---|---|---|---|
| SCL最大频率 | 100 kHz | 400 kHz | 3.4 MHz |
| 上拉电阻典型值 | 4.7 kΩ | 2.2 kΩ | 1.0 kΩ |
| 总线电容上限 | 400 pF | 400 pF | 100 pF |
| 最大从机数量 | 127(7位地址) | 127 | 127 |
驱动开发提示: 在MCU的I2C外设初始化时,需根据总线负载电容和通信速率选择合适的上拉电阻。过小的电阻会增加功耗,过大的电阻会减慢上升沿,导致时序违规。
1.2 SCL/SDA时序规范
I2C协议对SCL和SDA的时序有严格定义,驱动开发中必须确保满足以下关键时间参数:
- tHD;STA:起始条件保持时间(≥ 4.0 μs @ 100 kHz)
- tSU;STA:重复起始条件建立时间(≥ 4.7 μs)
- tHD;DAT:数据保持时间(≥ 0 ns)
- tSU;DAT:数据建立时间(≥ 250 ns)
- tLOW:SCL低电平时间(≥ 4.7 μs)
- tHIGH:SCL高电平时间(≥ 4.0 μs)
- tSU;STO:停止条件建立时间(≥ 4.0 μs)
- tBUF:停止与起始条件间总线空闲时间(≥ 4.7 μs)
常见陷阱: 在轮询模式下,MCU主频较高时容易忽略SCL低电平时间tLOW。如果SCL高电平时间过短,从机可能无法正确采样SDA数据,导致通信失败。建议使用逻辑分析仪或示波器验证时序。
1.3 起始条件与停止条件
I2C总线上所有通信都以起始条件(START)开始,以停止条件(STOP)结束。这两个条件是总线状态转换的唯一合法边界。
起始条件(S)
当SCL为高电平时,SDA从高电平切换到低电平。此信号由主机产生,表示总线从空闲状态进入活跃状态。
停止条件(P)
当SCL为高电平时,SDA从低电平切换到高电平。此信号由主机产生,表示当前传输结束,总线恢复空闲。
重复起始条件(Sr)
在未产生停止条件的情况下,主机再次产生起始条件。常用于多字节读写或改变数据传输方向,无需释放总线。
1.4 完整数据传输流程
一次典型的I2C写操作包含以下步骤:
- 主机发送起始条件(S):SCL高时拉低SDA。
- 主机发送7位从机地址 + 读写位(R/W):地址高位在前,R/W=0表示写,1表示读。
- 从机发送应答位(ACK):从机在第9个SCL周期拉低SDA表示应答。
- 主机发送寄存器地址或数据字节:每字节后跟从机ACK。
- 主机发送停止条件(P):SCL高时释放SDA使其变高。
1.5 应答机制(ACK/NACK)
每个字节传输完成后,接收方必须在第9个SCL周期产生应答:
- ACK(应答):接收方拉低SDA,表示准备接收下一字节。
- NACK(非应答):接收方保持SDA高电平,表示传输结束或错误。
驱动开发要点: 在MCU的I2C中断服务函数中,检测到NACK时应立即停止后续传输并产生停止条件。轮询模式下,需在发送每字节后检查I2C状态寄存器的ACK标志位,避免死循环。