在本博客的《使用Beaglebone Black的I2C(一)》中,介绍了BBB上无需编程对i2c总线进行读写操作的方法,本文将介绍如何在c语言程序中使用i2c-dev驱动来操作i2c设备。

以下将还以前文中使用过的L3G4200D三轴陀螺仪为例。

BBB自带了i2c-dev驱动,它使用ioctl方法对i2c设备进行配置,然后利用read()、write()函数就可以操作i2c设备了。

要操作某个i2c设备,首先要确定它的地址。按照我在前文中的说法,通常i2cdetect显示的器件地址是由“7位”二进制数换算成的,而器件的读写地址则需要将这7位左移,然后在末尾添加一个1或0。但是对于i2c-dev驱动来说,我们不必费此周折,只要告诉他i2cdetect显示的那个地址就可以了,驱动会自动根据你的读操作或写操作来相应地在末尾添加1或者0。

先把完整程序摆出来:

  1. #include <stdio.h>
  2. #include <stdlib.h>   //exit()
  3. #include <fcntl.h>    //define O_RDWR
  4. #include <linux/i2c-dev.h>
  5. #include <sys/ioctl.h>
  6. void main()
  7. {
  8. int file,i;
  9. int addr = 0b01101001; //i2c device address of gyro
  10. char *filename = "/dev/i2c-1";
  11. char wbuf[] = {0x20, 0x0f}; //first byte is address to write. others are bytes to be written
  12. char read_start_buf[1];
  13. char rbuf[1000] = {0};
  14. if((file = open(filename, O_RDWR)) < 0)
  15. {
  16. perror("Failed to open i2c device.\n");
  17. exit(1);
  18. }
  19. if(ioctl(file, I2C_SLAVE, addr) < 0)
  20. {
  21. printf("Failed to access bus.\n");
  22. exit(1);
  23. }
  24. write(file, wbuf, 2); //write 0x0f to register 0x20 to enable gyro.
  25. for(i=0;i<5;i++)
  26. {
  27. read_start_buf[0] = 0x29;
  28. write(file, read_start_buf, 1); //reposition file pointer to register 0x29
  29. read(file, rbuf, 1); //read register 0x29 and save to rbuf
  30. printf("%x", rbuf[0]);
  31. read_start_buf[0] = 0x28;
  32. write(file, read_start_buf, 1); //reposition file pointer to register 0x28
  33. read(file, rbuf, 1); //read register 0x28 and save to rbuf
  34. printf("%x\n", rbuf[0]);
  35. sleep(1);
  36. }
  37. close(file);
  38. }

上面的程序首先打开/dev/i2c-1这个设备,然后用ioctl配置成slave模式。然后通过将第0x20这个寄存器写成0x0f来使能陀螺仪。然后在for循环中依次读取0x29和0x28两个寄存器的值并输出,这两个寄存器一起组成了X轴的角速度值。

程序输出如下:

  1. root@beaglebone:~/ioctl_test# ./i2c
  2. 03c
  3. 04a
  4. 035
  5. 05f
  6. 03c
  7. root@beaglebone:~/ioctl_test# ./i2c
  8. 1f7f
  9. f2c3
  10. f567
  11. 3979
  12. 3aca

运行了两次,第一次陀螺仪静止(但输出仍有一点小波动),第二次陀螺仪在晃动。可以看到输出值的不同。

需要注意的一点,读i2c设备时如何定位读取的位置?

使用lseek()的话会返回-1,这个是不可行的。答案就是程序中,用write()写一个字节。write函数参数中的buf数组里的第一项代表了write的位置,从第二项开始是写入的内容,因此只写一个字节就是把指针移动过去了但是不写入任何内容。

用这个方法就无需其他驱动也可以操作任意i2c外设了。

另外有个疑问。按理说执行 read(file, rbuf, 10); 的话,可以读出当前指针位置开始的10个字节的内容。我在其他设备上也验证了这点。但是在L3G4200D陀螺仪上,一次读取10个的话,读出的就全是一样的数值,都是第一个数值。所以只能一位一位地读取。难道是陀螺仪芯片有意设置成这样?(这个现象跟我在《使用Beaglebone Black的I2C(一)》中的问题相符,即执行 i2cdump -y 1 0x69 c 会导致输出全部是一样的,都是第一个字节的内容。把c参数去掉才可以。)

参考资料:

elinux.org/Interfacing_with_I2C_Devices

www.kernel.org/doc/Documentation/i2c/dev-interface

