当前位置: 首页 > article >正文

Linux上的`i2c-tools`工具集的详细介绍;并利用它操作IMX6ULL的I2C控制器进而控制芯片AP3216C读取光照值和距离值

I²C-Tools 工具集介绍

i2c-toolsLinux 下用于 I²C 设备调试 的用户空间工具集(你也可以把它看成是一个库,类似于之前自己用过的触摸屏库tslib库、FreeType矢量字符库),它提供了一系列命令行工具,可以扫描、读取、写入 I²C 设备,非常适合嵌入式开发和调试 I²C 设备,如 传感器、EEPROM、GPIO 扩展器 等。


1. i2c-tools 的主要工具

i2c-tools 工具集主要包含以下几个命令:

命令作用
i2cdetect扫描 I²C 总线,查找可用的设备地址
i2cdump读取 I²C 设备的全部寄存器数据
i2cget读取 I²C 设备某个寄存器的数据
i2cset向 I²C 设备某个寄存器写入数据
i2ctransfer发送更复杂的 I²C 读/写命令

2. i2c-tools 详细命令解析

(1)i2cdetect — 扫描 I²C 设备

功能
扫描 I²C 总线上的设备,显示哪些地址上有响应的 I²C 设备。

使用示例

i2cdetect -y 1
  • 扫描 I²C 总线 1,并显示已连接设备的地址。

输出示例

     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- 77                         
  • 4877 代表有设备响应。
  • -- 代表该地址无设备响应。

(2)i2cdump — 读取 I²C 设备所有寄存器

功能
读取 I²C 设备的全部寄存器内容,适用于调试寄存器数据。

使用示例

i2cdump -y 1 0x50
  • 读取 I²C 总线 10x50 地址 设备的寄存器数据。

输出示例

     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
00: 12 34 56 78 90 AB CD EF 12 34 56 78 90 AB CD EF 
10: 12 34 56 78 90 AB CD EF 12 34 56 78 90 AB CD EF 
...
  • 以 16 进制格式显示 I²C 设备的寄存器内容。

(3)i2cget — 读取单个寄存器

功能
读取 I²C 设备某个寄存器 的值。

使用示例

i2cget -y 1 0x50 0x10
  • 读取 I²C 总线 10x50 设备 0x10 寄存器 的值。

输出示例

0xAB
  • 说明 0x10 地址 处的值是 0xAB

(4)i2cset — 写入 I²C 设备寄存器

功能
I²C 设备某个寄存器 写入数据。

使用示例

i2cset -y 1 0x50 0x10 0xAB
  • I²C 总线 10x50 设备 0x10 寄存器 写入 0xAB

写入多字节

i2cset -y 1 0x50 0x10 0x12 0x34 i
  • I²C block 模式 写入 0x12 0x34

(5)i2ctransfer — 复杂 I²C 读/写

功能
因为i2ctransfer是比较底层的命令,所以它灵活,所以它允许更复杂的 I²C 数据传输,例如:

  • 一次性读/写多个字节
  • 自定义 I²C 消息格式
  • 精确控制 I²C 事务

写入 2 字节

i2ctransfer -y 1 w2@0x50 0x10 0xAB
  • 0x50 设备 0x10 寄存器 写入 2 字节数据 0xAB

读取 2 字节

i2ctransfer -y 1 r2@0x50
  • 0x50 设备 读取 2 字节 数据。

3. i2c-tools 安装到Linux系统

在大多数 Linux 发行版中可以直接安装:

  • Debian/Ubuntu
    sudo apt install i2c-tools
    
  • CentOS/RHEL
    sudo yum install i2c-tools
    
  • Yocto
    local.conf 添加:
    IMAGE_INSTALL_append = " i2c-tools "
    
  • IMX6ULL_PRO等嵌入式开发板
    和tslib库的安装类似,先在Ubuntu中编译出库文件,然后把相关文件复制到IMX6ULL_PRO嵌入式开发板上,同时还要把相关的头文件复制到交叉编译器的头文件搜索目录中,这些这程可参考tslib库的安装,相关博文 https://blog.csdn.net/wenhao_ir/article/details/144621008 【搜索“tslib的交叉编译”,然后开始看】
    由于很多芯片的官方BSP都集成了i2c-tools 库,所以需要自己去编译安装i2c-tools 的时间不多,所以这里我就不去尝试自己编译安装了。

4. 查看自己的两个开发板的Linux系统中是否有i2c-tools

