imx257下实现I2C驱动的四种方法

发布时间:2024-08-13  

今天我们的任务是简单的入门linux内核下i2c设备驱动分离的四种写法.



一.一个简单的i2c驱动


和以前的驱动程序不同,i2c驱动分为drv驱动和dev设备驱动两个文件,不懂的可以参考我以前写的<20150313 驱动模块分离概念>以及总线设备驱动模型这些博文


地址:http://www.cnblogs.com/lihaiyan/p/4336165.html



1.首先是drv驱动的编写at24cxx_drv_1.c:


在drv驱动中,其实很简单,就是实现一个i2c_driver结构体,然后在init函数中注册i2c_driver结构体,最后自然是在exit函数中卸载i2c_driver结构体.


①定义i2c_driver结构体以及实现相应的函数


 1 //probe函数

 2 static int __devinit at24cxx_probe(struct i2c_client *client, const struct i2c_device_id *id){

 3     printk('%s, %s, %dnn',__FILE__,__FUNCTION__,__LINE__);

 4     return 0;

 5 }

 6 //remove函数

 7 static int __devexit at24cxx_remove(struct i2c_client *client)

 8 {

 9     printk('%s, %s, %dnn',__FILE__,__FUNCTION__,__LINE__);

10     return 0;

11 }

12 static const struct i2c_device_id at24cxx_id_table[] = {

13     {'at24c08', 0},      //记录了设备的名字,用于去顶后面的驱动是否匹配

14     {}

15 };    

16 static struct i2c_driver at24cxx_driver = {

17     .driver = {

18         .name = 'LoverXueEr',

19         .owner = THIS_MODULE,

20     },

21     .probe = at24cxx_probe,            //探测函数

22     .remove = at24cxx_remove,        //卸载函数

23     .id_table = at24cxx_id_table,

24 };


可以发现,在i2c_driver结构体中总共实现了探测函数probe,用于探测匹配的设备,id_table定义了设备的名字用于匹配合适的驱动.


②在init和exit对i2c_driver分别注册和卸载


 1 static int at24cxx_drv_init(void)

 2 {

 3     /* 2.注册i2c_driver*/

 4     i2c_add_driver(&at24cxx_driver);

 5     return 0;

 6 }

 7 static void at24cxx_drv_exit(void)

 8 {

 9     i2c_del_driver(&at24cxx_driver);

10 }


2.设备驱动程序编写at24cxx_dev_1.c


在设备驱动中主要是定义了一些设备的具体的信息,比如设备地址啊等等的信息.


在设备驱动中,主要就是I2C控制器(也称适配器)的使用了.


在init函数中首先创建一个i2c_adapter控制器结构体,


接着通过格泰i2c_get_adapter获取内核存在的i2c控制器号,这个在/sys/class/i2c-adapter下可以查看,


接着使用i2c_new_device直接创建一个设备,不管设备存在与否,该函数都会强制认为该设备存在.


而如果使用i2c_new_probed_device的话:它和前面不同的是,它一定要对于能够'已经识别出来的设备'(probed_device),才会去创建,否则无法创建.(见下面方法二)


