用户态访问I2C设备

显然内核里面有万能的驱动程序给我们用

看看内核文档 在\linux-4.8.14\Documentation\i2c下面的用户态访问I2C设备

这里有的dev-interface,这里面告诉了什么,我们来看看里面说了什么

用户态访问I2C设备

通常,I2C设备由设备驱动来控制,但是他也可以提供用户空间直接访问适配器上的设备,通过/dev接口。你需要加载I2C-DEV模块

有个i2c-tools 的工具包帮你写好了接口,在网上下好这个工具包

用户态访问I2C设备

进入之后,点击下载

用户态访问I2C设备

下下来之后我们来看一下

用户态访问I2C设备

里面有个头文件

用户态访问I2C设备

人家给你封装好了很多接口,我们拿上图那个例子来看一看怎么实现的

用户态访问I2C设备

还不是用ioctl函数实现的。

那么这些ioctl对应的是什么文件呢,

用户态访问I2C设备

对应的就是i2c-dev这个驱动程序,我们看看这个驱动程序做了什么事情,看看这个驱动的入口函数

用户态访问I2C设备

register_chrdev 首先注册一个字符设备,看看fops

用户态访问I2C设备

来看看open函数

用户态访问I2C设备

这里给你创建了i2c_client,i2c_client里面要有适配器啊,i2c_client要用适配器来发出i2c命令啊,根据你打开设备节点的次设备号,来得到适配器

再看看设备地址,是通过ioctl穿进去的,在我们ioctl里面有这么一行

用户态访问I2C设备

这里有个client->addr=arg。

我们来看一下简单的读函数

用户态访问I2C设备

他用的i2c_master_recv来帮你读,如果我们想用smbus那套代码,我们进入IOCTL里面,看看

用户态访问I2C设备

有个这个参数,进入看一下,

用户态访问I2C设备

这里是对各种参数的判断,最后

用户态访问I2C设备

最后调用的i2c_smbus_xfer来进行传输,里面内部实现占时不用关心


我们来写程序来实现,要拿出i2c-tool里面的头文件


如果你开发板下的/dev目录下没有i2c-x这些节点,那么请看你的内核配置

用户态访问I2C设备

用户态访问I2C设备

是这个i2c-dev这个文件,然后是由CONFIG_I2C_CHARDEV来配置的,是这个宏

我们在内核里面搜索

用户态访问I2C设备

打开这个宏就行了


代码如下

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include "i2c-dev.h"


/*i2c_usr_test </dev/i2c-x> <dev_addr> r addr
  *i2c_usr_test </dev/i2c-x> <dev_addr> w addr val
*/
void print_usage(char *file)
{
printf("%s </dev/i2c-x> <dev_addr> r addr\n",file);
printf("%s </dev/i2c-x> <dev_addr> w addr val \n",file);
}


int main(int argc,char **argv)
{
    unsigned char addr,data;
int fd;
int dev_addr;


if((argc!=5)&&(argc !=6))
{
print_usage(argv[0]);
return 0;
}


fd=open(argv[1],O_RDWR);
if(fd<0)
{
printf("can't open %s\n",argv[1]);
return -1;
}


dev_addr=strtoul(argv[2],NULL,0);


if(ioctl(fd,I2C_SLAVE,dev_addr)<0)
{
printf("set addr error\n");
return -1;
}


if(strcmp(argv[3],"r")==0)
{
addr=strtoul(argv[4],NULL,0);
data=i2c_smbus_read_word_data(fd,addr);
printf("data : %c,%d,0x%x\n",data,data,data);
}
else if (strcmp(argv[3],"w")==0)
{
addr=strtoul(argv[4],NULL,0);
data=strtoul(argv[5],NULL,0);
i2c_smbus_write_byte_data(fd,addr,data);
}
else
{
print_usage(argv[0]);
return -1;
}
return 0;
}


运行结果如下

用户态访问I2C设备

运行结果如上图


如果失败了,说明你这个设备地址已经被别的驱动程序使用了,程序证明如下

用户态访问I2C设备

用户态访问I2C设备

如上图

这是为了防止你破坏别人的驱动程序