先说明一下,直接运行命令i2cdetect,如果有提示这个命令怎么用,那么就证明当前Linux系统中已经集成了i2c-tools

i2cdetect

在这里插入图片描述
上面的运行结果表明当前Linux系统中已经集成了i2c-tools

IMX6ULL_PRO开发板出厂提供的Linux系统中包含有i2c-tools

1号开发板是开发板商出厂时提供的Linux内核和设备树文件。

在1号开发板上运行命令i2cdetect的结果如下:
在这里插入图片描述
这证明IMX6ULL_PRO开发板出厂提供的Linux系统中包含有i2c-tools

NXP官方提供的BSP中包含有i2c-tools

2号开发板是我自己用NXP官方提供的BSP移植的Linux内核和设备树文件。

在2号开发板上运行命令i2cdetect的结果如下:
在这里插入图片描述
这证明NXP官方提供的BSP中包含有i2c-tools

5. 小结

i2c-toolsLinux 下的 I²C 调试工具集,适用于嵌入式设备调试。
✔ 提供 设备扫描、数据读取、数据写入 等命令:

  • i2cdetect:扫描 I²C 设备。
  • i2cdump:读取设备所有寄存器。
  • i2cget:读取单个寄存器。
  • i2cset:写入单个寄存器。
  • i2ctransfer:高级 I²C 操作。
    ✔ 在 IMX6ULL 开发板、树莓派等嵌入式 Linux 设备上广泛使用。

i2c-tools 工具集使用的前提:存在相关的I2C控制器的设备文件

首先需要Linux的I2C子系统提供了相关的I2C控制器的设备文件。我猜 i2c-tools 也会像tslib那样去扫描获取相关的设备文件。我们可以用下面的命令查看系统的I2C子系统提供的I2C控制器的设备文件。

ls /dev/i2c-*

运行结果如下:
在这里插入图片描述
i2c-tools 在工作运行时,就会扫描获取到这两个I2C控制器的设备文件,然后用这两个设备文件进行相关操作。设备文件的名字末尾的数字就是i2c-tools 各命令中需要的I2C控制器的编号。

i2c-tools 工具集所使用的协议:SMBus协议和I2C协议

i2c-tools 工具集有部分命令是基于SMBus协议,有部分命令是基于SMBus协议。不过由于SMBus协议是I2C协议的子集,所以只要设备是I2C设备,就可以运行SMBus协议。

SMBus协议的详细介绍见博文 https://blog.csdn.net/wenhao_ir/article/details/146336623

检测扫描命令i2cdetect的实操记录

查看当前Linux系统中有多少个I2C控制器

1号开发板的运行结果

可以用下面的命令来查看当前Linux系统中有多少个I2C控制器及各自的基本信息:

i2cdetect -l

在这里插入图片描述

[root@imx6ull:~]# i2cdetect -l
i2c-1   i2c             21a4000.i2c                             I2C adapter
i2c-0   i2c             21a0000.i2c                             I2C adapter

可见,有两个,其实IMX6ULL芯片上一共也只有两个I2C控制器,它们的设备文件名分别为i2c-1、i2c-0,它们被命令名I2C adapter,它们各自的内存地址为21a4000、21a0000。

2号开发板的运行结果

i2cdetect -l

在这里插入图片描述

检测某个I2C控制器上有哪些设备

编号为0的I2C控制器上的设备

1号开发板的运行结果

假设现在我要检测编号为0的I2C控制器上是否有设备,那么运行下面这条命令即可:

i2cdetect 0

运行之后会提示你这个操作可能会干扰该条I2C总线上目前正在工作的I2C设备,因为它要发送各设备的地址,然后让设备得到回应嘛。我们回答y就是了。

在这里插入图片描述
当然你也可像下面这样写:

i2cdetect -y 0

这样就可以屏蔽命令运行过程中的交互,也就不用需要回答y了。

在这里插入图片描述
这个结果说明,在0x1e的地址上,有一个I2C设备,但是在内核中还不存在这个设备的驱动程序,所以显示为其地址值,如果在内核中存在这个设备的驱动程序,那么应该显示为UU,如下图所示:
在这里插入图片描述
这里顺便说一下,地址为0x1e的I2C设备其实是芯片AP3216C,它能进行光照强度测量和距离检测、并且通信接口为I2C,它的详细介绍见博客 https://blog.csdn.net/wenhao_ir/article/details/146326884

2号开发板的运行结果
i2cdetect 0

在这里插入图片描述

