Linux I2C读写调试
目录
目录
i2cdetect -q可以探测到I2C从设备但i2cdetect -r探测不到
前言
在嵌入式开发中,确认I2C硬件设备是否正常连接、设备是否正常工作、设备的地址是多少等问题,可以使用测试I2C总线的工具:i2c-tools。
i2c-tools工具是一个专门调试I2C的开源工具,可获取挂载的设备及设备地址,还可以读取I2C设备寄存器。
它比传统调试方式(修改驱动代码寄存器值->编译->下载->运行->看结果)节省时间。
i2cdetect命令
i2cdetect命令参数查询
# i2cdetect
BusyBox v1.31.1 (2023-07-14 19:40:49 CST) multi-call binary.
Usage: i2cdetect -l | -F I2CBUS | [-ya] [-q|-r] I2CBUS [FIRST LAST]
Detect I2C chips
-l List installed buses (列出已安装的总线)
-F BUS# List functionalities on this bus (列出此总线上的功能)
-y Disable interactive mode (关闭交互式,不会显示警告信息)
-a Force scanning of non-regular addresses(强制扫描非规则地址)
-q Use smbus quick write commands for probing (default) (使用smbus快速写入命令进行探测)
-r Use smbus read byte commands for probing(使用smbus读取字节命令进行探测)
FIRST and LAST limit probing range (第一个和最后一个极限探测范围)
列出I2C总线
# i2cdetect -l
i2c-3 i2c test-i2c I2C adapter
i2c-0 i2c test-i2c I2C adapter
- 列出某个I2C总线上的I2C设备
“--”表示I2C从机地址被检测到了,但是没有该地址具体的从设备,“UU”表示地址正在被某个驱动使用,数值一般表示有该设备但是没有对应的设备驱动。
# i2cdetect -y -r 0 (列出I2C0总线上的所有从设备)
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- UU -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- 5d -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
# i2cdetect -y -r 3 (列出I2C3总线上的所有从设备)
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- 29 -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- 45 -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
列出I2C控制器支持的功能
`i2cdetect -F <总线编号>`命令可以列出I2C控制器支持的功能,包括:
- 各种I2C传输模式。
- 特殊功能支持。
- 总线限制和特性。
# i2cdetect -F 1
Functionalities implemented by bus #1
I2C yes
SMBus quick command yes
SMBus send byte yes
SMBus receive byte yes
SMBus write byte yes
SMBus read byte yes
SMBus write word yes
SMBus read word yes
SMBus process call yes
SMBus block write yes
SMBus block read no
SMBus block process call no
SMBus PEC yes
I2C block write yes
I2C block read yes
#
# i2cdetect -F 2
Functionalities implemented by bus #2
I2C yes
SMBus quick command yes
SMBus send byte yes
SMBus receive byte yes
SMBus write byte yes
SMBus read byte yes
SMBus write word yes
SMBus read word yes
SMBus process call yes
SMBus block write yes
SMBus block read no
SMBus block process call no
SMBus PEC yes
I2C block write yes
I2C block read yes
i2cdetect -q和i2cdetect -r的区别
i2cdetect -q和i2cdetect -r是用于检测I2C总线上设备的两种不同模式,它们的主要区别在于探测设备时所使用的底层通信方法。
i2cdetect -q使用SMBus “Quick Write”命令进行探测。这种方式会向设备地址发送一个写入信号,但并不实际传输任何数据字节。这相当于一种非常轻量级的“敲门”操作,
旨在查看设备是否会应答。
i2cdetect -r则使用SMBus “Receive Byte”命令进行探测。这种方式会尝试从设备读取一个字节的数据。可以将其理解为一种“直接读取”的尝试。
这两种模式探测结果的差异主要源于它们与不同I2C设备兼容性的不同。
-q(Quick Write)适用于大多数标准的I2C从设备。然而,对于一些特殊的设备,特别是那些只响应读操作或者协议要求必须先写入地址再进行读取的设备(即“先写再读”),-q模式可能无法成功探测到。
-r(Receive Byte)适用于能够检测到那些仅对读命令作出响应的设备。当使用默认模式(或-q模式)无法检测到设备,而使用-r参数却能发现时,通常意味着该设备属于这类“只读响应”或需要特定读时序的类型。
i2cdetect -q可以探测到I2C从设备但i2cdetect -r探测不到
i2cdetect -q能够探测到I2C从设备而i2cdetect -r却探测失败,这通常表明该设备在通信协议或内部状态上存在特定的行为模式。
这种情况的核心原因在于两种探测模式使用了不同的底层SMBus命令,而该设备可能只响应其中一种。
-q参数的行为使用SMBus “Quick Write”命令,它仅仅向设备地址发送一个写入信号,并不实际传输任何数据字节,可以看作是一种轻量级的“敲门”操作,仅用于确认设备是否存在。
-r参数的行为使用SMBus "Receive Byte"命令,它会尝试执行一个复合操作:先发送设备地址(带写位),然后立即读取一个字节的数据。
该设备能够响应-q的“敲门”但不响应-r的“读取尝试”,可能由以下原因导致:
- 设备需要初始化写入:某些I2C设备在能够返回数据之前,必须向向内部寄存器写入一个命令或地址指针。-r命令发起的“空读取”由于缺少必要的前置写入命令,可能导致设备无响应或返回NACK。
- 设备处于特定状态:设备可能处于某种模式(如睡眠模式、低功耗模式),此时它会响应简单的存在性探测(-q),但拒绝执行需要消耗更多的读数据操作(-r)。
- 协议时序不兼容:-r模式产生的特定通信时序(如“重复起始条件”)可能与该设备的期望不完全匹配。
面对上面这些情况,可以尝试以下方法进行验证和进一步操作:
1. 直接尝试通信:既然以确认设备存在,最有效的方法是跳过探测,直接使用i2cget或i2ctransfer等工具,按照设备的数据手册提供的正确协议与设备通信。
2. 检查设备电源与配置:确保设备供电充足,能够支持完整的读写操作。检查设备是否有需要通过GPIO控制的使能引脚,并确保其已被正确配置。
3. 验证I2C总线状态:使用`i2cdetect -F <总线编号>`可以检查总线的功能标志,确保总线是否支持所有必要的模式。
i2cget命令
i2cget主要用于获取某总线某从设备的寄存器值,其中“-f”:强制访问设备,“-y”:取消交互模式。默认情况下,将等待用户的确认,当使用此标志时,它将直接执行操作。
例如:
# i2cget -f -y 0 0x27 0x28 (获取I2C0总线从设备0x27寄存器0x28的值)
0x21 (获取到的寄存器的值)
i2cset命令
i2cset主要用于设置某总线某从设备的寄存器值,其中“-f”:强制访问设备,“-y”:取消交互模式。默认情况下,将等待用户的确认,当使用此标志时,它将直接执行操作。
例如:
# i2cset -f -y 0 0x27 0x28 0x22 (设置I2C0总线从设备0x27寄存器0x28的值)
i2cdump命令
查看某一个I2C总线上某一个I2C从设备所有寄存器的值,注意其中的寄存器地址为8位。
例如,查看I2C0上地址为0x27从设备的所有寄存器的值:
# i2cdump -f -y 0 0x27
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 00 13 13 08 93 11 d3 ba 00 00 00 00 00 00 00 40 .???????.......@
10: 05 1e 01 00 00 00 07 00 00 04 00 00 00 00 00 00 ???...?..?......
20: 01 0b 00 00 00 00 00 03 22 00 04 0a 00 00 00 00 ??.....?".??....
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
i2ctranfer命令
一般寄存器都是8位地址,i2cdump、i2cget、i2cset也是设置读取8位地址,如果一次读写超过8位,则需要使用i2ctranfer。
所以i2ctranfer主要用于一次性读写多个字节的数据。
例如:
向寄存器地址为8位的从设备0x27的寄存器0x27写入数据:
# i2ctransfer -f -y 0 w2@0x27 0x27 0x04
从寄存器地址为8位的从设备0x27的寄存器0x27读取数据:
# i2ctransfer -f -y 0 w1@0x27 0x27 r1
0x04
向寄存器地址为16位的从设备0x29的寄存器0x0180写入数据:
# i2ctransfer -f -y 3 w3@0x29 0x01 0x80 0x46
其中:
3:哪条总线
w2:写两个字节地址
0x01 0x80:寄存器地址为8位
0x46:0x01 0x80寄存器地址往后的寄存器写入0x46
从寄存器地址为16位的从设备0x29的寄存器0x0180读取数据:
# i2ctransfer -f -y 3 w2@0x29 0x01 0x80 r1
0x46
其中:
3:哪条总线
w2:写两个字节地址
0x01 0x80:寄存器地址为8位
r1:往后1个寄存器所对应的寄存器值
总结
i2c-tools是通过操作/dev路径下的i2c-x设备文件完成的,因此kernel必须开启CONFIG_I2C_CHARDEV宏控,否则会报找不到对应的节点。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)