i2c是树莓派支持的一个串行通信协议,可以通过wringPi操作i2c设备,向i2c设备内部的寄存器读数据写数据。主要的初始化流程如下:

  1. 添加WiringPi 的依赖
  2. 引入i2C库
  3. 初始化WiringPi
  4. 初始化WiringPiI2C,通过指定i2c设备地址,获取i2c设备fd

完成以上步骤后,就可以对I2C设备进行读写。

在写数据的时候,使用的函数是 **wiringPiI2CWriteReg8(int fd, int reg, int **data) ,有3个参数,解释如下

  • 第一个参数是i2c设备的fd
  • 第二个参数是i2c设备内部寄存器的地址(和i2c设备自身的地址没有关系)
  • 第三个参数是对目标寄存器的想写入的数据

在读数据的时候,使用的函数是int **wiringPiI2CReadReg8(int fd, int **reg) ,有2个参数,解释如下

  • 第一个参数是i2c设备的fd
  • 第二个参数是想要读取的寄存器在I2C设备内部的地址

读取的数据最终会以int返回值的形式来返回读到的,i2c设备寄存器里的地址。

1. 添加i2c的依赖

操作i2c需要wiringPi库的支持。在.pro 文件里添加对应依赖

  1. LIBS += -lwiringPi

2. 引入i2c的头文件

在mainwindows.h中,引入与i2c相关的两个头文件

  1. #include "wiringPi.h"
  2. #include "wiringPiI2C.h"

3. 声明fd

对i2c设备的操作,都基于fd进行。因此需要在.h 文件中,声明一个fd,类型是int
fd其实代表的是文件描述符号( file descriptor ),在linux系统里面,硬件设备在操作系统里面都以fd来标识和索引,可以通过fd来对一个设备进行操作,一般就是一个数字。I2C在树莓派的操作系统中,也是作为一个fd来进行识别。因此需要在初始化的时候声明一个int类型保存fd。

  1. class MainWindow : public QMainWindow
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit MainWindow(QWidget *parent = nullptr);
  6. ~MainWindow();
  7. int fd // i2c设备的文件描述符
  8. private:
  9. Ui::MainWindow *ui;
  10. };

4. 初始化WirngPI和WiringPiI2C

在初始化函数内, 初始化wiringPi和wiringPiI2C这两个模块。其中wiringPiI2CSetup要传入一个参数,是i2c设备的地址。ADXL345的默认地址是0x53 ,下面是初始化的代码

  1. MainWindow::MainWindow(QWidget *parent) :
  2. QMainWindow(parent),
  3. ui(new Ui::MainWindow)
  4. {
  5. ui->setupUi(this);
  6. wiringPiSetup();
  7. fd = wiringPiI2CSetup(0x53);
  8. }

到这里,就完成了对I2C的基本配置。如果只考i2c的配置已经足够

5. 向I2C设备写入数据

wiringPiI2CWriteReg8**(int fd, int reg) **可以实现向I2C设备的指定寄存器写入数据
以向设备的0x66写入0x88为例子:

  1. wiringPiI2CWriteReg8(0x66, 0x88);

6. 向I2C设备读数据

wiringPiI2CReadReg8**(int fd, int reg)**可以实现向I2C设备的指定寄存器读取数据
以向设备的0xe5读数据为例子

  1. wiringPiI2CReadReg8(0xe5);

7. 对ADXL345进行初始化

  1. void MainWindow::adxl345_init(){
  2. wiringPiI2CWriteReg8(fd, 0x31, 0x0b);//设置数据格式为全分辨率,范围最大
  3. wiringPiI2CWriteReg8(fd, 0x2c, 0x0a);//设置速度为50hz
  4. wiringPiI2CWriteReg8(fd, 0x1e , 0x00);//清空x偏移设置
  5. wiringPiI2CWriteReg8(fd, 0x1f , 0x00);//清空y偏移设置
  6. wiringPiI2CWriteReg8(fd, 0x20 , 0x00);//清空z偏移设置
  7. wiringPiI2CWriteReg8(fd, 0x2d , 0x08); //配置为唤醒模式
  8. }

8. 读取ADXL345的三个轴上的加速度

  1. struct acc_dat MainWindow::adxl345_read_xyz()
  2. {
  3. char x0, y0, z0, x1, y1, z1;// 用来保存x, y, z的两个分量
  4. struct acc_dat acc_xyz;
  5. x0 = (char)wiringPiI2CReadReg8(fd, 0x32 );
  6. x1 = (char)wiringPiI2CReadReg8(fd, 0x33 );
  7. y0 = (char)wiringPiI2CReadReg8(fd, 0x34 );
  8. y1 = (char)wiringPiI2CReadReg8(fd, 0x35 );
  9. z0 = (char)wiringPiI2CReadReg8(fd, 0x36 );
  10. z1 = (char)wiringPiI2CReadReg8(fd, 0x37 );
  11. acc_xyz.x = ((quint16)(x1 << 8) | x0) /(double)256; //缩放
  12. acc_xyz.y = ((quint16)(y1 << 8) | y0) /(double)256 ; //缩放
  13. acc_xyz.z = ((quint16)(z1 << 8) | z0) /(double)256; //缩放
  14. return acc_xyz;
  15. }