Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1222233
  • 博文数量: 105
  • 博客积分: 127
  • 博客等级: 入伍新兵
  • 技术积分: 962
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-29 15:22
文章分类

全部博文(105)

文章存档

2021年(1)

2019年(3)

2018年(1)

2017年(11)

2016年(47)

2015年(32)

2014年(4)

2012年(6)

我的朋友

分类: LINUX

2016-06-04 16:19:56

 
       i2c的设备驱动可以直接利用内核提供的i2c-dev.c文件提供的ioctl函数接口在应用层实现对i2c设备的读写,

但是在应用层使用ioctl函数对应用程序员要求较高,需要自行构建msg结构体,必须了解设备的操作流程,时序之类的。

        另外i2c设备的驱动也可以通过普通的设备驱动实现,像往常的驱动一样实现,然后在应用层就可以像读取普通文件
一样操作,无需再考虑读写时序。其实普通的设备驱动也可以用两种方法实现,
1)构建字符设备驱动,在open,read,write等函数中直接操作i2c总线的相关寄存器来读写i2c设备,但是这种方法因平台不同,
 设备不同都要重新写驱动,

2)在设备驱动中调用i2c-core.c提供的i2c_transfer函数来实现和i2c设备的通信,这样只要对不同的设备写不同的驱动就行了。

        下面就分别对i2c-dev驱动、普通设备驱动方法1和普通设备驱动方法2来介绍一下,共分为博客的三篇文章:
1)i2c驱动之i2c-dev驱动,
2)普通设备驱动1,
3)普通设备驱动方法2(推荐方法)。

        关于i2c设备驱动,自己在理解的过程中感觉比较好的资料的连接:

        linux下I2C驱动架构全面分析 、  、 


        在/linux-2.6.32.2/drivers/i2c目录下

        ----Algos/                  一些i2c总线适配器通信的算法,个人感觉是用I/O口模拟实现i2c通信的算法

        ----Busses/               I2C总线驱动的方法,对应于s3c2440适配器驱动的文件是I2c-s3c2410.c

        ----Chips/                 I2C设备驱动,具体到某个设备,比如at24c08等

        ----I2c-boardinfo.c   

        ----I2c-core.c           I2C核心文件,用于联系设备驱动和总线驱动,作为一个桥梁,有用的函数i2c_add_addapter

                                       i2c_add_driver,和i2c_transfer函数

        ----I2c-dev.c            通用的i2c设备驱动

        ----Kconfig

        ----Makefile

       

开始在内核编译i2c-dev通用驱动

1)在linux-2.6.32.2/内核目录下make menuconfig,选择如下Device Drivers


2)进入Device Drivers目录,选择I2C Support,表示编译I2C驱动模块,会将i2c-core.c编译成模块文件i2c-core.ko


3)进入I2C support


4)选择模块化编译I2C device interface "M",则会将i2c-dev.c编译成i2c-dev.ko


5)选择I2C Hardware Bus support,并进入

选择s3c2410 I2c Driver则会将i2c-s3c2410.c编译成i2c-s3c2410.ko驱动模块


6)选择Miscellaneous I2c Chip Support,并进入

会提示让你选择编译具体的设备驱动,因为这里我们采用内核提供的通用设备驱动i2c-dev,所以这里的驱动就暂时不编译了


以上编译总共得到了3个驱动文件i2c-core.ko,i2c-dev.ko,i2c-s3c2410.ko

将这三个模块insmod到内核中,顺序是i2c-core.ko,i2c-s3c2410.ko,i2c-dev.ko,会自动创建/dev/i2c/0设备节点,然后就可以直接调用/dev/i2c/0文件节点进行访问设备了

之后应用程序员可以利用下面两种ioctl函数

ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);或者

ioctl(file,I2C_SMBUS,&args);

进行与i2c设备通信了。



验证i2c应用程序:


