六、树莓派+MAX30102血氧模块(WiringPi I2C试验)
wiringPi I2C库相关
1、wiringPi包含了一个I2C库,能让您能够轻松的使用树莓派上I2C接口,在使用I2C接口之前,您可能需要使用gpio命令来加载I2C驱动到内核中:
gpio load i2c
注:在实际的使用中先使用 sudo raspi-config 对树莓派I2C接口进行开启
但是在这之后无论怎么使用 gpio load i2c 指令,一直提示如下报错内容
gpio: Unable to load/unload modules as this Pi has the device tree enabled. You need to run the raspi-config program (as root) and select the modules (SPI or I2C) that you wish to load/unload there and reboot.
在网络上查询了老半天也不知道这个问题应该怎么解决,在链接:https://forums.raspberrypi.com/viewtopic.php?t=136867 中得知,使用 raspi-config 打开I2C后,以上报错可以忽略,不影响I2C使用。
2、如果你需要的波特率不是1000Kbps,那么您可以使用如下命令设置波特率为1000Kbps:
gpio load i2c 1000
3、使用I2C库,需要包含wiringPiI2C.h文件,并且在编译时,同样需要使用 -lwiringPi来连接到wiringPi库
4、您仍可以使用标准的系统命令来检测I2C设备,如i2cdetect命令,需要注意的是在V1版本的树莓派上是 0 ,V2版本上是 1,如下:
i2cdetect -y 0 #Rev 1 i2cdetect -y 1 #Rev 1
当然你也可以使用gpio指令来调用 i2cdetect 命令,从而检测I2C设备,如下:
gpio i2cdetect
5、I2C库函数接口如下:
函数接口 | 函数原型 | 参数说明 | 功能说明 |
wiringPiI2CSetup |
int wiringPiI2CSetup(int devId) |
返回值:标准的Linux句柄,也就是下面各接口中的 fd,如有错误则返回 -1 devId: 设备ID号(即为通过i2cdetect指令扫描出的设备ID) |
该函数使用指定的设备标号来初始化I2C系统 |
wiringPiI2CRead | int wiringPiI2CRead(int fd) |
返回值:接收到的数据 fd:wiringPiI2CSetup的返回值 |
简单的设备读操作,一些设备可以直接读取,而不需要发送任何寄存器地址 |
wiringPiI2CWrite | int wiringPiI2CWrite(int fd, int data) |
返回值:写入状态 fd:wiringPiI2CSetup的返回值 data:待写入数据 |
简单的设备写操作,一些设备可以接收数据,而不需要发送任何寄存器地址 |
wiringPiI2CWriteReg8 | int wiringPiI2CWriteReg8(int fd, int reg ,int data) |
返回值:写入状态 fd:wiringPiI2CSetup的返回值 reg:寄存器地址 data:待写入数据 |
使用该函数,可以写一个8位的数值到指定寄存器 |
wiringPiI2CWriteReg16 | int wiringPiI2CWriteReg16(int fd, int reg ,int data) |
返回值:写入状态 fd:wiringPiI2CSetup的返回值 reg:寄存器地址 data:待写入数据 |
使用该函数,可以写一个16位的数值到指定寄存器 |
wiringPiI2CReadReg8 | int wiringPiI2CReadReg8(int fd, int reg ) |
返回值:读取到的数据 fd:wiringPiI2CSetup的返回值 reg:寄存器地址 |
使用该函数,可以从指定寄存器中读一个8位的数值 |
wiringPiI2CReadReg16 | int wiringPiI2CReadReg16(int fd, int reg ) |
返回值:读取到的数据 fd:wiringPiI2CSetup的返回值 reg:寄存器地址 |
使用该函数可以从指定寄存器中读一个16位的数值 |
代码实现对血氧检测原始数据读取:
#include <stdio.h> #include <wiringPi.h> #include <wiringSerial.h> #include <wiringPiI2C.h> #define REG_INTR_STATUS_1 0x00 #define REG_INTR_STATUS_2 0x01 #define REG_INTR_ENABLE_1 0x02 #define REG_INTR_ENABLE_2 0x03 #define REG_FIFO_WR_PTR 0x04 #define REG_OVF_COUNTER 0x05 #define REG_FIFO_RD_PTR 0x06 #define REG_FIFO_DATA 0x07 #define REG_FIFO_CONFIG 0x08 #define REG_MODE_CONFIG 0x09 #define REG_SPO2_CONFIG 0x0A #define REG_LED1_PA 0x0C #define REG_LED2_PA 0x0D #define REG_PILOT_PA 0x10 #define REG_MULTI_LED_CTRL1 0x11 #define REG_MULTI_LED_CTRL2 0x12 #define REG_TEMP_INTR 0x1F #define REG_TEMP_FRAC 0x20 #define REG_TEMP_CONFIG 0x21 #define REG_PROX_INT_THRESH 0x30 #define REG_REV_ID 0xFE #define REG_PART_ID 0xFF int num = 0; void FunMax30102Init(void) {
//具体寄存器描述可查看MAX30102数据手册 wiringPiI2CWriteReg8(num, REG_MODE_CONFIG , 0x40); //复位 wiringPiI2CWriteReg8(num, REG_MODE_CONFIG , 0x40); //复位
wiringPiI2CWriteReg8(num, REG_INTR_ENABLE_1, 0xC0); //中断1使能 A_FULL_EN、ALC_OVF_EN、PROX_INT_EN wiringPiI2CWriteReg8(num, REG_INTR_ENABLE_2, 0x00); //中断2使能 DIE_TEMP_RDY_EN wiringPiI2CWriteReg8(num, REG_FIFO_WR_PTR , 0x00); //FIFO写指针 wiringPiI2CWriteReg8(num, REG_OVF_COUNTER , 0x00); //FIFO计数器 wiringPiI2CWriteReg8(num, REG_FIFO_RD_PTR , 0x00); //FIFO读指针 wiringPiI2CWriteReg8(num, REG_FIFO_CONFIG , 0xFF); //FIFO配置 wiringPiI2CWriteReg8(num, REG_MODE_CONFIG , 0x03); //设置为SPO2血氧检测模式 wiringPiI2CWriteReg8(num, REG_SPO2_CONFIG , 0x27); //SPO2配置 wiringPiI2CWriteReg8(num, REG_LED1_PA , 0x24); //LED1 wiringPiI2CWriteReg8(num, REG_LED2_PA , 0x24); //LED2 wiringPiI2CWriteReg8(num, REG_PILOT_PA , 0x7F); // } void FunMAX30102ReadFifo(unsigned int *PunRed, unsigned int *PunIr) {
//在SPO2模式下,FIFO每个样本中会包括三个字节数据,且前三个字节为 RED,后三个字节为 IR,以此类推,因此在对数据进行读取时每回需要读取6个字节,前3个字节为RED,后三个字节为IR
unsigned int Temp0 = 0; unsigned int Temp1 = 0; wiringPiI2CReadReg8(num, REG_INTR_STATUS_1); wiringPiI2CReadReg8(num, REG_INTR_STATUS_2); Temp0 = wiringPiI2CReadReg8(num, REG_FIFO_DATA); Temp0 <<= 16; *PunRed += Temp0; Temp0 = wiringPiI2CReadReg8(num, REG_FIFO_DATA); Temp0 <<= 8; *PunRed += Temp0; Temp0 = wiringPiI2CReadReg8(num, REG_FIFO_DATA); *PunRed += Temp0; Temp1 = wiringPiI2CReadReg8(num, REG_FIFO_DATA); Temp1 <<= 16; *PunIr += Temp1; Temp1 = wiringPiI2CReadReg8(num, REG_FIFO_DATA); Temp1 <<= 8; *PunIr += Temp1; Temp1 = wiringPiI2CReadReg8(num, REG_FIFO_DATA); *PunIr += Temp1; *PunRed &= 0x3FFFF; *PunIr &= 0x3FFFF; } int main() { int fd = 0; int Temp = 0; int FifoData = 0; unsigned int PunRed = 0; unsigned int PunIr = 0; wiringPiSetup(); num = wiringPiI2CSetup(0x57);//gpio i2cdetect if (num == -1) { printf("I2C Error\r\n"); } else { printf("num = %d\r\n", num); } FunMax30102Init(); fd = serialOpen("/dev/ttyS0",115200); pinMode(26,OUTPUT); pinMode(27,OUTPUT); pinMode(7, INPUT); digitalWrite(26,HIGH); digitalWrite(27,HIGH); while(1) { //if (digitalRead(7) == 1) { FunMAX30102ReadFifo(&PunRed, &PunIr); //FifoData = wiringPiI2CReadReg8(num, 0x07); printf("%d , %d\r\n",PunRed, PunIr); } } return 0; }
试验结果:
相关参考链接:
https://blog.csdn.net/u012183892/article/details/109545972
https://blog.csdn.net/weixin_45633206/article/details/110276226
https://blog.csdn.net/lin5103151/article/details/109412943
本文来自博客园,作者:伽椰子真可爱,转载请注明原文链接:https://www.cnblogs.com/jiayezi/p/16918304.html