4. I2C 传输模式:标准、快速、高速与超快速
I2C 总线协议定义了多种传输速率模式,以适应从低速传感器到高速存储器、显示接口等不同外设的需求。每种模式在电气特性、时序参数、驱动能力以及兼容性方面均有严格规范。本章将详细解析标准模式(100 kHz)、快速模式(400 kHz)、高速模式(3.4 MHz)与超快速模式(5 MHz)的核心差异、应用场景及驱动适配要点。
4.1 四种传输模式对比总览
下表从时钟频率、最大总线电容、驱动电流、兼容性及典型应用场景五个维度,对四种标准模式进行横向对比:
| 参数 | 标准模式 (Sm) | 快速模式 (Fm) | 高速模式 (Hs) | 超快速模式 (UFm) |
|---|---|---|---|---|
| 时钟频率 | 100 kHz | 400 kHz | 3.4 MHz | 5 MHz |
| 最大总线电容 | 400 pF | 400 pF | 100 pF | 100 pF |
| 最小上拉电阻 | 4.7 kΩ | 1.5 kΩ | 0.5 kΩ | 0.5 kΩ |
| 驱动电流能力 | 3 mA | 6 mA | 20 mA | 20 mA |
| 输入阈值兼容 | TTL (0.8V/2.0V) | TTL (0.8V/2.0V) | Hs 专用 (0.3V/0.7VCC) | TTL (0.8V/2.0V) |
| 从设备地址 | 7-bit / 10-bit | 7-bit / 10-bit | 7-bit / 10-bit | 8-bit (无 R/W 位) |
| 典型应用 | 温度传感器、EEPROM | 加速度计、音频编解码器 | 图像传感器、高速 ADC | LED 驱动器、GPIO 扩展器 |
struct i2c_bus_recovery_info 和 struct i2c_timings 结构体来配置不同模式下的时序参数。对于高速模式,通常需要启用 I2C_FUNC_10BIT_ADDR 和 I2C_FUNC_PROTOCOL_MANGLING 功能标志。
4.2 标准模式 (Standard-mode, 100 kHz)
标准模式是 I2C 总线最基础的传输模式,由 Philips 在 1982 年首次定义。其时钟频率为 100 kHz,最大数据传输速率为 100 kbit/s。该模式对总线电容和上拉电阻的要求最为宽松,兼容性最好,几乎所有 I2C 设备都支持标准模式。
- 时序参数: SCL 高电平时间 tHIGH ≥ 4.0 μs,低电平时间 tLOW ≥ 4.7 μs;上升时间 tr ≤ 1000 ns,下降时间 tf ≤ 300 ns。
- 总线电容: 最大允许 400 pF,允许较长的 PCB 走线和多个从设备挂载。
- 驱动适配: 标准模式下,Linux 内核通常使用
I2C_CLASS_HWMON或I2C_CLASS_SPD类 ID 进行设备探测。时钟分频系数一般设置为 50(假设输入时钟为 5 MHz)。
4.3 快速模式 (Fast-mode, 400 kHz)
快速模式将时钟频率提升至 400 kHz,数据传输速率达到 400 kbit/s。该模式在保持与标准模式向后兼容的同时,通过降低上拉电阻值和缩短时序参数来实现速率提升。快速模式是目前嵌入式系统中最常用的 I2C 传输模式。
- 时序参数: tHIGH ≥ 0.6 μs,tLOW ≥ 1.3 μs;tr ≤ 300 ns,tf ≤ 300 ns。
- 上拉电阻: 典型值为 1.5 kΩ ~ 2.2 kΩ,具体取决于总线电容和供电电压。
- 驱动适配: 在设备树中,通过
clock-frequency = <400000>;属性指定快速模式。控制器驱动需设置对应的 SCL 分频寄存器,并启用施密特触发器输入以抑制噪声。
// Linux 设备树中配置 I2C 控制器为快速模式示例
&i2c1 {
clock-frequency = <400000>; // 400 kHz
pinctrl-0 = <&i2c1_pins>;
status = "okay";
temperature_sensor: sensor@48 {
compatible = "lm75";
reg = <0x48>;
};
};
4.4 高速模式 (High-speed Mode, 3.4 MHz)
高速模式(Hs-mode)将 I2C 总线速率提升至 3.4 MHz,数据传输速率达到 3.4 Mbit/s。该模式引入了专用的 Hs 从设备使能信号(SDAH/SCLH)和电流提升电路,以克服高频率下的总线电容限制。Hs 模式与标准/快速模式不直接兼容,需要通过主控制器发送特定的“高速使能码”(00001XXX)来切换总线状态。
- 时序参数: tHIGH ≥ 60 ns,tLOW ≥ 160 ns;tr ≤ 40 ns,tf ≤ 40 ns。
- 总线电容: 严格限制在 100 pF 以内,通常只允许 1~2 个 Hs 从设备直接挂载。
- 驱动适配: 高速模式需要控制器支持
I2C_FUNC_HIGH_SPEED功能标志。在传输开始时,主设备必须发送 8 位高速使能码(例如 0x08),然后切换至 Hs 模式时钟。Linux 内核中,i2c_msg的flags字段需设置I2C_M_HIGH_SPEED。
- Hs 模式下只能进行单主传输,多主仲裁在高速阶段被禁止。
- 所有 Hs 从设备必须支持 3.4 MHz 的输入缓冲器,且输出级需为开漏结构。
- 总线长度通常限制在 10 cm 以内,以减少信号反射和振铃。
4.5 超快速模式 (Ultra Fast-mode, 5 MHz)
超快速模式(UFm)是 I2C 总线规范中速率最高的单向传输模式,时钟频率可达 5 MHz。UFm 仅支持单主设备到从设备的单向数据传输(推挽输出),不支持多主仲裁、时钟拉伸或从设备应答。该模式专为 LED 驱动器、GPIO 扩展器等纯输出设备设计。
- 时序参数: tHIGH ≥ 50 ns,tLOW ≥ 100 ns;tr ≤ 30 ns,tf ≤ 30 ns。
- 地址格式: 使用 8 位从设备地址(无 R/W 位),地址空间为 0x00 ~ 0xFF。
- 驱动适配: UFm 模式下,SDA 线变为推挽输出,不再需要上拉电阻。Linux 内核中,UFm 通常通过
I2C_M_RECV_LEN和自定义协议扩展实现。控制器需支持I2C_FUNC_UFM功能标志。
i2c_check_functionality 中验证控制器是否支持 UFm 模式。
4.6 传输模式选择与驱动配置流程
在实际嵌入式项目中,选择合适的 I2C 传输模式需要综合考虑从设备规格、总线负载、PCB 布局和功耗要求。以下流程图展示了从需求分析到驱动配置的完整决策路径:
4.7 驱动代码中的模式配置示例
以下代码片段展示了在 Linux 内核 I2C 控制器驱动中,如何根据设备树指定的时钟频率动态选择传输模式,并配置对应的时序寄存器:
#include <linux/i2c.h>
#include <linux/clk.h>
static int my_i2c_set_bus_speed(struct i2c_adapter *adap, u32 speed)
{
struct my_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
unsigned long parent_rate = clk_get_rate(i2c_dev->clk);
unsigned int divider;
u32 ccr_value;
switch (speed) {
case 100000: // 标准模式
divider = DIV_ROUND_UP(parent_rate, 100000 * 2);
ccr_value = (divider & 0xFF) << 8;
i2c_dev->mode = I2C_MODE_STANDARD;
break;
case 400000: // 快速模式
divider = DIV_ROUND_UP(parent_rate, 400000 * 2);
ccr_value = (divider & 0xFF) << 8;
i2c_dev->mode = I2C_MODE_FAST;
break;
case 3400000: // 高速模式
divider = DIV_ROUND_UP(parent_rate, 3400000 * 2);
ccr_value = (divider & 0xFF) << 8;
ccr_value |= I2C_CCR_HS_MODE; // 设置高速使能位
i2c_dev->mode = I2C_MODE_HIGH_SPEED;
break;
case 5000000: // 超快速模式
divider = DIV_ROUND_UP(parent_rate, 5000000 * 2);
ccr_value = (divider & 0xFF) << 8;
ccr_value |= I2C_CCR_UF_MODE; // 设置超快速使能位
i2c_dev->mode = I2C_MODE_ULTRA_FAST;
break;
default:
dev_err(&adap->dev, "Unsupported I2C speed: %u\n", speed);
return -EINVAL;
}
writel(ccr_value, i2c_dev->base + I2C_CCR_REG);
dev_info(&adap->dev, "I2C bus set to %u Hz (mode: %d)\n",
speed, i2c_dev->mode);
return 0;
}
4.8 四种模式的电气特性对比 SVG
下图以可视化方式展示了四种传输模式在时钟频率、总线电容和上拉电阻三个关键电气参数上的相对关系:
4.9 中断安全编程中的模式切换注意事项
在多主通信或中断驱动的 I2C 传输场景中,动态切换传输模式需要特别关注以下安全要点:
- 原子性操作: 模式切换寄存器(如 CCR)的写操作必须在关中断环境下执行,防止在写操作过程中被中断处理程序抢占,导致时序配置不一致。
- 状态同步: 切换模式前,必须确保当前总线处于空闲状态(SDA 和 SCL 均为高电平)。建议在切换前调用
i2c_recover_bus()进行总线恢复。 - 缓存刷新: 高速模式切换后,需清空控制器内部的 FIFO 和状态寄存器,避免残留数据影响新模式的传输。
- 中断优先级: 高速模式传输时间短,中断服务程序应设置较高优先级,避免因中断延迟导致 SCL 时钟拉伸超时。
// 中断安全的模式切换示例
static int i2c_safe_mode_switch(struct my_i2c_dev *i2c_dev, u32 new_speed)
{
unsigned long flags;
int ret;
// 1. 关中断,确保原子操作
spin_lock_irqsave(&i2c_dev->lock, flags);
// 2. 等待当前传输完成
ret = wait_for_completion_timeout(&i2c_dev->xfer_complete,
msecs_to_jiffies(100));
if (ret == 0) {
spin_unlock_irqrestore(&i2c_dev->lock, flags);
return -ETIMEDOUT;
}
// 3. 执行模式切换
ret = my_i2c_set_bus_speed(&i2c_dev->adapter, new_speed);
// 4. 清空 FIFO 和状态
writel(I2C_FIFO_FLUSH, i2c_dev->base + I2C_FIFO_CTRL);
readl(i2c_dev->base + I2C_STATUS_REG); // 读清状态
// 5. 开中断
spin_unlock_irqrestore(&i2c_dev->lock, flags);
return ret;
}