[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /* 
  2. //作者:王磊 
  3. //日期:2013.11.17 
  4. //文件功能:实现ioctl函数调用,并操作i2c设备/dev/i2c/0进行读写数据 
  5. //可以用i2c -r来检验数据是否已写入 
  6. */  
  7. #include  
  8. #include  
  9. #include  
  10. #include  
  11. #include  
  12. #include  
  13. #include  
  14. #include  
  15. #include  
  16. #include  
  17. #include  
  18. #include  
  19.   
  20. int main(int argc, char** argv)  
  21. {  
  22.     struct i2c_rdwr_ioctl_data work_queue;  
  23.   
  24.     unsigned int slave_address,reg_address,dat;  
  25.     unsigned int fd;  
  26.     int ret;  
  27.     char select;  
  28.   
  29.     fd=open("/dev/i2c/0",O_RDWR);  
  30.     if(!fd)  
  31.     {  
  32.         printf("error on opening the device file\n");  
  33.         exit(1);  
  34.     }  
  35.     ioctl(fd,I2C_TIMEOUT,2);//超时时间  
  36.     ioctl(fd,I2C_RETRIES,1);//重复次数  
  37.       
  38.     //nmsgs决定了有多少start信号,一个msgs对应一个start信号,但这个start信号又不能适用于repeat start  
  39.     //在nmsg个信号结束后总线会产生一个stop  
  40.     work_queue.nmsgs = 1;  
  41.     work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs * sizeof(work_queue.msgs));  
  42.     if(!work_queue.msgs)  
  43.     {  
  44.         printf("memory alloc failed");  
  45.         close(fd);  
  46.         exit(1);  
  47.     }  
  48.   
  49.     slave_address = 0x50;//24c08的访问地址是101000b  
  50.     printf("please select:w or r?\n");  
  51.     scanf("%c", &select);  
  52.     if('w' == select)  
  53.     {  
  54.         printf("please input:address,dat?(example:0x00,0x00)\n");  
  55.         scanf("%x,%x", ®_address, &dat);  
  56.         //往i2c里面写数据  
  57.         printf("began to write\n");  
  58.         work_queue.nmsgs  = 1;    
  59.         (work_queue.msgs[0]).len = 2;//buf的长度  
  60.         (work_queue.msgs[0]).flags = 0;//write  
  61.         (work_queue.msgs[0]).addr = slave_address;//设备地址  
  62.         (work_queue.msgs[0]).buf = (unsigned char *)malloc(2);  
  63.         (work_queue.msgs[0]).buf[0] = reg_address;//写的地址  
  64.         (work_queue.msgs[0]).buf[1] = dat;//你要写的数据  
  65.   
  66.         ret = ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);  
  67.         if(ret < 0)  
  68.             printf("error during I2C_RDWR ioctl with error code %d\n", ret);  
  69.     }  
  70.     else if('r' == select)  
  71.     {  
  72.         printf("please input:address?(example:0x00)\n");  
  73.         scanf("%x", ®_address);  
  74.         //从i2c里面读出数据  
  75.         printf("began to read:");  
  76.         work_queue.nmsgs  = 1;  
  77.         //先设定一下地址     
  78.         (work_queue.msgs[0]).flags = 0;//write  
  79.         (work_queue.msgs[0]).addr = slave_address;  
  80.         (work_queue.msgs[0]).len = 1;  
  81.         (work_queue.msgs[0]).buf = (unsigned char *)malloc(1);  
  82.         (work_queue.msgs[0]).buf[0] = reg_address;//因为上面buf已经分配过了  
  83.         ret = ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);  
  84.         if(ret < 0)  
  85.             printf("error during I2C_RDWR ioctl with error code %d\n", ret);  
  86.   
  87.     //因为i2c-dev不支持repeat start,所以只能将读数据操作中的写地址和读数据分为两次消息。     
  88.         //然后从刚才设定的地址处读  
  89.         work_queue.nmsgs  = 1;  
  90.         (work_queue.msgs[0]).flags = I2C_M_RD;  
  91.         (work_queue.msgs[0]).addr = slave_address;  
  92.         (work_queue.msgs[0]).len = 1;  
  93.         (work_queue.msgs[0]).buf[0] = 0;//初始化读缓冲  
  94.         ret = ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);  
  95.         if(ret < 0)  
  96.             printf("error during I2C_RDWR ioctl with error code %d\n", ret);  
  97.         printf("reg_address=0x%2x,dat=0x%2x\n", reg_address, work_queue.msgs[0].buf[0]);  
  98.     }  
  99.     close(fd);  
  100.     free((work_queue.msgs[0]).buf);  
  101.     free(work_queue.msgs);  
  102.     return 0;   
  103.       
  104. }  
  105.                   
转载地址 :http://blog.csdn.net/luckywang1103/article/details/16834519


阅读(3450) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~