4. I2C总线时序分析:标准模式、快速模式与高速模式
I2C总线时序是驱动开发中最核心的硬件基础。不同速率模式下,SCL时钟频率、上升/下降时间、数据建立/保持时间等参数差异显著。本章从物理层时序参数出发,逐模式分析标准模式(100kHz)、快速模式(400kHz)和高速模式(3.4MHz)的时序要求,并给出驱动开发中的实测与配置要点。
4.1 I2C总线时序基础框架
I2C总线由SCL(时钟线)和SDA(数据线)构成,所有时序参数均围绕这两条线的电平变化定义。下图展示了I2C单次数据传输的完整时序框架,包含起始条件、数据字节传输、应答位和停止条件。
一次完整的I2C传输包含以下阶段:
- 起始条件(S): SDA在SCL高电平时从高到低跳变,表示传输开始。
- 从设备地址发送: 主设备发送7位或10位从设备地址,后跟读写位(R/W)。
- 应答位(ACK): 从设备在第9个SCL周期将SDA拉低,表示应答。
- 数据字节传输: 每字节8位,MSB先行,后跟应答位。
- 停止条件(P): SDA在SCL高电平时从低到高跳变,表示传输结束。
4.2 标准模式(100kHz)时序参数
标准模式是I2C总线最基础的速率模式,兼容性最广。下表列出了标准模式下的关键时序参数及其最小/最大值要求。
| 参数符号 | 参数名称 | 最小值 | 最大值 | 单位 |
|---|---|---|---|---|
| f_SCL | SCL时钟频率 | 0 | 100 | kHz |
| t_HD;STA | 起始条件保持时间 | 4.0 | — | μs |
| t_LOW | SCL低电平时间 | 4.7 | — | μs |
| t_HIGH | SCL高电平时间 | 4.0 | — | μs |
| t_SU;STA | 重复起始条件建立时间 | 4.7 | — | μs |
| t_HD;DAT | 数据保持时间 | 0 | 3.45 | μs |
| t_SU;DAT | 数据建立时间 | 250 | — | ns |
| t_r | SCL/SDA上升时间 | — | 1000 | ns |
| t_f | SCL/SDA下降时间 | — | 300 | ns |
| t_SU;STO | 停止条件建立时间 | 4.0 | — | μs |
| t_BUF | 停止与起始条件间总线空闲时间 | 4.7 | — | μs |
4.3 快速模式(400kHz)时序参数
快速模式将时钟频率提升至400kHz,时序要求比标准模式更严格,尤其是上升/下降时间和建立时间。下表对比快速模式与标准模式的关键差异参数。
| 参数符号 | 参数名称 | 标准模式 | 快速模式 | 单位 |
|---|---|---|---|---|
| f_SCL | SCL时钟频率 | 0~100 | 0~400 | kHz |
| t_LOW | SCL低电平时间 | 4.7 | 1.3 | μs |
| t_HIGH | SCL高电平时间 | 4.0 | 0.6 | μs |
| t_HD;STA | 起始条件保持时间 | 4.0 | 0.6 | μs |
| t_SU;DAT | 数据建立时间 | 250 | 100 | ns |
| t_r | SCL/SDA上升时间 | 1000 | 300 | ns |
| t_f | SCL/SDA下降时间 | 300 | 300 | ns |
| t_BUF | 总线空闲时间 | 4.7 | 1.3 | μs |
快速模式相比标准模式的主要变化:
- SCL低电平时间从4.7μs缩短至1.3μs,高电平时间从4.0μs缩短至0.6μs。
- 数据建立时间从250ns收紧至100ns,要求数据在SCL上升沿前更早稳定。
- 上升时间从1000ns收紧至300ns,对总线电容和上拉电阻提出更高要求。
- 总线空闲时间从4.7μs缩短至1.3μs,允许更快的连续传输。
4.4 高速模式(3.4MHz)时序参数
高速模式(Hs-mode)将I2C总线速率提升至3.4MHz,是标准I2C速率的34倍。高速模式引入了特殊的传输协议:主设备先以标准模式或快速模式发送高速模式使能码(00001XXX),然后切换到高速模式传输数据。
高速模式的关键时序参数如下表所示:
| 参数符号 | 参数名称 | 最小值 | 最大值 | 单位 |
|---|---|---|---|---|
| f_SCL | SCL时钟频率(高速模式) | 0 | 3.4 | MHz |
| t_LOW | SCL低电平时间 | 160 | — | ns |
| t_HIGH | SCL高电平时间 | 60 | — | ns |
| t_HD;STA | 起始条件保持时间 | 160 | — | ns |
| t_SU;DAT | 数据建立时间 | 10 | — | ns |
| t_HD;DAT | 数据保持时间 | 0 | 70 | ns |
| t_r | SCL/SDA上升时间 | — | 40 | ns |
| t_f | SCL/SDA下降时间 | — | 40 | ns |
| t_SU;STO | 停止条件建立时间 | 160 | — | ns |
| t_BUF | 总线空闲时间 | 160 | — | ns |
- 高速模式下,SCL由主设备的电流源驱动(典型电流源为3mA),而非开漏输出加外部上拉电阻。
- 数据建立时间仅需10ns,对主设备输出延迟和从设备输入采样窗口要求极高。
- 上升/下降时间必须控制在40ns以内,总线电容应≤100pF。
- 高速模式传输结束后,必须发送停止条件,使总线返回标准/快速模式。
4.5 三种模式时序参数对比总表
下表汇总了标准模式、快速模式和高速模式的核心时序参数,便于驱动开发时快速查阅和对比。
| 参数 | 标准模式 (100kHz) | 快速模式 (400kHz) | 高速模式 (3.4MHz) | 单位 |
|---|---|---|---|---|
| SCL频率 | 100 | 400 | 3400 | kHz |
| SCL周期 | 10 | 2.5 | 0.294 | μs |
| t_LOW | 4.7 | 1.3 | 0.16 | μs |
| t_HIGH | 4.0 | 0.6 | 0.06 | μs |
| t_SU;DAT | 250 | 100 | 10 | ns |
| t_HD;DAT | 0~3.45 | 0~0.9 | 0~0.07 | μs |
| t_r | 1000 | 300 | 40 | ns |
| t_f | 300 | 300 | 40 | ns |
| 总线电容 | ≤400 | ≤200 | ≤100 | pF |
| 驱动方式 | 开漏+上拉 | 开漏+上拉 | 电流源+开漏 | — |
4.6 驱动开发中的时序配置实践
在嵌入式Linux驱动开发中,I2C时序配置通常通过I2C适配器驱动中的时钟分频寄存器实现。以下是一个典型的I2C时序配置代码示例,展示如何根据目标速率计算分频系数。
/*
* I2C时序配置示例:计算SCL分频系数
* 假设I2C控制器输入时钟为50MHz
*/
#include <linux/i2c.h>
#include <linux/delay.h>
/* 根据目标速率计算分频系数 */
static u32 i2c_calc_divider(u32 input_clk_hz, u32 target_rate_hz)
{
u32 divider;
/* 标准模式:100kHz */
if (target_rate_hz <= 100000)
divider = input_clk_hz / (2 * 100000);
/* 快速模式:400kHz */
else if (target_rate_hz <= 400000)
divider = input_clk_hz / (2 * 400000);
/* 高速模式:3.4MHz */
else if (target_rate_hz <= 3400000)
divider = input_clk_hz / (2 * 3400000);
else
return -EINVAL;
/* 确保分频系数在有效范围内 */
if (divider < 2)
divider = 2;
if (divider > 0xFFFF)
divider = 0xFFFF;
return divider;
}
/* 设置I2C时序寄存器 */
static int i2c_set_timing(struct i2c_adapter *adap, u32 rate)
{
u32 divider;
u32 reg_val;
divider = i2c_calc_divider(50000000, rate);
if (divider < 0)
return -EINVAL;
/* 写入时钟分频寄存器(假设寄存器偏移为0x00) */
reg_val = readl(adap->base + 0x00);
reg_val &= ~0xFFFF;
reg_val |= (divider & 0xFFFF);
writel(reg_val, adap->base + 0x00);
/* 设置上升时间补偿(快速模式需要) */
if (rate > 100000) {
reg_val = readl(adap->base + 0x04);
reg_val |= (1 << 8); /* 使能上升时间补偿 */
writel(reg_val, adap->base + 0x04);
}
dev_dbg(&adap->dev, "I2C rate set to %u Hz, divider = %u\n", rate, divider);
return 0;
}
4.7 时序违规的常见问题与排查
驱动开发中,时序违规是导致I2C通信失败的常见原因。下表列出了典型时序问题及其排查方法。
| 问题现象 | 可能原因 | 排查方法 |
|---|---|---|
| 从设备无应答(NACK) | SCL频率过高,从设备无法响应 | 降低SCL频率至标准模式测试;检查从设备数据手册支持的速率 |
| 数据采样错误(CRC/校验失败) | 数据建立时间不足,SDA在SCL上升沿未稳定 | 增加t_SU;DAT延时;检查总线电容是否过大导致上升沿变缓 |
| 起始条件无法识别 | t_HD;STA过短,SDA跳变后SCL未及时拉低 | 增加起始条件保持时间;检查主设备驱动中起始条件时序实现 |
| 总线卡死(SDA一直被拉低) | 从设备未释放SDA,或时钟拉伸超时 | 检查从设备是否处于异常状态;增加时钟拉伸超时处理 |
| 高速模式无法进入 | 使能码发送失败,或从设备不支持高速模式 | 用示波器捕获使能码波形;确认从设备Hs-mode使能条件 |
4.8 本章小结
I2C总线时序分析是驱动开发的基础技能。标准模式(100kHz)兼容性最好,时序裕量大;快速模式(400kHz)是嵌入式系统中最常用的速率,需注意上升时间和建立时间;高速模式(3.4MHz)需要特殊的电流源驱动和严格的PCB布局。驱动开发中,应根据从设备数据手册选择匹配的速率模式,并通过示波器或逻辑分析仪验证实际时序是否满足规范要求。