Linux驱动.之I2C,iic驱动框架,之应用开发,以及i2c-tools工具使用(二)

本文介绍了Linux下的i2c-tools工具,包括安装、使用方法和常见命令,如i2cdetect、i2cdump、i2cget、i2cset以及i2ctransfer,用于调试i2c总线和设备。通过实例展示了如何检测和操作i2c设备的寄存器,以及如何进行读写操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、通过命令 对i2c读写命令

hisi写的,封装的一个app应用程序,做成shell命令,在终端,通过命令 对i2c读写命令, 此操作示例通过 I2C 读写命令
实现对 I2C 外围设备的读写操作。

1、在控制台使用 i2c_read 命令对 I2C 外围设备进行读操作:

 i2c_read <i2c_num> <device_addr> <reg_addr> <end_reg_addr><reg_width> <data_width> <reg_step> 

i2c_num:I2C 控制器序号(对应《Hi35xx H.265 编解码处理器用户指南》中的 I2C 控制器
device_addr:外围设备地址(Hi35xx 支持标准地址(7bit)和扩展地址(10bit))
reg_addr:读外围设备寄存器操作的开始地址
end_reg_addr:读外围设备寄存器操作的结束地址
reg_width:外围设备的寄存器位宽(Hi35xx 支持 8/16bit)
data_width:外围设备的数据位宽(Hi35xx 支持 8/16bit)
reg_step:连续读外围设备寄存器操作时递增幅值,默认为 1,即连续读寄存器,读取单个寄存

例如读挂载在 I2C 控制器 0 上的 sil9024 设备的 0x8 寄存器:

i2c_read 0 0x72 0x8 0x8 0x1 0x1

2、在控制台使用 i2c_write 命令对 I2C 外围设备进行写操作:

i2c_write <i2c_num> <device_addr> <reg_addr> <value> <reg_width><data_width>

i2c_num:I2C 控制器编号(对应《Hi35xx H.265 编解码处理器用户指南》中的 I2C 控制器
device_addr:外围设备地址(Hi35xx 的 I2C 控制器支持标准地址(7bit)和扩展地址(10bit))
reg_addr:写外围设备寄存器操作的地址
value:写外围设备寄存器操作的数据
reg_width:外围设备的寄存器位宽(Hi35xx 的 I2C 控制器支持 8/16bit)
data_width:外围设备的数据位宽(Hi35xx 的 I2C 控制器支持 8/16bit)

例如向挂载在 I2C 控制器 0 上的 sil9024 设备的 0x8 寄存器写入数据 0xa5:

 i2c_write 0 0x72 0x8 0xa5 0x1 0x1

这种方法,适合简单测试

二、此操作示例在用户态下,对 I2C 外围设备的读写操作。

步骤 1.
打开 I2C 总线对应的设备文件,获取文件描述符:

fd = open("/dev/i2c-0", O_RDWR);

步骤 2.
通过 ioctl 设置外围设备地址、外围设备寄存器位宽和数据位宽:

ret = ioctl(fd, I2C_SLAVE_FORCE, device_addr);
ioctl(fd, I2C_16BIT_REG, 0);
ioctl(fd, I2C_16BIT_DATA, 0);

设置寄存器位宽和数据位宽时,ioctl 的第三个参数为 0 表示 8bit 位宽,为 1 表示 16bit 位宽。

步骤 3.
使用 read/wite 进行数据读写:

read(fd, recvbuf, reg_width);
write(fd, buf, (reg_width + data_width));

代码示例如下:

unsigned int reg_width = 1;
unsigned int data_width = 1;
unsigned int reg_step = 1;

HI_RET i2c_read(int argc, char* argv[])
{
	 int fd = -1;
	 int ret;
	 unsigned int i2c_num, device_addr, reg_addr, reg_addr_end;
	 char data;
	 char recvbuf[4];
	 int cur_addr;
	 memset(recvbuf, 0x0, 4);
	 fd = open("/dev/i2c-0", O_RDWR);
	 if (fd<0)
	 {
	 	printf("Open i2c dev error!\n");
		 return -1;
 	} 

	 ret = ioctl(fd, I2C_SLAVE_FORCE, device_addr);
	 if (reg_width == 2)
	 ret = ioctl(fd, I2C_16BIT_REG, 1);
	 else{
	 ret = ioctl(fd, I2C_16BIT_REG, 0);
	 if (ret < 0) {
	 printf("CMD_SET_REG_WIDTH error!\n");
	 }
	 close(fd);
	 return -1;
 }
 
 if (data_width == 2)
 ret = ioctl(fd, I2C_16BIT_DATA, 1);
 else
 ret = ioctl(fd, I2C_16BIT_DATA, 0);
 if (ret < 0) {
	 printf("CMD_SET_DATA_WIDTH error!\n");
	 close(fd);
	 return -1;
 }
 
 for (cur_addr = reg_addr; cur_addr < reg_addr_end + reg_width;cur_addr += reg_step)
 {
		 if (reg_width == 2) {
		 recvbuf[0] = cur_addr & 0xff;
		 recvbuf[1] = (cur_addr >> 8) & 0xff;
		 } else
		 recvbuf[0] = cur_addr & 0xff;
		 ret = read(fd, recvbuf, reg_width);
		 if (ret < 0) {
		 printf("CMD_I2C_READ error!\n");
		 close(fd);
		 return -1;
 }
 
	 if (data_width == 2) {
	 data = recvbuf[0] | (recvbuf[1] << 8);
	 } else
	 data = recvbuf[0]; 
	 printf("0x%x 0x%x\n", cur_addr, data);
	 }
	 close(fd);
	 return 0;
}

HI_RET i2c_write(int argc , char* argv[])
{
		 int fd = -1;
		 int ret =0, index = 0;
		 unsigned int i2c_num, device_addr, reg_addr, reg_value;
		 char buf[4];
		 fd = open("/dev/i2c-0", O_RDWR);
		 if(fd < 0)
		 {
		 printf("Open i2c dev error!\n");
		 return -1;
 }
 
 ret = ioctl(fd, I2C_SLAVE_FORCE, device_addr);
 if (reg_width == 2)
 	ret = ioctl(fd, I2C_16BIT_REG, 1);
 else
 	ret = ioctl(fd, I2C_16BIT_REG, 0);
 if (data_width == 2)
	 ret = ioctl(fd, I2C_16BIT_DATA, 1);
 else
 ret = ioctl(fd, I2C_16BIT_DATA, 0);
 if (reg_width == 2) {
	 buf[index] = reg_addr & 0xff;
	 index++;
	 buf[index] = (reg_addr >> 8) & 0xff;
	 index++;
 } else {
	 buf[index] = reg_addr & 0xff;
	 index++;
 }
 
 if (data_width == 2) { 
	 buf[index] = reg_value & 0xff;
	 index++;
	 buf[index] = (reg_value >> 8) & 0xff;
	 index++;
 } else {
	 buf[index] = reg_value & 0xff;
	 index++;
 }
 
 write(fd, buf, (reg_width + data_width));
 if(ret < 0)
 {
	 printf("I2C_WRITE error!\n");
	 return -1;
 }
 close(fd);
 return 0;
}

三、 i2c-tools 命令测试i2c设备。

工具安装,i2c-tools工具是一个专门调试i2c的,开源,可获取挂载的设备及设备地址,还可以在对应的设备指定寄存器设置值或者获取值等功能。

从开源网站 http://dl.lm-sensors.org/i2c-tools/releases/ 下载i2c-tools,
在这里插入图片描述
修改makefile文件,交叉编译,直接make,进行编译,安装:sudo make install

编译完成后在tools/文件夹下会有如下几个可执行文件,i2cdetect, i2cdump, i2cget, i2cset,将i2cdetect, i2cdump,
i2cget, i2cset push到设备就可以调试了
在这里插入图片描述

二、测试
1、错误认知;

i2c-tools使用之前需要修改设备树和配置相关驱动,其实,只要内核开启,设备树开启相关i2c总线,将设备挂载在硬件上,接上设备即可检测到该总线上i2c芯片。

2、命令介绍:

i2cdetect:检测i2c芯片
i2cdump:查看寄存器值
i2cget:获取单个寄存器值(8位寄存器)
i2cset:设置单个寄存器值(8位寄存器)
i2ctransfer:一次传输多字节数据(16位寄存器)
参数介绍:
-y:禁用交互模式。
-f:强制访问设备。
-r:写入后立即读回该值。

2.1、列出所有可用的i2c总线:i2cdetect -l
在这里插入图片描述
在这里插入图片描述
上图可以看到,总共注册了8条i2c总线
2.2、检测第7条总线上器件:i2cdetect -r -y 7
在这里插入图片描述
1,上面有UU和和数字显示,UU表示此地址已经加载了驱动,具体有没有设备不一定,显示有数字说明探测到设备了,也可能是系统的,不知是谁的。
2,不是所有的i2c设备都能探测到,有些16位寄存器i2c设备无法探测到,可以尝试使用i2ctransfer去尝试读写来判断当前地址是否存在设备;。

另外一种说法:
1、UU表示设备地址的两个从设备已经被驱动占用了,当你卸载掉对应的驱动后,此UU就会变成数据了。
2、数字是,这个地址被芯片使用并应答,dts已经配置了,但是没有加载驱动。

2.3、查看器件所有寄存器的值:i2cdump -f -y i2c总线 器件地址
在这里插入图片描述
列出所有存在的寄存器的值,如0x00=71,0x01=73,以此类推。

2.4 、获取单个寄存器的值:i2cget -y -f i2c总线 器件地址
在这里插入图片描述
读取i2c4总线上的,设备地址为0x4c的设备,寄存器0x00的值,为0x71

2.5、设置单个寄存器的值:i2cset -y -f i2c总线 器件地址
i2cset -y -f 4 0x4c 020 0x77
如图写0xa0的值

三、测试i2ctransfer

i2cdump、i2cget、i2cset只适用于读写8位的寄存器地址, 功能完全可由i2ctransfer代替
在这里插入图片描述
1、i2ctransfer写

如:i2ctransfer -f -y 1 w3@0x36 0x50 0x81 0x01
在这里插入图片描述
0x36为I2C设备的地址, 0x5081为要写的寄存器地址, 0x01为写入的值。

2、i2ctransfer读

i2ctransfer -f -y 1 w2@0x36 0x30 0x0A r3
在这里插入图片描述
0x36为I2C设备的地址, 0x300A为要读的寄存器地址, r3为连续读3Byte, 0x56 0x08 0x41 为读到的寄存器的值。

文章摘抄学习来自:https://blog.youkuaiyun.com/weixin_35367646/article/details/116593331

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值