理论描述总是太抽象了,我们来看看程序就懂了.


 1 //单板结构体,用于存放设备的硬件信息

 2 static struct i2c_board_info at24cxx_info = {

 3         I2C_BOARD_INFO('at24c08',0x50),        //注意这个名字 1010000

 4 };

 5 static struct i2c_client *at24cxx_client;

 6 

 7 /* 1.分配/设置i2c_driver */

 8 static int at24cxx_dev_init(void)

 9 {

10     struct i2c_adapter *i2c_adapt;

11     printk('%s, %s, %dnn',__FILE__,__FUNCTION__,__LINE__);

12     //创建i2c适配器

13     //直接创建设备

14     i2c_adapt = i2c_get_adapter(1);        //获得第0个适配器

15     if (!i2c_adapt) {

16         printk('can't get i2c adapter %dn',1);

17         return -EIO;

18     }

19     at24cxx_client = i2c_new_device(i2c_adapt,&at24cxx_info);    //在总线下面创建一个i2c_adapt,强制认为设备存在

20     //i2c_new_probed_device:    对于能够'已经识别出来的设备'(probed_device),才会去创建

21     i2c_put_adapter(i2c_adapt);            //释放i2c_adapt

22     return 0;

23 }

24 

25 static void at24cxx_dev_exit(void)

26 {

27     if(at24cxx_client)

28         i2c_unregister_device(at24cxx_client);

29 }


3.编译测试


结果如图所示:

afe9cc762fc38f60f41c3efd04746c84_8DcWtWMqzORnEAAAAASUVORK5CYII=.png

附上drv驱动程序: at24cxx_drv_1.c


 1 #include

 2 #include

 3 #include

 4 #include

 5 #include

 6 #include

 7 

 8 

 9 //probe函数

10 static int __devinit at24cxx_probe(struct i2c_client *client, const struct i2c_device_id *id){

11     printk('%s, %s, %dnn',__FILE__,__FUNCTION__,__LINE__);

12     return 0;

13 }

14 

15 //remove函数

16 static int __devexit at24cxx_remove(struct i2c_client *client)

17 {

18     printk('%s, %s, %dnn',__FILE__,__FUNCTION__,__LINE__);

19     return 0;

20 }

21 

22 

23 static const struct i2c_device_id at24cxx_id_table[] = {

24     {'at24c08', 0},

25     {}

26 };

27     

28 static struct i2c_driver at24cxx_driver = {

29     .driver = {

30         .name = 'LoverXueEr',

31         .owner = THIS_MODULE,

32     },

33     .probe = at24cxx_probe,

34     .remove = at24cxx_remove,

35     .id_table = at24cxx_id_table,

36 };

37 

38 

39 /* 1.分配/设置i2c_driver */

40 

41 static int at24cxx_drv_init(void)

42 {

43     /* 2.注册i2c_driver*/

44     i2c_add_driver(&at24cxx_driver);

45     return 0;

46 }

47 

48 static void at24cxx_drv_exit(void)

49 {

50     i2c_del_driver(&at24cxx_driver);

51 }

52 

53 module_init(at24cxx_drv_init);

54 module_exit(at24cxx_drv_exit);

55 MODULE_LICENSE('GPL');

56 

57 /*

58 1.左边注册一个设备 i2c_client

59 2.右边注册一个驱动 i2c_driver

60 3.比较他们的名字,如果相同,则调用probe函数

61 4.在probe函数里,register_chrdev

62 */


附上dev驱动程序: at24cxx_dev_1.c


 1 #include

 2 #include

 3 #include

 4 #include

 5 #include

 6 #include

 7 #include

 8 #include

 9 

10 //单板结构体,用于存放设备的硬件信息

11 static struct i2c_board_info at24cxx_info = {

12         I2C_BOARD_INFO('at24c08',0x50),        //注意这个名字 1010000

13 };

14 static struct i2c_client *at24cxx_client;

15 

16 /* 1.分配/设置i2c_driver */

17 static int at24cxx_dev_init(void)

18 {

19     struct i2c_adapter *i2c_adapt;

20     printk('%s, %s, %dnn',__FILE__,__FUNCTION__,__LINE__);

21     //创建i2c适配器

22     //直接创建设备

23     i2c_adapt = i2c_get_adapter(1);        //获得第0个适配器

24     if (!i2c_adapt) {

25         printk('can't get i2c adapter %dn',1);

26         return -EIO;

27     }

28     at24cxx_client = i2c_new_device(i2c_adapt,&at24cxx_info);    //在总线下面创建一个i2c_adapt,强制认为设备存在

29     //i2c_new_probed_device:    对于能够'已经识别出来的设备'(probed_device),才会去创建

30     i2c_put_adapter(i2c_adapt);            //释放i2c_adapt

31     return 0;

32 }

33 

34 static void at24cxx_dev_exit(void)

35 {

36     if(at24cxx_client)

37         i2c_unregister_device(at24cxx_client);

38 }

39 

40 module_init(at24cxx_dev_init);

41 module_exit(at24cxx_dev_exit);

42 MODULE_LICENSE('GPL');

43 

44 /*

45 1.左边注册一个设备 i2c_client

46 2.右边注册一个驱动 i2c_driver

47 3.比较他们的名字,如果相同,则调用probe函数

48 4.在probe函数里,register_chrdev

49 */


二.创建已经能被识别的设备



前面我们已经涉及到了,和i2c_new_device不同,使用i2c_new_probed_device的话,它会线查看设备是否存在,如果存在的话,才会创建设备.现在我们第二种方法就是使用它来实现.


再前面的程序基础上修改at24cxx_dev_1.c设备驱动程序.drv驱动不用修改.


1.定义一些用于探测的id数组


前面我们说了,它会探测id的设备是否存在,所以,意味着我们这里可以有多个id,并且id号也可以是不存在的,为了保存这些id,自然就需要一个数组来装咯.


程序如下所示:


 


1 static struct i2c_client *at24cxx_client;

2 //一些用于试探是否存在的id

3 static const unsigned short addr_list[] = {0x60,0x50,0x70,NULL};  

 


 


 


2.在init函数中


和前面第一种方法不同的是,


①我们此处是在init函数中动态的创建i2c_board_info结构体.


②接着就是初始化i2c_board_info结构体,分配设备的名字用于匹配合适的总线.


③创建适配器,获取适配器,和前面一样


④使用i2c_new_probed_device来创建设备,再i2c_new_probed_device中,首先会遍历id数组,线测试id设备是否存在,接着就是调用i2c_new_device来创建设备.


⑤动态是否i2c_adapt控制器.


程序如下:


 1 /* 1.分配/设置i2c_driver */

 2 static int at24cxx_dev_init(void)

 3 {

 4     struct i2c_adapter *i2c_adapt;

 5     struct i2c_board_info at24cxx_info;

 6     

 7     printk('%s, %s, %dnn',__FILE__,__FUNCTION__,__LINE__);

 8     

 9     //初始化i2c_board_info 结构体

10     memset(&at24cxx_info, 0, sizeof(struct i2c_board_info));

11     strlcpy(at24cxx_info.type,'at24c08',20);

12     

13     //创建i2c适配器  //直接创建设备

14     i2c_adapt = i2c_get_adapter(1);        //获得第1个i2c_bus总线

15     if (!i2c_adapt) {

16         printk('can't get i2c adapter %dn',1);

17         return -EIO;

18     }

19     //在总线下面创建一个i2c_adapt,强制认为设备存在

20     //at24cxx_client = i2c_new_device(i2c_adapt,&at24cxx_info);    

21     //对于addr_list能够'已经识别出来的设备'(probed_device),才会去创建,i2c_new_device之前,先测试addr_List中的设备是否存在

22     at24cxx_client = i2c_new_probed_device(i2c_adapt, &at24cxx_info, addr_list);    

23     if(!at24cxx_client)

24         return -ENODEV;

25     if(i2c_adapt)

26         i2c_put_adapter(i2c_adapt);            //释放i2c_adapt

27     return 0;

28 }

29 

30 static void at24cxx_dev_exit(void)

31 {

32     if(at24cxx_client)

33         i2c_unregister_device(at24cxx_client);

34 }


3.编译测试


附上drv驱动程序: at24cxx_drv_2.c


 1 #include

 2 #include

 3 #include

 4 #include

 5 #include

 6 #include

 7 

 8 

 9 //probe函数

10 static int __devinit at24cxx_probe(struct i2c_client *client, const struct i2c_device_id *id){

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    微单外观有暴风黑、冰河银两种风格,采用索尼Exmor IMX269传感器,2016万有效像素,ISO 100-25600,拍照分辨率最高5184×3888,可插值至8160×6120(5000万像......
    微单外观有暴风黑、冰河银两种风格,采用索尼Exmor IMX269传感器,2016万有效像素,ISO 100-25600,拍照分辨率最高5184×3888,可插值至8160×6120(5000万像......
    微单外观有暴风黑、冰河银两种风格,采用索尼Exmor IMX269传感器,2016万有效像素,ISO 100-25600,拍照分辨率最高5184×3888,可插值至8160×6120(5000万像......
    年轻人的第一台 国产智能微单小蚁M1实拍样张;上月29日,售价2199元,号称是“年轻人的第一台智能微单相机”。 小蚁微单采用索尼Exmor IMX269传感器,2016万有效像素,ISO 100......
    是检测纸张、箔片、木材、金属,还是高反光的太阳能硅片,帮助用户轻松实现多种双张材料的可靠检测。新加入的IO-Link通讯可实时获取传感器参数、诊断数据和过程数据,实现数据可视化,预测性维护等智能功能,针对......
    过程: 01 实验选取5种材质的球形颗粒作为实验颗粒,进行金属颗粒复数域信号检测实验; 02 三线圈传感器置于金属罩内以屏蔽外界电磁干扰。信号发生器输出的正弦电压作为激励电压。功率放大器的参数设定为10倍......
    车用图像传感器参数小议——信噪比;智能驾驶如今渐渐成为汽车的一个常见功能,它增强了汽车和驾驶员的感知能力,降低了驾驶员的工作强度,同时可以有效提高行车的安全性。这其中,基于CMOS 图像传感器......
    R&S验证恩智浦的下一代汽车雷达传感器设计; 罗德与施瓦茨(以下简称R&S)的R&S RTS雷达测试解决方案验证了恩智浦半导体的下一代雷达传感器参考设计的性能。双方......
    R&S验证恩智浦的下一代汽车雷达传感器设计; 罗德与施瓦茨(以下简称R&S)的R&S RTS雷达测试解决方案验证了恩智浦半导体的下一代雷达传感器参考设计的性能。双方......
    差压变送器。   五、V锥流量计显示正常,无输出。   1、D/A输出部分损坏   解决方案:修复D/A输出。   V锥流量计选型注意事项   V锥流量计选型工作时应考虑以下八个注意点:   1、V锥流量传感器设计选型时需要知道用户的详尽工艺及准确的参数......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>