编号为1的I2C控制器上的设备

1号开发板的运行结果

按照上面的方法,我们再顺便检测下编号为1的I2C控制器上的设备:

i2cdetect 1

在这里插入图片描述
可见,编号为1的I2C控制器上有四个设备,地址分别为0x1a、0x39、0x5d、0x60,前三个设备在内核中是有驱动程序的,最后一个地址为0x60的设备是在内核中没有驱动程序的。

2号开发板的运行结果
i2cdetect 1

在这里插入图片描述

1号开发板和2号开发板运行结果的分析

1号开发板是开发板商出厂时提供的Linux内核和设备树文件。
2号开发板是我自己用NXP官方提供的BSP移植的Linux内核和设备树文件。

这说明NXP官方提供的BSP里已经包含了IMX6ULL的I2C控制器的底层驱动,并且接入了Linux的I2C子系统。一旦一个I2C控制器被正确启用并被接入Linux的I2C子系统,那么就能使用i2c-tools 工具集检测并操作相关I2C总线上的I2C设备了。

写入数据命令i2cset的格式的详解

可以直接在命令行中输入命令i2cset来查看其格式:

i2cset

运行结果如下:
在这里插入图片描述
详细介绍如下:
i2cset 是 Linux 命令行工具,用于向 I²C 设备的寄存器写入数据。它属于 i2c-tools 工具集,常用于调试 I²C 设备。


1. 基本语法

i2cset [-fy] [-m MASK] BUS CHIP-ADDRESS DATA-ADDRESS [VALUE] ... [MODE]

其中:

  • BUS:I²C 总线号,通常对应 /dev/i2c-X 设备中的 X
  • CHIP-ADDRESS:I²C 设备地址(7 位地址,范围 0x030x77)。
  • DATA-ADDRESS:要写入数据的寄存器地址(从设备内部的寄存器)。
  • VALUE(可选):要写入的数值。如果 MODE 允许多个值,则可以写入多个数据。
  • MODE(可选):数据的传输模式(见下文)。
  • 额外的 选项(如 -f-y)可用于控制操作方式。

2. 选项说明

  • -f :强制访问设备,即使它可能正在使用(风险较高,谨慎使用)。
  • -y :禁用交互模式,不再要求用户确认写入(默认情况下会有提示以防误操作)。
  • -r :在写入后读取并比较结果(用于确认写入是否成功)。
  • -m MASK :使用掩码选择要写入的特定位。例如 -m 0xF0 仅修改高 4 位,低 4 位保持不变。

3. MODE 参数
MODE 指定数据写入的方式,支持以下几种:

MODE说明
c只写数据地址,不写入任何数据(通常用于触发某些设备的操作)。
b写入 1 字节(默认模式)。
w写入 2 字节(word)。
iI²C 块数据 方式写入多个字节(I²C block write)。
sSMBus 块数据 方式写入多个字节(SMBus block write)。
p追加 p 启用 SMBus 的 PEC(Packet Error Checking)校验。

4. 示例
#(1)写入一个字节

i2cset -y 1 0x50 0x10 0xAB
  • 在 I²C 总线 1 上,向地址 0x50 的设备写入数据:
    • 0x10 作为寄存器地址。
    • 0xAB 作为要写入的数据(默认 b 模式,即 1 字节)。

#(2)写入 2 字节(word)

i2cset -y 1 0x50 0x10 0x1234 w
  • 0x50 设备的 0x10 寄存器写入 0x1234(2 字节)。

#(3)写入 SMBus 块数据

i2cset -y 1 0x50 0x10 0x01 0x02 0x03 s
  • 0x50 设备 0x10 寄存器写入 0x01 0x02 0x03(SMBus block write)。

#(4)使用掩码修改部分位

i2cset -y -m 0xF0 1 0x50 0x10 0xAB
  • 仅修改 0x10 寄存器的高 4 位(0xF0 掩码)。

5. 注意事项

  • 确保设备地址正确,误操作可能会影响 I²C 总线上的其他设备。
  • 使用 -y 选项时要谨慎,否则 i2cset 可能直接写入数据而不提示确认。
  • 强制写入 -f 有风险,可能导致总线冲突或设备异常。

读数据命令i2cget的格式的详解

可以直接在命令行中输入命令i2cset来查看其格式:

i2cget

运行结果如下:
在这里插入图片描述
详细介绍如下:

i2cgeti2c-tools 工具集中的一个命令,用于读取 I²C 设备的寄存器数据


