SMBus (System Management Bus) 是由 Intel 在 1995 年定义的,基于 I2C 协议的子集。它主要用于主板上的电源管理、系统监控等低速通信。
虽然 SMBus 建立在 I2C 之上,但它们之间存在一些细微差别。
1. 关键区别
| 特性 | I2C | SMBus |
|---|---|---|
| 速率 | 0 - 3.4MHz (DC) | 10kHz - 100kHz |
| 超时 | 无 (DC) | 必须有 (Low max 35ms) |
| 逻辑电平 | 依赖 VDD | 固定电平 (0.8V / 2.1V) |
| 电流 | 3mA | 350uA (低功耗) |
| ACK | 必须应答 | 允许忽略 |
| 协议强制性 | 较宽松 | 严格定义了数据包格式 |
- 超时机制:SMBus 规定如果时钟低电平超过 35ms,总线必须复位。这防止了设备锁死总线。I2C 没有这个强制规定。
- 最小频率:SMBus 要求最少 10kHz,以维持超时检测。
2. 传输协议 (Transactions)
SMBus 定义了一组标准的数据传输类型,Linux 内核提供了对应的 API。
2.1 Quick Command
只发送读/写位,用于扫描设备。
i2c_smbus_write_quick(client, value)
2.2 Byte Data
写:Addr + Cmd + Data 读:Addr + Cmd + Restart + Addr + Data
i2c_smbus_read_byte_data(client, command)i2c_smbus_write_byte_data(client, command, value)
这是最常用的读写 8 位寄存器的方式。
2.3 Word Data
类似 Byte Data,但读写 16 位数据(通常是 Little Endian)。
i2c_smbus_read_word_data(client, command)i2c_smbus_write_word_data(client, command, value)
2.4 Block Data
读写一块数据(最多 32 字节)。第一个字节表示长度。
i2c_smbus_read_block_data(...)i2c_smbus_write_block_data(...)
3. I2C 与 SMBus 的互操作性
- I2C 设备在 SMBus 总线上:可能工作,但要注意:
- I2C 设备必须能处理超时复位。
- 电气特性必须兼容。
- SMBus 设备在 I2C 总线上:通常可以工作。Linux 的
i2c-core会尝试用 I2C 传输模拟 SMBus 协议。
4. Linux 编程建议
在编写驱动时,优先使用 i2c_smbus_* 系列函数。
原因:
- 兼容性好:如果控制器支持原生 SMBus 硬件加速,性能更高;如果不支持,内核会自动用 I2C bit-banging 模拟。
- 语义清晰:代码更易读(如
read_byte_data明确表示读一个字节)。 - 适配器支持:有些 PC 平台的适配器(如 Intel PCH SMBus)只能执行 SMBus 命令,不支持原始的 I2C 消息。使用 SMBus API 可以确保驱动在这些平台上也能运行。