4. I2C 寻址方式:7位地址、10位地址、保留地址与广播地址
I2C 总线上的设备怎么互相找到对方?
靠的就是地址。每个从机都有一个唯一地址,主机发起通信时,先把地址发到总线上。谁匹配上了,谁就回应。
我刚开始学 I2C 时,总觉得地址就是个简单的编号。后来踩了几次坑才发现,这里面的门道比想象中多。7位、10位、保留地址、广播地址,各有各的规矩。
4.1 7位地址格式
7位地址,说白了就是一次寻址最多挂128个设备。地址范围从 0x00 到 0x7F。但实际能用的大概112个,因为头几个被保留做特殊用途。
通信时,主机发一个字节作为起始字节。高7位是地址,最低位是读写标志位(R/W)。0表示主机要写,1表示主机要读。
起始字节格式(7位地址):
位7 - 位1: 从机地址 (A6 ~ A0)
位0: R/W (0=写, 1=读)
示例:主机向地址 0x27 的从机写数据
-> 发送字节: 0x4E (0100 1110)
地址: 0100 111 = 0x27
R/W: 0 = 写
一个典型的总线拓扑能挂多少设备?
| 地址位 | 理论设备数 | 实际可用(不含保留) | 常见应用 |
|---|---|---|---|
| 7位 | 128 | 112 | 传感器、EEPROM、LCD驱动 |
| 10位 | 1024 | 约1000 | 复杂系统中多设备场景 |
7位地址用的最多。我在项目里接触的传感器、EEPROM、温度芯片,基本都是7位。你想想看,如果总线上只挂三五个设备,7位地址完全够用了。
4.2 10位地址格式
10位地址是干嘛用的?
扩展寻址空间。当总线上设备超过112个,或者地址冲突时,就得用10位了。
这里的实现有点绕。10位地址并不是直接发两个字节,而是用一个特殊的头字节做标志。我第一次用10位地址时,就被那个特殊格式搞晕了。
流程是这样的:
- 第一步: 主机发第一个字节,高5位固定为
11110,接着是地址的高2位(A9~A8),最后是R/W位。 - 第二步: 主机发第二个字节,包含地址的低8位(A7~A0)。
- 第三步: 从机在两步后回应ACK。
10位地址通信示例(地址 = 0x1A3):
地址高2位: 0x1A3 >> 8 = 0x01 (A9=0, A8=1)
地址低8位: 0x1A3 & 0xFF = 0xA3
起始字节1: 1111 0 [A9 A8] [R/W]
= 1111 0 0 1 0
= 0xF2 (写操作)
起始字节2: 0xA3
从机地址 = 0x1A3
10位地址和7位地址可以混挂在同一条总线上。具体怎么区分?
靠的是第一个字节的高5位。如果是 11110,就是10位地址模式。兼容性做得挺好的。
4.3 保留地址
地址空间里有几个特殊值被固定保留,不能被普通设备占用。我见过有些新手直接把设备地址设成0x00,结果总线上所有从机都响应了,乱成一片。
| 地址(7位) | 用途 | 说明 |
|---|---|---|
| 0x00 | 广播/通用呼叫地址 | 所有支持广播的从机必须响应 |
| 0x01 | 启动字节 | 用于低速模式下唤醒总线 |
| 0x02 | 保留 | CBUS 兼容地址 |
| 0x03 - 0x07 | 保留 | 未来扩展 / 特殊总线格式 |
| 0x78 - 0x7F | 10位地址头标志 | 高5位为11110 |
我还记得调试一个I2C触摸屏时,从机就是不响应。后来用示波器看波形,发现主机发的地址是0x00。查了数据手册才发现,那个芯片不支持广播,但恰好地址线设置了全0。这属于硬件设计的坑。
4.4 广播地址
广播地址就是 0x00。主机发地址0x00时,所有支持广播模式的从机都必须回应。
广播能干嘛?我最常用的是:系统复位或全局写入某个配置。比如想同时重置所有传感器,发一个广播地址再跟一个复位指令,所有从机一起执行。省去挨个寻址的麻烦。
广播通信过程:
- 主机发 START 条件
- 主机发 0x00 + W(写标志)
- 所有支持广播的从机在第九个SCL周期拉低SDA回应ACK
- 主机发后续数据字节(比如复位指令)
- 主机发 STOP 条件
但要注意,不是所有设备都支持广播。很多便宜的传感器会忽略广播地址。我曾经在项目中遇到一个温度传感器,明明数据手册标着支持广播,实际测下来根本不响应。最后只能一个个单独复位。
4.5 地址冲突与避坑
地址冲突是我在项目中遇到最多的问题。尤其是同一个型号的芯片挂在同一条总线上,每个芯片的地址引脚就那么几个,很容易撞车。
怎么办?
- 换地址: 有些芯片通过引脚或寄存器可以改地址。优先用不同组合。
- 加MUX: 实在冲突了,用 I2C 多路复用器(比如 PCA9548)。一个MUX能分出8路,每路独立总线。
- 用10位地址: 如果你的MCU和从机都支持,直接切换到10位模式。
我个人的习惯是:做原型阶段先列一个地址分配表。7位地址从0x08开始用,0x00-0x07彻底避开。这样即使后续加设备,也不太会踩到保留地址的坑。
好啦,这就是I2C寻址方式的全部核心内容。掌握好这些地址知识,你在I2C调试中就能少走很多弯路。地址选对了,通信就成功了一半。