🔹 语法解析

i2cget [-fy] BUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]
参数含义
BUSI²C 控制器编号(总线编号),比如 01,可以通过 i2cdetect -l 查看
CHIP-ADDRESSI²C 设备地址(7 位地址),通常在 0x03 ~ 0x77 之间
DATA-ADDRESS要读取的寄存器地址(可选),如果省略,则直接读取设备数据
MODE读取模式(可选),默认为 b(字节读取)

🔹 选项说明

选项作用
-f强制访问 I²C 设备(忽略内核的安全检查)
-y关闭交互模式,直接执行操作而不要求用户确认

🔹 读取模式

模式含义
b读取 1 字节数据(默认)
w读取 2 字节(16-bit word)数据
c先写 1 字节数据,再读取 1 字节数据(适用于某些设备)
p附加 SMBus PEC(Packet Error Checking)错误检测

🔹 示例
#✅ 1. 读取设备的整个数据(无指定寄存器)

i2cget -y 1 0x1E
  • 读取 I²C 设备地址 0x1E 的数据(不指定寄存器)。
  • -y 选项表示不提示用户确认。

#✅ 2. 读取 AP3216C 传感器 0x00 寄存器的值

i2cget -y 1 0x1E 0x00
  • 读取 设备 0x1E0x00 号寄存器(系统配置寄存器)。

#✅ 3. 读取 16-bit(word)数据

i2cget -y 1 0x1E 0x0C w
  • 读取 设备 0x1E0x0C 号寄存器16-bit 数据
  • 适用于返回 2 字节(word)的设备,如某些传感器。

#✅ 4. 先写 1 字节数据,再读取 1 字节数据

i2cget -y 1 0x1E 0x00 c
  • 先写 0x00 到设备 0x1E,然后读取 1 字节数据。
  • 适用于某些 需要寄存器索引 的设备。

🔹 小结

  • i2cget 用于从 I²C 设备的寄存器读取数据
  • 默认读取 1 字节(可选 w 读取 2 字节)。
  • -f 强制访问,-y 关闭交互模式
  • 可以配合 i2cset 进行写入操作

使用读写命令行对I2C设备AP3216C进行读写操作

AP3216C是能进行光照强度测量和距离检测、并且通信接口为I2C的芯片,它的详细介绍见博客 https://blog.csdn.net/wenhao_ir/article/details/146326884
当它通过I2C挂接到我们的Linux系统的I2C总线上后,我们例可以用I2C总线对它进行读写操作了。在这里,我们用i2c-tools工具集的命令对它进行读写操作,从而利用AP3216C读出光照强度和距离值。

第01条命令-写数据:软复位AP3216C

i2cset -f -y 0 0x1e 0 0x4

在这里插入图片描述
前面已经详细介绍了命令i2cset,这里就不再详细赘述。
-f :表示强制访问设备,即使它可能正在使用。
-y :禁用交互模式,不再要求用户确认写入(默认情况下会有提示以防误操作)。
第1个0:表示使用第0个I2C控制器,也可以看成是I2C总线的编号嘛。
0x1e:表示AP3216C这个I2C设备的地址。
第2个0:表示AP3216C中要写入数据的寄存器地址。
0x4:表示写入的值为0x4,表示软复位AP3216C。
关于AP3216C的0号寄存器的详细介绍见博文 https://blog.csdn.net/wenhao_ir/article/details/146326884

第02条命令-写数据:启用AP3216C的光感和距离检测功能

i2cset -f -y 0 0x1e 0 0x3

在这里插入图片描述
前面已经详细介绍了命令i2cset,这里就不再详细赘述。
-f :表示强制访问设备,即使它可能正在使用。
-y :禁用交互模式,不再要求用户确认写入(默认情况下会有提示以防误操作)。
第1个0:表示使用第0个I2C控制器,也可以看成是I2C总线的编号嘛。
0x1e:表示AP3216C这个I2C设备的地址。
第2个0:表示AP3216C中要写入数据的寄存器地址。
0x3:表示写入的值为0x3,表示“ALS and PS+IR functions active”,即把AP3216C的ALS (Ambient Light Sensor)光感和Proximity (接近传感器) 都激活。
关于AP3216C的0号寄存器的详细介绍见博文 https://blog.csdn.net/wenhao_ir/article/details/146326884

第03条命令-读取光照强度数据

i2cget -f -y 0 0x1e 0x0c w