【转】使用Beaglebone Black的I2C (二)——使用C语言和i2c-dev驱动的更多相关文章

  1. I2C(二) linux2.6

    目录 I2C(二) linux2.6 总线驱动 关键结构 入口 i2c_add_adapter 硬件操作 设备驱动 入口 注册 attach_adapter eeprom_detect i2c_att ...

  2. 为 MaixPy 加入软 I2C 接口(移植 MicroPython 的 I2C)

    起因 本文的重心为讲解如何为一款芯片移植和实现 micropython 的通用组件,但会顺带解释不同芯片的工作方式和特性. 国际惯例,先有起因,再谈问题的解决,所以记得上次总结的 关于 K210 Ma ...

  3. Python3+Selenium2完整的自动化测试实现之旅(二):IE和Chrome浏览器驱动配置

    上一篇写了自动化测试需要的最基础环境配置,地址:https://www.cnblogs.com/tdp0108/p/10412073.html 当前市面上很多公司开发的应用软件都是BS架构,即基于浏览 ...

  4. 基于I2C总线的0.96寸OLED显示屏驱动

    资料未整理,先占位置,以后补充

  5. (二)ubuntu下安装Amd RX470驱动

    0X:ADM官方下载驱动 https://www.amd.com/en/support 查看本机驱动命令 lspci | grep -i vga 选择自己的驱动 下载对应的版本 现在最新的是:amdg ...

  6. Linux I2C设备驱动编写(二)

    在(一)中简述了Linux I2C子系统的三个主要成员i2c_adapter.i2c_driver.i2c_client.三者的关系也在上一节进行了描述.应该已经算是对Linux I2C子系统有了初步 ...

  7. 【转】Linux I2C设备驱动编写(二)

    原文网址:http://www.cnblogs.com/biglucky/p/4059582.html 在(一)中简述了Linux I2C子系统的三个主要成员i2c_adapter.i2c_drive ...

  8. qnx i2c 学习 二

    File still Updating.... many errors have been FOUND , need big change  qnx i2c structure  --written ...

  9. I2C驱动框架(二)

    参考:I2C子系统之I2C bus初始化——I2C_init() 在linux内核启动的时候最先执行的和I2C子系统相关的函数应该是driver/i2c/i2c-core.c文件中的i2c_init( ...

随机推荐

  1. SQL注入攻击的种类和防范手段

    观察近来的一些安全事件及其后果,安全专家们已经得到一个结论,这些威胁主要是通过SQL注入造成的.虽然前面有许多文章讨论了SQL注入,但今天所讨论的内容也许可帮助你检查自己的服务器,并采取相应防范措施. ...

  2. iBatis之type

    iBatis下关于type的UML图,展示iBatis下关于类型的处理和注册等.

  3. 从IRP说起(转)

    原文链接:http://www.cnblogs.com/zhuyp1015/archive/2012/03/14/2396595.html IRP(I/O request package)是操作系统内 ...

  4. 类内const static(static const)成员变量初始化问题

    在查找const相关资料的过程中,又遇到了另外一个问题,就是C++类中const static(或者static const)成员变量应当如何初始化的问题. 查阅了许多资料,发现VC环境下,只允许co ...

  5. 8.3 MPI

    MPI 模型 如图MPI的各个运算节点是分布式的.每一个节点可以视为是一个“Thread”,但这里的不同之处在于这些节点没有所谓的共享内存,或者说Global Memory.所以,在后面也会看到,一般 ...

  6. acm-DP整理

    一.背包 .各种01背包 void leastOne_Pack(int id, int num ) {//至少取一个: int i, j, c, v ; ; i <= num ; i ++ ) ...

  7. nodejs学习:师哥自家的twenty博客框架

    这周继续为DTree项目预热,学习sails框架的搭建和结构熟悉.正好师哥在做一个nodejs的CMS框架twenty,他们用的就是sails框架. 结构 首先简单了解一下结构.在jade文件里由an ...

  8. A Tour of Go Switch with no condition

    Switch without a condition is the same as switch true. This construct can be a clean way to write lo ...

  9. angular ui-route

    http://www.cnblogs.com/freeliver54/p/4488141.html

  10. jQuery插件- Autocomplete应用详解

    项目中有时会用到自动补全查询,就像Google搜索框.淘宝商品搜索功能,输入汉字或字母,则以该汉字或字母开头的相关条目会显示出来供用户选择, autocomplete插件就是完成这样的功能. auto ...