在Linux内核源代码中的drivers/i2c/busses目录下包含着一些适配器的驱动。如S3C2410的驱动i2c-s3c2410.c。当适配器加载到内核后,接下来的工作就要针对具体的设备编写设备驱动了。
编写I2C设备驱动也有两种方法。一种是利用系统给我们提供的i2c-dev.c来实现一个i2c适配器的设备文件。然后通过在应用层操作i2c适配器来控制i2c设备。另一种是为i2c设备,独立编写一个设备驱动。注意:在后一种情况下,是不需要使用i2c-dev.c的。
i2c-s3c2410.c 为总线驱动,好像是必需的,编译的时候不添加i2c-s3c2410.c的配置选项测试程序不能读写IIc设备dev/i2c/0
项目中的是独立的设备驱动程序。
下面是利用i2c-dev.c创建的设备文件/dev/i2c-0在用户模式下控制适配器访问at24c02的例子:
#define I2C_RETRIES 0x0701
17 #define I2C_TIMEOUT 0x0702
18 #define I2C_RDWR 0x0707
19 /*********定义struct i2c_rdwr_ioctl_data和struct i2c_msg,要和内核一致*******/
20 struct i2c_msg
21 {
22 unsigned short addr;
23 unsigned short flags;
24 #define I2C_M_TEN 0x0010
25 #define I2C_M_RD 0x0001
26 unsigned short len;
27 unsigned char *buf;
28 };
29
30 struct i2c_rdwr_ioctl_data
31 {
32 struct i2c_msg *msgs;
33 int nmsgs;
34 /* nmsgs这个数量决定了有多少开始信号,对于“单开始时序”,取1*/
35 };
36 int main()
{
38 int fd,ret;
39 struct i2c_rdwr_ioctl_data e2prom_data;
40 fd=open("/dev/i2c-0",O_RDWR);
41 /*
42 /dev/i2c-0是在注册i2c-dev.c后产生的,代表一个可操作的适配器。如果不使用i2c-d ev.c*的方式,就没有,也不需要这个节点。
43 */
44 if(fd<0)
45 {
46 perror("open error");
47 printf("open device error\n");
48 return 0;
49 }
50 e2prom_data.nmsgs=2;
51 /*
52 *
53 * *因为操作时序中,最多是用到2个开始信号(字节读操作中),所以此将
54 * *e2prom_data.nmsgs配置为2
55 *
56 **/
57 e2prom_data.msgs=(struct i2c_msg*)malloc(e2prom_data.nmsgs*sizeof(st ruct i2c_msg));
58 if(!e2prom_data.msgs)
59 {
60 perror("malloc error");
61 exit(1);
62 }
63 ioctl(fd,I2C_TIMEOUT,1);/*超时时间*/
64 ioctl(fd,I2C_RETRIES,2);/*重复次数*/
65 /***write data to e2prom**/
66 e2prom_data.nmsgs=1;
67 (e2prom_data.msgs[0]).len=5; //1个 e2prom 写入目标的地址和4个数据
68 (e2prom_data.msgs[0]).addr=0x50;//e2prom 设备地址
69 (e2prom_data.msgs[0]).flags=0; //write
70 (e2prom_data.msgs[0]).buf=(unsigned char*)malloc(5);
71 (e2prom_data.msgs[0]).buf[0]=0x10;// e2prom 写入目标的地址
72 (e2prom_data.msgs[0]).buf[1]=0x11;//the data to write
73 (e2prom_data.msgs[0]).buf[2]=0x22;
74 (e2prom_data.msgs[0]).buf[3]=0x33;
75 (e2prom_data.msgs[0]).buf[4]=0x44;
ret=ioctl(fd,I2C_RDWR,(unsigned long)&e2prom_data);
78 if(ret<0)
79 {
80 perror("ioctl error1");
81 printf("ioctl error1\n");
82 }
83 sleep(1);
84
85 /******read data from e2prom*******/
86 e2prom_data.nmsgs=2;
87 (e2prom_data.msgs[0]).len=1; //e2prom 目标数据的地址
88 (e2prom_data.msgs[0]).addr=0x50; // e2prom 设备地址
89 (e2prom_data.msgs[0]).flags=0;//write
90 (e2prom_data.msgs[0]).buf[0]=0x10;//e2prom数据地址
91 (e2prom_data.msgs[1]).len=4;//读出的数据
92 (e2prom_data.msgs[1]).addr=0x50;// e2prom 设备地址
93 (e2prom_data.msgs[1]).flags=I2C_M_RD;//read
94 (e2prom_data.msgs[1]).buf=(unsigned char*)malloc(4);//存放返回值的地
址。
95 (e2prom_data.msgs[1]).buf[0]=0;//初始化读缓冲
96 (e2prom_data.msgs[1]).buf[1]=0;//初始化读缓冲
97 (e2prom_data.msgs[1]).buf[2]=0;//初始化读缓冲
98 (e2prom_data.msgs[1]).buf[3]=0;//初始化读缓冲
ret=ioctl(fd,I2C_RDWR,(unsigned long)&e2prom_data);
100 if(ret<0)
101 {
102 perror("ioctl error2");
103 printf("ioctl error2\n");
104 }
105
106 printf("buff[0]=%x\n",(e2prom_data.msgs[1]).buf[0]);
107 printf("buff[1]=%x\n",(e2prom_data.msgs[1]).buf[1]);
108 printf("buff[2]=%x\n",(e2prom_data.msgs[1]).buf[2]);
109 printf("buff[3]=%x\n",(e2prom_data.msgs[1]).buf[3]);
110 /***打印读出的值,没错的话,就应该是前面写的0x11 0x22 0x33 0x44了***/
111 close(fd);
112 return 0;
113 }