前面已经详细介绍了命令i2cget,这里就不再详细赘述。
-f :表示强制访问设备,即使它可能正在使用。
-y :禁用交互模式,不再要求用户确认写入(默认情况下会有提示以防误操作)。
第1个0:表示使用第0个I2C控制器,也可以看成是I2C总线的编号嘛。
0x1e:表示AP3216C这个I2C设备的地址。
0x0c:表示要读取AP3216C中的目标寄存器的地址。
w:表示读取一个字,即两个字节的值。
关于AP3216C的0x0c号寄存器的详细介绍见下面这张截图:
在这里插入图片描述
由于我们附加了参数w,所以这里其实我们这里读取的是0x0c和0x0d寄存器的值。
读取的结果如下:
在这里插入图片描述
我们再用手电筒照向这个芯片,然后再读这个值,看有没有变化:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可见,值从0x0000变成了0x24e2。

第04条命令-读取距离值

i2cget -f -y 0 0x1e 0x0e w

前面已经详细介绍了命令i2cget,这里就不再详细赘述。
-f :表示强制访问设备,即使它可能正在使用。
-y :禁用交互模式,不再要求用户确认写入(默认情况下会有提示以防误操作)。
第1个0:表示使用第0个I2C控制器,也可以看成是I2C总线的编号嘛。
0x1e:表示AP3216C这个I2C设备的地址。
0x0e:表示要读取AP3216C中的目标寄存器的地址。
w:表示读取一个字,即两个字节的值。
关于AP3216C的0x0e号寄存器的详细介绍见下面这张截图:
在这里插入图片描述
其中第7位和第6位的详细说明见博文 https://blog.csdn.net/wenhao_ir/article/details/146326884 【搜索“其中第7位(Object detect)”】

由于我们附加了参数w,所以这里其实我们这里读取的是0x0e和0x0f寄存器的值。
读取的结果如下:
在这里插入图片描述
这个值我们得转换成二进制然后翻译一下:

0xb18d = 0b 10110001 10001101

所以PS_Data_Low的值为 1000 1101,分析如下:
PS_Data_Low[7]的值为1,代表“The object closed”,意思是物体在检测范围内,PS_Data_Low[6]的值为0,代表数据有效。PS_Data_Low[3:0]代表测量出的距离值的低4位,具体的值为0b1101

所以PS_Data_High的值为 1011 0001,分析如下:
PS_Data_High[7]的值为1,代表“The object closed”,意思是物体在检测范围内,PS_Data_High[6]的值为0,代表数据有效。PS_Data_High[5:0]代表测量出的距离值的高6位,具体的值为0b11 0001

把PS_Data_Low[3:0]和PS_Data_High[7]的值组合起来为:
0b11 0001 1101 = 0d797

现在我用我的手指靠近AP3216C,再去读PS_Data寄存器的值,结果如下:
在这里插入图片描述
可见值变成了0xbf8f = 0b10111111 10001111
此时把PS_Data_Low[3:0]和PS_Data_High[7]的值组合起来为:
0b1111111111 = 1023 ,因为我的指头几乎快挨着AP3216C了,所以距离值变了最大值1023,可见,对于AP3216C,距离越近,传感得到的距离值越大。


http://www.kler.cn/a/591062.html

相关文章:

  • 【算法题解答·七】哈希
  • VulnHub-Billu_b0x通关攻略
  • EditRocket for Mac v5.0.2 文本编辑器 支持M、Intel芯片
  • 基于多头注意机制的多尺度特征融合的GCN的序列数据(功率预测、故障诊断)模型及代码详解
  • 在WINDOWS中如何运行VBS脚本,多种运行方式
  • vscode vue3 jsconfig 与 tsconfig的区别
  • 扩展01:企业级Nginx+Keepalived双主架构实战
  • Hyperlane:Rust 语言打造的 Web 后端框架新标杆
  • LLM中lora的梯度更新策略公式解析
  • WiFi IEEE 802.11协议精读:IEEE 802.11-2007,19,ERP specification,802.11g,整合15/17/18
  • reactive数据修改无效
  • Visual Studio2022 中的键盘注释快捷方式
  • R语言绘图 | 环状柱状图+散点柱状组合图绘制
  • Spring中的循环依赖问题是什么?
  • 五种方案实现双链路可靠数据传输
  • 顺序表的C语言实现与解析
  • MySQL事务介绍
  • Vala编程语言教程-运算符
  • 算法刷题记录——LeetCode篇(3) [第201~300题](持续更新)
  • 蓝桥杯16