3. I2C地址机制:7位地址与10位地址格式、广播地址、保留地址、地址冲突检测
I2C总线上的每个从设备都有一个唯一的地址,主设备通过地址来选择通信目标。地址机制是I2C协议的核心基础,理解7位与10位地址格式、特殊地址以及冲突检测方法,对于驱动开发和调试至关重要。
3.1 7位地址格式
标准I2C总线使用7位地址,这是最广泛使用的地址模式。7位地址允许挂载最多112个从设备(保留地址除外)。
7位地址传输结构:
- 起始条件(S):SCL高电平时SDA由高变低。
- 7位地址(A6~A0):高位在前,低位在后。
- 读/写位(R/W):0表示主设备写,1表示主设备读。
- 应答位(ACK):从设备在第9个SCL周期拉低SDA表示应答。
关键点: 7位地址在发送时实际上占用8个时钟周期(7位地址 + 1位R/W),加上起始条件和应答位,构成完整的地址帧。
3.2 10位地址格式
为了解决7位地址空间不足的问题,I2C规范引入了10位地址模式。10位地址允许挂载最多1024个从设备,且与7位设备兼容。
10位地址传输分为两个阶段:
| 阶段 | 字节内容 | 说明 |
|---|---|---|
| 第1字节(高5位) | 11110 A9 A8 R/W | 11110为10位地址标识,A9~A8为地址高位,R/W为读写位 |
| 第2字节(低8位) | A7 A6 A5 A4 A3 A2 A1 A0 | 地址低位,共8位 |
兼容性说明: 10位地址设备在总线上必须能识别两种地址格式。主设备发送10位地址时,第1字节的11110前缀不会与任何7位地址冲突,因为7位地址中1111XXX被保留。
3.3 广播地址与保留地址
I2C规范定义了一些特殊地址,用于总线管理和通用呼叫。这些地址不能被分配给普通从设备。
保留地址表:
| 7位地址(二进制) | 用途 | 说明 |
|---|---|---|
| 0000 000 | 广播/通用呼叫地址 | 主设备发送此地址时,所有从设备都应应答 |
| 0000 001 | 起始字节 | 用于慢速设备检测总线起始 |
| 0000 010 | CBUS地址 | 保留给CBUS兼容设备 |
| 0000 011 | 保留 | 未来扩展用途 |
| 0000 1XX | Hs-mode主设备码 | 高速模式主设备标识 |
| 1111 0XX | 10位地址前缀 | 标识后续为10位地址 |
| 1111 1XX | 保留 | 未来扩展用途 |
驱动开发注意: 在配置从设备地址时,必须避开上述保留地址范围。常见的错误是将设备地址设置为0x00或0x7F,这些地址在I2C规范中是非法的。建议使用0x08~0x77范围内的地址。
3.4 地址冲突检测
当多个从设备使用相同地址时,总线通信将出现不可预测的行为。地址冲突是I2C调试中最常见的问题之一。
地址冲突的典型症状:
- 无应答(NACK):主设备发送地址后未收到ACK。
- 数据错乱:多个设备同时应答,导致SDA线被同时拉低和释放,产生不确定电平。
- 总线挂死:SCL或SDA被某个设备持续拉低,无法释放。
地址冲突检测方法:
- 硬件检测:使用逻辑分析仪或示波器抓取地址帧,观察是否有多个设备同时应答。
- 软件扫描:主设备依次发送所有可能的地址,记录哪些地址有ACK响应。
- 设备数据手册核对:确认每个从设备的固定地址位和可编程地址位。
3.5 地址配置实战要点
在Linux I2C驱动开发中,地址配置通常通过设备树或板级文件完成。以下是关键配置参数:
/* 设备树中I2C从设备地址配置示例 */
&i2c1 {
status = "okay";
clock-frequency = <100000>; /* 标准模式100kHz */
temperature_sensor: tmp102@48 {
compatible = "ti,tmp102";
reg = <0x48>; /* 7位地址,左对齐 */
#address-cells = <1>;
#size-cells = <0>;
};
eeprom: at24@50 {
compatible = "atmel,24c02";
reg = <0x50>; /* 7位地址 */
pagesize = <8>;
};
};
地址配置检查清单:
- 确认设备地址不在保留地址范围内(0x00~0x07, 0x78~0x7F)。
- 检查同一I2C总线上是否有重复地址。
- 确认设备数据手册中的地址位是否包含可编程引脚(如A0、A1、A2)。
- 对于10位地址设备,确保驱动支持10位地址模式(Linux内核需配置CONFIG_I2C_10BIT)。
- 使用i2cdetect工具扫描总线,验证地址配置是否正确。
/* 使用i2cdetect扫描I2C总线 */
# i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- 48 -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
调试技巧: 如果i2cdetect扫描到预期之外的地址,可能表示存在地址冲突或设备未正确初始化。此时应使用逻辑分析仪抓取实际总线波形,确认地址帧是否与预期一致。