Linux驱动子系统之I2C用户空间调用

        在学习了linux驱动IIC,对linux有了更深一层的了解。其中在内核drivers/i2c目录下有I2c-dev.c这么一个文件,他是一个通用的从设备驱动,一般的IIC只要使用这个驱动就能完成数据的交互,比如EEPROM、实时RTC等。

       首先来介绍一下重要的结构体

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;	         /* 从器件地址			*/
	__u16 flags;     
#define I2C_M_TEN		0x0010	/* this is a ten bit chip address */
#define I2C_M_RD		0x0001	/* read data, from slave to master */
#define I2C_M_NOSTART		0x4000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR	0x2000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK	0x1000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK		0x0800	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN		0x0400	/* length will be first received byte */
	__u16 len;		/* msg length				*/
	__u8 *buf;		/* pointer to msg data			*/
};

 以上两个结构体在用户应用程序中进行赋值,之后调用ioctl函数直接将数据发送出去或接收。     


来看一下写EEPROM的应用程序

#include <stdio.h>  
    #include <linux/types.h>  
    #include <fcntl.h>  
    #include <unistd.h>  
    #include <stdlib.h>  
    #include <sys/types.h>  
    #include <sys/ioctl.h>  
    #include <errno.h>  
    #include <assert.h>  
    #include <string.h>  
    #include <linux/i2c.h>  
    #include <linux/i2c-dev.h>  
    #include <time.h>
       
    int main()  
    {  
             int fd, ret;  
             unsigned char device_addr = 0x53;     /*从器件的地址,这里使用EEPROM----AT24C256其中A0和A1都接高电平*/
             unsigned char data=0x31;              /*写入EEPROM的数据*/
	     unsigned short rdwr_addr;             /*写入地址,在这里使用地址递增的方式写满整个EEPROM*/
             struct i2c_rdwr_ioctl_data e2prom_data;  /*传入驱动的结构体*/
       
             fd= open("/dev/i2c/0", O_RDWR);  /*打开IIC设备*/
             if(fd < 0) {  
                       printf("openerror");  
                       exit(1);  
             }  
       
             e2prom_data.msgs= (struct i2c_msg *)malloc(e2prom_data.nmsgs * sizeof(struct i2c_msg));    /*分配结构体空间并检查*/  
             if(e2prom_data.msgs == NULL) {  
                       printf("mallocerror");  
                       exit(1);  
             }  
       
             ioctl(fd,I2C_TIMEOUT, 1);      /*设置超时  1表示10ms*/
             ioctl(fd,I2C_RETRIES, 1);      /*设置重复次数*/
       
	     for(rdwr_addr=0;rdwr_addr<32768;rdwr_addr++)       /*地址自增写入*/
	     {		
		     e2prom_data.nmsgs= 1;                      /*传输数据包的数目,在这里e2prom_data.msgs[0]只有一个因此填写1*/
		     e2prom_data.msgs[0].len= 3;                /*数据缓冲的长度3,在这里e2prom_data.msgs[0].buf是个3大小的数组因此填写3*/
		     e2prom_data.msgs[0].addr= device_addr;     /*从器件的地址*/
		     e2prom_data.msgs[0].flags= 0;              /*0----write\1-----read*/  
	       
		      
		     e2prom_data.msgs[0].buf= (unsigned char *)malloc(3);      /*分配数组大小*/
		     e2prom_data.msgs[0].buf[0]= (unsigned char)(rdwr_addr>>8);    /* write address ,先写高位*/  
		     e2prom_data.msgs[0].buf[1]= (unsigned char)(rdwr_addr);       /* write address ,再写低位*/ 
		     e2prom_data.msgs[0].buf[2]= data;                             /* write data */  
	       
		     ret= ioctl(fd, I2C_RDWR, (unsigned long)&e2prom_data);        /*执行ioctl,将数据写入并检查*/
		     if(ret < 0) {  
		               printf("writedata error");  
		               exit(1);  
		     }  
		     printf("writedata: %d to address: %#x\n", data, rdwr_addr);    /*打印写入数据*/
		     usleep(10000);                                                 
	     }
       
	     sleep(1);
          
             free(e2prom_data.msgs);  
             close(fd);  
       
             return 0;  
    }  

下面是读应用程序

    #include <stdio.h>  
    #include <linux/types.h>  
    #include <fcntl.h>  
    #include <unistd.h>  
    #include <stdlib.h>  
    #include <sys/types.h>  
    #include <sys/ioctl.h>  
    #include <errno.h>  
    #include <assert.h>  
    #include <string.h>  
    #include <linux/i2c.h>  
    #include <linux/i2c-dev.h>  
    #include <time.h>
       
    int main()  
    {  
             int fd, ret;  
             unsigned short rdwr_addr;
             unsigned char device_addr = 0x53; 
             unsigned char data;
             struct i2c_rdwr_ioctl_data e2prom_data;  
       
             fd= open("/dev/i2c/0", O_RDWR);  
             if(fd < 0) {  
                       printf("openerror");  
                       exit(1);  
             }  
       
             e2prom_data.msgs= (struct i2c_msg *)malloc(e2prom_data.nmsgs * sizeof(struct i2c_msg));  
             if(e2prom_data.msgs == NULL) {  
                       printf("mallocerror");  
                       exit(1);  
             }  
       
             ioctl(fd,I2C_TIMEOUT, 1); 
             ioctl(fd,I2C_RETRIES, 2); 
             for(rdwr_addr=0;rdwr_addr<32768;rdwr_addr++)
	     {
		     e2prom_data.msgs[0].buf= (unsigned char *)malloc(5);   
		     e2prom_data.nmsgs= 2;  
		     e2prom_data.msgs[0].len= 2;  
		     e2prom_data.msgs[0].addr= device_addr;  
		     e2prom_data.msgs[0].buf[0]= (unsigned char)(rdwr_addr>>8);    /* write address */  
		     e2prom_data.msgs[0].buf[1]= (unsigned char)(rdwr_addr);    /* write address */ 
	       
		     e2prom_data.msgs[1].len= 1;  
		     e2prom_data.msgs[1].addr= device_addr;  
		     e2prom_data.msgs[1].flags= 1;     /* read */  
		     e2prom_data.msgs[1].buf= &data;  
	       
		     ret= ioctl(fd, I2C_RDWR, (unsigned long)&e2prom_data);  
		     if(ret < 0) {  
		               perror("readerror");  
		               exit(1);  
		     }  
		     printf("read  data: %d from address: %#x\n", data,rdwr_addr);   
		     data = 0;  
	             usleep(10000);
	     }         
             free(e2prom_data.msgs);  
             close(fd);  
       
             return 0;  
    }  




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值