在线设计logo免费网站,如何在网站上添加qq,电脑网页制作软件下载,中国制造网怎么样这部分准备分几个部分进行分析总结 因为I2C的通信肯定至少要有2个芯片完成#xff0c;所以它的驱动是由2大部分组成#xff1a;主芯片的i2c的驱动从芯片的i2c的驱动 注#xff1a;万一选的都不支持咋办#xff1f;#xff1f;#xff1f;#xff08;惨了#xff0c;只能…这部分准备分几个部分进行分析总结
因为I2C的通信肯定至少要有2个芯片完成所以它的驱动是由2大部分组成主芯片的i2c的驱动从芯片的i2c的驱动 注万一选的都不支持咋办惨了只能2个芯片的驱动都得实现了不过过程差不多一.主芯片的I2C的驱动具体如何实现在后面在具体讲解首先要查看linux内核是否支持主芯片中i2c驱动器如果支持就配置一下就ok了否则要编写主控芯片的i2c驱动器编写方法
第一.要有i2c总线驱动首先要查查内核i2c文件是否支持这种总线驱动一般都有支持如果没有只好自己倒霉自己写了第二.i2c设备驱动主控芯片的地址等等信息这个过程都是差不多的以后在分析。一般的主控芯片的i2c控制器linux内核基本上支持的很好如2410的i2c驱动器的支持二.从芯片的I2C的驱动下面主要分析从芯片的I2C驱动也有2种方式第一个是利用内核提供的i2c-dev.c来构建另一个是自己写主要分析第一种方式利用系统给我们提供的i2c-dev.c来实现一个i2c适配器的设备文件。然后通过在应用层操作i2c适配器来控制i2c设备。i2c-dev.c并没有针对特定的设备而设计只是提供了通用的read()、write()和ioctl()等接口应用层可以借用这些接口访问挂接在适配器上的i2c设备的存储空间或寄存器并控制I2C设备的工作方式。但是read和write方法适用性有限。所以用ioctl方法来操作一般都不会使用i2c-dev.c的read()、write()方法。最常用的是ioctl()方法。ioctl()方法可以实现上面所有的情况两种数据格式、以及I2C算法和smbus算法。 针对i2c的算法需要熟悉struct i2c_rdwr_ioctl_data 、struct i2c_msg。使用的命令是I2C_RDWR。 struct i2c_rdwr_ioctl_data { struct i2c_msg __user *msgs; /* pointers to i2c_msgs */ __u32 nmsgs; /* number of i2c_msgs */ }; struct i2c_msg { _ _u16 addr; /* slave address */ _ _u16 flags; /* 标志读、写 */ _ _u16 len; /* msg length */ _ _u8 *buf; /* pointer to msg data */ }; 针对smbus算法需要熟悉struct i2c_smbus_ioctl_data。使用的命令是I2C_SMBUS。对于smbus算法不需要考虑“多开始信号时序”问题。 struct i2c_smbus_ioctl_data { __u8 read_write; //读、写 __u8 command; //命令 __u32 size; //数据长度标识 union i2c_smbus_data __user *data; //数据 }; 首先在内核中已经包含了对s3c2410 中的i2c控制器总线驱动驱动的支持。提供了i2c算法非smbus类型的所以后面的ioctl的命令是I2C_RDWR static const struct i2c_algorithm s3c24xx_i2c_algorithm { .master_xfer s3c24xx_i2c_xfer, .functionality s3c24xx_i2c_func, }; 另外一方面需要确定为了实现对AT24C02 e2prom的操作需要确定从机芯片的地址及读写访问时序。 在网上找了个例子 具体分析如下 #include stdio.h#include linux/types.h#include stdlib.h#include fcntl.h#include unistd.h#include sys/types.h#include sys/ioctl.h#include errno.h#define I2C_RETRIES 0x0701#define I2C_TIMEOUT 0x0702#define I2C_RDWR 0x0707 /*********定义struct i2c_rdwr_ioctl_data和struct i2c_msg要和内核一致。两个重要的结构体*******/struct i2c_msg{unsigned short addr;unsigned short flags;unsigned short len;unsigned char *buf;};struct i2c_rdwr_ioctl_data{struct i2c_msg *msgs;int nmsgs; /* nmsgs这个数量决定了有多少开始信号对于“单开始时序”取1*/};int main(){int fd,ret;struct i2c_rdwr_ioctl_data e2prom_data;fdopen(/dev/i2c-0,O_RDWR); /*为什么是i2c-0呢那就要到内核里看啦等会再说open底层调用了i2c_get_adapter(int id)函数这个函数很重要他可以识别占用了哪个i2c总线使用地0个i2c控制器/dev/i2c-0是在注册i2c-dev.c后产生的代表一个可操作的适配器。如果不使用i2c-dev.c这里说啦上面的为什么 的方式就没有也不需要这个节i2c_driver结构体中有attach_adapter方法里面用device_create(i2c_dev_class, adap-dev,MKDEV(I2C_MAJOR, adap-nr), NULL,i2c-%d,adap-nr);I2C_MAJOR89即i2c-dev.c针对每个i2c适配器生成一个主设备号位89的设备文件次设备要自己定义*/if(fd0){perror(open error);}e2prom_data.nmsgs2; /**因为操作时序中最多是用到2个开始信号字节读操作中所以此将*e2prom_data.nmsgs配置为2*/e2prom_data.msgs(struct i2c_msg*)malloc(e2prom_data.nmsgs*sizeof(struct i2c_msg));if(!e2prom_data.msgs){perror(malloc error);exit(1);}ioctl(fd,I2C_TIMEOUT,1);/*超时时间*/ioctl(fd,I2C_RETRIES,2);/*重复次数*//***write data to e2prom**/
/**/e2prom_data.nmsgs1;(e2prom_data.msgs[0]).len2; //1个 e2prom 写入目标的地址和1个数据 (e2prom_data.msgs[0]).addr0x50;//e2prom 设备地址(e2prom_data.msgs[0]).flags0; //write(e2prom_data.msgs[0]).buf(unsigned char*)malloc(2);(e2prom_data.msgs[0]).buf[0]0x10;// e2prom 写入目标的地址(e2prom_data.msgs[0]).buf[1]0x58;//the data to writeretioctl(fd,I2C_RDWR,(unsigned long)e2prom_data);if(ret0){perror(ioctl error1);}sleep(1);/******read data from e2prom*******/e2prom_data.nmsgs2;(e2prom_data.msgs[0]).len1; //e2prom 目标数据的地址(e2prom_data.msgs[0]).addr0x50; // e2prom 设备地址(e2prom_data.msgs[0]).flags0;//write(e2prom_data.msgs[0]).buf[0]0x10;//e2prom数据地址(e2prom_data.msgs[1]).len1;//读出的数据(e2prom_data.msgs[1]).addr0x50;// e2prom 设备地址 (e2prom_data.msgs[1]).flagsI2C_M_RD;//read(e2prom_data.msgs[1]).buf(unsigned char*)malloc(1);//存放返回值的地址。(e2prom_data.msgs[1]).buf[0]0;//初始化读缓冲retioctl(fd,I2C_RDWR,(unsigned long)e2prom_data);if(ret0){perror(ioctl error2);}printf(buff[0]%x/n,(e2prom_data.msgs[1]).buf[0]);close(fd);i2c_put_adapter(client-adapter);释放i2c总线return 0;}以上讲述了一种比较常用的利用i2c-dev.c操作i2c设备的方法这种方法可以说是在应用层完成了对具体i2c设备的驱动工作。 接下来准备具体分析如何写第一部分