i2c是树莓派支持的一个串行通信协议,可以通过wringPi操作i2c设备,向i2c设备内部的寄存器读数据或写数据。主要的初始化流程如下:
- 添加WiringPi 的依赖
- 引入i2C库
- 初始化WiringPi
- 初始化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 文件里添加对应依赖
LIBS += -lwiringPi
2. 引入i2c的头文件
在mainwindows.h中,引入与i2c相关的两个头文件
#include "wiringPi.h"
#include "wiringPiI2C.h"
3. 声明fd
对i2c设备的操作,都基于fd进行。因此需要在.h 文件中,声明一个fd
,类型是int
。
fd其实代表的是文件描述符号( file descriptor ),在linux系统里面,硬件设备在操作系统里面都以fd来标识和索引,可以通过fd来对一个设备进行操作,一般就是一个数字。I2C在树莓派的操作系统中,也是作为一个fd来进行识别。因此需要在初始化的时候声明一个int类型保存fd。
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
int fd // i2c设备的文件描述符
private:
Ui::MainWindow *ui;
};
4. 初始化WirngPI和WiringPiI2C
在初始化函数内, 初始化wiringPi和wiringPiI2C这两个模块。其中wiringPiI2CSetup
要传入一个参数,是i2c设备的地址。ADXL345的默认地址是0x53
,下面是初始化的代码
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
wiringPiSetup();
fd = wiringPiI2CSetup(0x53);
}
到这里,就完成了对I2C的基本配置。如果只考i2c的配置已经足够
5. 向I2C设备写入数据
wiringPiI2CWriteReg8**(int fd, int reg) **可以实现向I2C设备的指定寄存器写入数据
以向设备的0x66写入0x88为例子:
wiringPiI2CWriteReg8(0x66, 0x88);
6. 向I2C设备读数据
wiringPiI2CReadReg8**(int fd, int reg)**可以实现向I2C设备的指定寄存器读取数据
以向设备的0xe5读数据为例子
wiringPiI2CReadReg8(0xe5);
7. 对ADXL345进行初始化
void MainWindow::adxl345_init(){
wiringPiI2CWriteReg8(fd, 0x31, 0x0b);//设置数据格式为全分辨率,范围最大
wiringPiI2CWriteReg8(fd, 0x2c, 0x0a);//设置速度为50hz
wiringPiI2CWriteReg8(fd, 0x1e , 0x00);//清空x偏移设置
wiringPiI2CWriteReg8(fd, 0x1f , 0x00);//清空y偏移设置
wiringPiI2CWriteReg8(fd, 0x20 , 0x00);//清空z偏移设置
wiringPiI2CWriteReg8(fd, 0x2d , 0x08); //配置为唤醒模式
}
8. 读取ADXL345的三个轴上的加速度
struct acc_dat MainWindow::adxl345_read_xyz()
{
char x0, y0, z0, x1, y1, z1;// 用来保存x, y, z的两个分量
struct acc_dat acc_xyz;
x0 = (char)wiringPiI2CReadReg8(fd, 0x32 );
x1 = (char)wiringPiI2CReadReg8(fd, 0x33 );
y0 = (char)wiringPiI2CReadReg8(fd, 0x34 );
y1 = (char)wiringPiI2CReadReg8(fd, 0x35 );
z0 = (char)wiringPiI2CReadReg8(fd, 0x36 );
z1 = (char)wiringPiI2CReadReg8(fd, 0x37 );
acc_xyz.x = ((quint16)(x1 << 8) | x0) /(double)256; //缩放
acc_xyz.y = ((quint16)(y1 << 8) | y0) /(double)256 ; //缩放
acc_xyz.z = ((quint16)(z1 << 8) | z0) /(double)256; //缩放
return acc_xyz;
}