一、初识神兵:i2c-tools是什么?
想象一下:你面前有几十根I2C总线(俗称/dev/i2c-X),每根线上挂着神秘的外设芯片(EEPROM、传感器、电源管理IC...)。这些芯片不会说话,只会用高低电平 跟你交流。而i2c-tools就是一套能让人类和这些"哑巴芯片"对话的翻译官!
它由5个核心命令组成,覆盖从"人口普查"到"精准外科手术"的全套技能:
| 命令 | 江湖诨名 | 必杀技 |
|---|---|---|
i2cdetect |
总线侦探 | 扫描总线上的设备地址 |
i2cdump |
寄存器X光机 | 一键导出所有寄存器内容 |
i2cget |
单点读心术 | 读取指定寄存器的值 |
i2cset |
寄存器手术刀 | 修改指定寄存器的值 |
i2ctransfer |
终极奥义 | 破解复杂时序与多字节操作 |
二、四大基础招式:从入门到熟练
1️⃣ 摸家底:i2cdetect - 谁是总线的主人?
场景 :刚接手一台新机器,完全不知道I2C总线上挂了啥设备?
解法:两步走战略!
- 列出所有I2C总线(找到/dev/i2c-X的编号)
powershell
$ i2cdetect -l
i2c-0 smbus SMBus I801 adapter at efa0 SMBus adapter
i2c-1 i2c Synopsys DesignWare I2C adapter I2C adapter
- 扫描指定总线上的设备(重点看输出!)
powershell
$ i2cdetect -y 1 # 扫描i2c-1总线
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- UU -- -- -- -- -- -- -- -- -- -- --
20: UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 51 52 53 54 55 56 57 -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
输出解密:
--:此地址无设备(或已断电)UU:⚠️警告! 该地址已被内核驱动霸占(如lm75传感器驱动)
→ 强行操作会冲突!需先rmmod对应驱动XX(如0x50):自由身! 可随意读写调试
💡 老司机Tips :
看到
UU别慌!用lsmod | grep i2c查驱动,用rmmod xxx卸掉它,世界瞬间清净~
2️⃣ 看全景:i2cdump - 寄存器X光机
场景 :发现地址0x50有设备,但不确定它内部长啥样?
解法:一键全寄存器扫描!
- 基础版:导出所有寄存器(字节模式)
powershell
$ i2cdump -y 1 0x50 b
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff
10: 01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
...
- 进阶版:只扫关键区域(0x00-0x0F)
powershell
$ i2cdump -y -r 0x00-0x0F 1 0x50
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff
3️⃣ 单点突破:i2cget/i2cset - 精准外科手术
场景 :只想读温度传感器当前值(寄存器0x05)或修改LED亮度(寄存器0x12)
- 读取寄存器值(字节模式)
powershell
$ i2cget -y 1 0x48 0x05 b # 返回 0x4A (74℃)
- 写入寄存器值(字节模式)
powershell
$ i2cset -y 1 0x30 0x12 0xFF # 设置LED最大亮度
- 高级写入:带掩码的位操作(只改bit0-3)
powershell
$ i2cset -y -m 0x0F 1 0x30 0x12 0x0A # 保持bit4-7不变
⚠️ 注意:
b=字节(8位),w=字(16位,注意大小端!)- 遇到
Error: Read failed?八成是地址被驱动占了(UU)
三、终极奥义:i2ctransfer - 破解复杂时序
当遇到16位寄存器地址 、连续读写 或32位数据 时,前面四个命令集体失效!这时必须召唤终极大杀器------i2ctransfer!
语法本质:字节流的精确编排
命令格式:i2ctransfer -y <总线> <操作序列>
wN@addr:写N个字节到设备addrrN:从当前地址读N个字节@addr:指定设备地址(紧跟在w/r后)
经典场景示例
✅ 场景1:向16位地址写入32位数据
向0x1d设备的地址0x0002写入0x7777
powershell
$ i2ctransfer -y 1 w4@0x1d 0x00 0x02 0x77 0x77
字节流解析 :
[0x00, 0x02] = 16位地址0x0002
[0x77, 0x77] = 要写入的32位数据(此处仅用2字节演示)
✅ 场景2:先写地址再连续读
从0x50设备的地址0x1234开始读4字节
powershell
$ i2ctransfer -y 1 w2@0x50 0x12 0x34 r4
硬件行为:
- 发送
S + 0x50(W) + 0x12 + 0x34 + Sr - 立即切读模式收4字节:
Sr + 0x50(R) + data1 + data2 + data3 + data4 + P
🔥 划重点 :
w2表示写2字节 (即地址),r4表示读4字节(数据)
四、深度思考:谁决定了地址宽度?
你曾困惑:
i2ctransfer -y 1 w8@0x1d 0x00 0x02 0x04 0x77 0x88 0x99 0xaa 0xbb
这8个字节到底怎么解析?
残酷真相:I2C总线是"哑巴快递员"!
- 它不关心你发的是地址还是数据
- 它只负责把字节流原样发出去
- 如何解析 完全由芯片数据手册决定!
三种可能解读(取决于芯片设计):
| 芯片类型 | 地址宽度 | 数据解析方式 | 实际效果 |
|---|---|---|---|
| 8位小短腿 | 1字节 | 首字节=地址,余下7字节=数据 | 写0x00-0x06地址 |
| 16位规范派 | 2字节 | 前2字节=地址,余下6字节=数据 | 从0x0002开始写6字节 |
| 32位高富帅 | 4字节 | 前4字节=地址,余下4字节=数据 | 向0x00020477写0x8899aabb |
工程师的破局之道:翻!数!据!手!册!
- 找到芯片的 "Protocol/Timing Diagram" 章节
- 确认 Address Bytes(地址长度)
- 确认 Byte Order(大小端:MSB/LSB first)
- 确认 Data Alignment(数据对齐方式)
📜 血的教训 :
某次调试PMIC时,因忽略手册写的小端模式 ,把地址
0x1234错写成0x3412,导致寄存器被写到错误位置,查了三天才发现!
五、高手心得:避坑指南
-y是你的好朋友:跳过确认提示,脚本必备- 敬畏
UU标记 :操作前用ls /sys/bus/i2c/drivers/查驱动 - 物理层常识 :扫描全是
--?检查上拉电阻和供电! - 善用组合技:
快速查看传感器原始数据
powershell
$ i2ctransfer -y 2 w1@0x4c 0x00 r2 | od -t x2
od:格式化输出命令-t x2:指定输出格式为十六进制(x),且每 2 个字节(2)为一组进行显示od -t x2:将接收到的原始数据,以每 2 个字节为一组的十六进制数形式显示
结语:你即是规则制定者
当你在OpenBMC中敲下i2ctransfer命令时,你不再是被动使用者------你成了I2C世界的造物主。那些冰冷的字节流将在你的指挥下,精准叩开硬件芯片的大门。记住:每一次成功的寄存器读写背后,都有一份被汗水浸透的数据手册在支撑。
硬件调试如同侦探破案,线索藏在比特之间,而你是手握万用表的福尔摩斯。��️♂️🔧
(完)