Abstract: MAX30102 测试代码,仅使用温度和血氧测量功能

代码部分

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "MAX30102.h"
#include "Serial.h"
#include "MAX30102_Reg.h"

uint8_t pf=0;
uint8_t mode=1;

void Config_Check(void);

int main(void)
{
MAX30102_Init();
Serial_Init();

Config_Check();
while (1)
{
float Spo2;
MAX30102_Read_FIFO_Data(MAX30102_PPG_Data);
if (MAX30102_PPG_Data[0]<=0x186a0) //未接近
{
if (pf==0)
{
pf=1;
Serial_Printf("Waiting...\r\n");
}
//Delay_ms(20);
continue;
}
pf=0;
if (mode==0) //输出原始数据
{
Serial_Printf("RED=%d,IR=%d\r\n",MAX30102_PPG_Data[0],MAX30102_PPG_Data[1]);
MAX30102_Read_Temp_Data(MAX30102_Temp_Data);
Serial_Printf("Temp=%.2f\r\n",MAX30102_Temp_Cal(MAX30102_Temp_Data));
}
else if (mode==1)//输出计算后的血氧值
{
MAX30102_Spo2_Cal_Median_Filter(&Spo2);
// Serial_Printf("RED=%d,IR=%d\r\n",MAX30102_PPG_Data[0],MAX30102_PPG_Data[1]);
Serial_Printf("Spo2=%.3f%\r\n",Spo2);
}
Delay_ms(200);
}
}

void Config_Check(void)
{
Serial_Printf("rv_id=%hX\r\n",MAX30102_ReadReg(MAX30102_Revision_ID));
Serial_Printf("part_id=%hX\r\n",MAX30102_ReadReg(MAX30102_Part_ID));

Serial_Printf("mode=%hX\r\n",MAX30102_ReadReg(MAX30102_Mode_Configuration));

Serial_Printf("status1=%hX\r\n",MAX30102_ReadReg(MAX30102_Interrupt_Status_1));
Serial_Printf("status2=%hX\r\n",MAX30102_ReadReg(MAX30102_Interrupt_Status_2));

Serial_Printf("enable1=%hX\r\n",MAX30102_ReadReg(MAX30102_Interrupt_Enable_1));
Serial_Printf("enable2=%hX\r\n",MAX30102_ReadReg(MAX30102_Interrupt_Enable_2));
Serial_Printf("rd_ptr=%hX\r\n",MAX30102_ReadReg(MAX30102_FIFO_Read_Pointer));
Serial_Printf("wr_ptr=%hX\r\n",MAX30102_ReadReg(MAX30102_FIFO_Writer_Pointer));
Serial_Printf("overflow=%hX\r\n",MAX30102_ReadReg(MAX30102_Overflow_Counter));
Serial_Printf("fifo_conf=%hX\r\n",MAX30102_ReadReg(MAX30102_FIFO_Configuration));

Serial_Printf("sp02_conf=%hX\r\n",MAX30102_ReadReg(MAX30102_SpO2_Configuration));

Serial_Printf("temp_conf=%hX\r\n",MAX30102_ReadReg(MAX30102_Die_Temperature_Config));

Serial_Printf("led1_amp=%hX\r\n",MAX30102_ReadReg(MAX30102_LED1_Pulse_Amplitude_Configuration));
Serial_Printf("led2_amp=%hX\r\n",MAX30102_ReadReg(MAX30102_LED2_Pulse_Amplitude_Configuration));
}

MAX30102.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
#include "stm32f10x.h"                  // Device header
#include "MAX30102_Reg.h"
#include "Delay.h"

#define MAX30102_ADDR 0xAE //地址

uint32_t MAX30102_PPG_Data[2];
uint8_t MAX30102_Temp_Data[2];


/**
* @brief 求最值函数
* @param 无
* @retval 数据缓存区大小及指针
*/
void MAX30102_Max_Min(uint32_t *Arr,uint8_t Size,uint32_t *Buf)
{
uint32_t Max=0;
uint32_t Min=Arr[0];
uint8_t i;
for (i=0;i<Size;i++)
{
if (Arr[i]>Max)
{
Max=Arr[i];
}
if (Arr[i]<Min)
{
Min=Arr[i];
}
}
if (Max==Min)
{
Min-=1;
}
Buf[0]=Max;
Buf[1]=Min;
}

/**
* @brief 变量交换函数
* @param 无
* @retval 待交换数据的指针
*/
void MAX30102_Swap(uint32_t *a, uint32_t *b)
{
uint32_t temp = *a;
*a = *b;
*b = temp;
}

//中位数计算,参考自https://blog.csdn.net/ONEDAY_789/article/details/76681764
uint32_t MAX30102_PartSort(uint32_t *arr, uint8_t start, uint8_t end)
{
uint8_t left = start;
uint8_t right = end;
uint32_t key = arr[end]; //选取关键字
while (left < right)
{
while (left < right && arr[left] <= key) //左边找比key大的值
{
++left;
}
while (left < right && arr[right] >= key) //右边找比key小的值
{
--right;
}
if (left < right)
{
MAX30102_Swap(&arr[left], &arr[right]); //找到之后交换左右的值
}
}
MAX30102_Swap(&arr[right], &arr[end]);
return left;
}

uint32_t MAX30102_GetMidNumNoSort(uint32_t *arr,uint32_t size)
{
uint8_t start = 0;
uint8_t end = size - 1;
uint8_t mid = (size - 1) / 2;
uint8_t div = MAX30102_PartSort(arr,start,end);
while (div != mid)
{
if (mid < div) //左半区间找
div = MAX30102_PartSort(arr, start, div - 1);
else //左半区间找
div = MAX30102_PartSort(arr, div + 1, end);
}
return arr[mid];
}
//中位数计算结束

/**
* @brief 等待事件发生
* @param 无
* @retval 略
*/
void MAX30102_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
{
uint32_t TimeOut;

TimeOut=1000;
while(I2C_CheckEvent(I2Cx,I2C_EVENT)!=SUCCESS)
{
TimeOut--;
if (TimeOut==0)
{
break;
}
}
}

/**
* @brief I2C指定地址写入数据
* @param 无
* @retval 指定写地址,数据
*/
void MAX30102_WriteReg(uint8_t RegAddress,uint8_t Data)
{
I2C_GenerateSTART(I2C2,ENABLE); //生成起始条件
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT); //检测EV5

I2C_Send7bitAddress(I2C2,MAX30102_ADDR,I2C_Direction_Transmitter); //发送地址
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //检测EV6

I2C_SendData(I2C2,RegAddress); //发送写入地址
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING); //检测EV8

I2C_SendData(I2C2,Data); //发送写入数据
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED); //检测EV8_2

I2C_GenerateSTOP(I2C2, ENABLE); //终止
}

/**
* @brief I2C指定地址读取数据
* @param 无
* @retval 指定读地址
*/
uint8_t MAX30102_ReadReg(uint8_t RegAddress)
{
uint8_t Data;

I2C_GenerateSTART(I2C2,ENABLE); //生成起始条件
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT); //检测EV5

I2C_Send7bitAddress(I2C2,MAX30102_ADDR,I2C_Direction_Transmitter); //发送地址
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //检测EV6

I2C_SendData(I2C2,RegAddress); //发送读取地址
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED); //检测EV8

I2C_GenerateSTART(I2C2,ENABLE); //生成起始条件
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT); //检测EV5

I2C_Send7bitAddress(I2C2,MAX30102_ADDR,I2C_Direction_Receiver); //发送地址
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED); //检测EV6

//只接受一字节
I2C_AcknowledgeConfig(I2C2,DISABLE); // 应答失效
I2C_GenerateSTOP(I2C2,ENABLE); //申请终止

MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED); //检测EV7
Data=I2C_ReceiveData(I2C2);

I2C_AcknowledgeConfig(I2C2,ENABLE); // 应答有效

return Data;
}

/**
* @brief 中断初始化函数
* @param 无
* @retval 无
*/
//void MAX30102_Exit_Init(void)
//{
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//
// GPIO_InitTypeDef GPIO_Initstructure;
// GPIO_Initstructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空输入
// GPIO_Initstructure.GPIO_Pin=GPIO_Pin_0; //PA0
// GPIO_Initstructure.GPIO_Speed=GPIO_Speed_50MHz;
// GPIO_Init(GPIOA,&GPIO_Initstructure);
//
// GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
//
// EXTI_InitTypeDef EXIT_InitStructure;
// EXIT_InitStructure.EXTI_Line=EXTI_Line0; //指定中断线
// EXIT_InitStructure.EXTI_LineCmd=ENABLE; //开启或关闭
// EXIT_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; //中断模式
// EXIT_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling; //下降沿触发
// EXTI_Init(&EXIT_InitStructure);
//
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //整个工程只用执行一次
// NVIC_InitTypeDef NVIC_InitStructure;
// NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
// NVIC_Init(&NVIC_InitStructure);
//}

/**
* @brief 初始化函数
* @param 无
* @retval 无
*/
void MAX30102_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);

I2C_InitTypeDef I2C_InitStructure;
I2C_InitStructure.I2C_Ack=I2C_Ack_Enable; //应答开启
I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit; //七位地址
I2C_InitStructure.I2C_ClockSpeed=200000; //200Khz
I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2; //低:高=2:1,高速有效
I2C_InitStructure.I2C_Mode=I2C_Mode_I2C;
I2C_InitStructure.I2C_OwnAddress1=0X00; //自身地址,从机有效
I2C_Init(I2C2,&I2C_InitStructure);

I2C_Cmd(I2C2,ENABLE);

MAX30102_WriteReg(MAX30102_Mode_Configuration,0X40); //重置模式
Delay_ms(20);

MAX30102_WriteReg(MAX30102_Interrupt_Enable_1,0X40); //中断开启 PPG_RDY 0x40 中断信号为低电平
MAX30102_WriteReg(MAX30102_Interrupt_Enable_2,0X02); //中断开启 DIE_TEMP_RDY 0x02
MAX30102_WriteReg(MAX30102_FIFO_Read_Pointer,0X00); //读指针清零
MAX30102_WriteReg(MAX30102_FIFO_Writer_Pointer,0X00); //写指针清零
MAX30102_WriteReg(MAX30102_Overflow_Counter,0X00); //溢出计数清零
MAX30102_WriteReg(MAX30102_FIFO_Configuration,0X2F); //FIFO配置,AVE=2,ROL=1,FULL=17

MAX30102_WriteReg(MAX30102_SpO2_Configuration,0X2B); //血氧测量配置,ADC=4096,SR=200/s,LED_PW=411,18

MAX30102_WriteReg(MAX30102_LED1_Pulse_Amplitude_Configuration,0X24);
MAX30102_WriteReg(MAX30102_LED2_Pulse_Amplitude_Configuration,0X24);

MAX30102_ReadReg(MAX30102_Interrupt_Status_1); //中断清零
MAX30102_ReadReg(MAX30102_Interrupt_Status_2); //中断清零

MAX30102_WriteReg(MAX30102_Die_Temperature_Config,0X01); //温度测量开
MAX30102_WriteReg(MAX30102_Mode_Configuration,0X03); //血氧模式

// MAX30102_Exit_Init();
}

/**
* @brief 读取FIFO采样数据
* @param 无
* @retval 数据缓存区指针
*/
void MAX30102_Read_FIFO_Data(uint32_t *Buf)
{
uint8_t Data[6];
I2C_AcknowledgeConfig(I2C2,ENABLE); // 应答失效

I2C_GenerateSTART(I2C2,ENABLE); //生成起始条件
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT); //检测EV5

I2C_Send7bitAddress(I2C2,MAX30102_ADDR,I2C_Direction_Transmitter); //发送地址
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //检测EV6

I2C_SendData(I2C2,MAX30102_FIFO_Data_Register); //发送读取地址
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED); //检测EV8

I2C_GenerateSTART(I2C2,ENABLE); //生成起始条件
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT); //检测EV5

I2C_Send7bitAddress(I2C2,MAX30102_ADDR,I2C_Direction_Receiver); //发送地址
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED); //检测EV6

uint8_t i;
uint8_t Tmp;
for (i=0;i<6;i++)
{
if (i==5)
{
//接受最后一字节前设置ACK=0,S=1
I2C_AcknowledgeConfig(I2C2,DISABLE); // 应答失效
I2C_GenerateSTOP(I2C2,ENABLE); //申请终止
}
Tmp=0;
MAX30102_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED); //检测EV7
Tmp=I2C_ReceiveData(I2C2);
Data[i]=Tmp;
}
I2C_AcknowledgeConfig(I2C2,ENABLE); // 应答有效
Buf[0] = ((Data[0]<<16 | Data[1]<<8 | Data[2]) & 0x03ffff); //3fffff
Buf[1] = ((Data[3]<<16 | Data[4]<<8 | Data[5]) & 0x03ffff);
}

/**
* @brief 读取温度数据
* @param 无
* @retval 数据缓存区指针
*/
void MAX30102_Read_Temp_Data(uint8_t *Buf)
{
Buf[0]=MAX30102_ReadReg(MAX30102_Die_Temp_Integer); //整数部分
Buf[1]=MAX30102_ReadReg(MAX30102_Die_Temp_Fraction); //小数部分(只取后四位)
}

/**
* @brief 读取版本ID
* @param 无
* @retval 无
*/
uint8_t MAX30102_Get_Revision_ID(void)
{
return MAX30102_ReadReg(MAX30102_Revision_ID);
}

/**
* @brief 读取部件ID
* @param 无
* @retval 无
*/
uint8_t MAX30102_Get_Part_ID(void)
{
return MAX30102_ReadReg(MAX30102_Part_ID);
}

/**
* @brief 温度计算函数
* @param 无
* @retval 数据缓存区指针
*/
float MAX30102_Temp_Cal(uint8_t *Buf)
{
return (float)Buf[0]+(float)Buf[1]*0.625;
}

/**
* @brief 血氧计算函数
* @param 无
* @retval 略
*/
float MAX30102_Spo2_Cal(uint32_t *Red_Data,uint32_t *Ir_Data,uint8_t Size)
{
float Red_Max,Red_Min;
float Ir_Max,Ir_Min;
float R;
uint32_t Temp[2];
//求出最大最小值
MAX30102_Max_Min(Red_Data,Size,Temp);
Red_Max=Temp[0];
Red_Min=Temp[1];
MAX30102_Max_Min(Ir_Data,Size,Temp);
Ir_Max=Temp[0];
Ir_Min=Temp[1];

R=((Red_Max + Red_Min) / (Red_Max - Red_Min)) / ((Ir_Max + Ir_Min) / (Ir_Max - Ir_Min));
float result=-45.060 * R * R + 30.354 * R + 94.845;
if (result<0)
{
result=0;
}
return result;
}

/**
* @brief 血氧原始数据中位数滤波函数
* @param 无
* @retval 略
*/
void MAX30102_Spo2_Cal_Median_Filter(float *Buf)
{
const uint8_t each_1=8; //each_1 个数据为一组计算血氧
uint32_t Red_m[each_1];
uint32_t Ir_m[each_1];
uint8_t i;
for (i=0;i<each_1;i++)
{
const uint8_t each_2=5; //each_2(奇数) 个数据为一组计算中位数
uint32_t Red_Data[each_2];
uint32_t Ir_Data[each_2];
uint8_t j=0;
for (j=0;j<each_2;j++)
{
MAX30102_Read_FIFO_Data(MAX30102_PPG_Data); // 读取FIFO数据
Red_Data[j]=MAX30102_PPG_Data[0];
Ir_Data[j]=MAX30102_PPG_Data[1];
}
Red_m[i]=MAX30102_GetMidNumNoSort(Red_Data,each_2); //分别计算中位数
Ir_m[i]=MAX30102_GetMidNumNoSort(Ir_Data,each_2);
}
*Buf=MAX30102_Spo2_Cal(Red_m,Ir_m,each_1);
}

/**
* @brief 中断函数
* @param 无
* @retval 无
*/
//void EXTI0_IRQHandler(void)
//{
// if (EXTI_GetITStatus(EXTI_Line0)==SET)
// {
// uint8_t ppg_flag = MAX30102_ReadReg(MAX30102_Interrupt_Status_1) & 0x40;
// uint8_t temp_flag = MAX30102_ReadReg(MAX30102_Interrupt_Status_1) & 0x02;
// if (ppg_flag==0x40)
// {
// MAX30102_Read_FIFO_Data(MAX30102_PPG_Data); //读取采样数据
// }
// if (temp_flag==0x02)
// {
// MAX30102_Read_Temp_Data(MAX30102_Temp_Data); //读取温度数据
// }
// EXTI_ClearITPendingBit(EXTI_Line0);
// }
//}

MAX30102.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef __MAX30102_H
#define __MAX30102_H
#include "stm32f10x.h" // Device header
#include "MAX30102_Reg.h"

extern uint32_t MAX30102_PPG_Data[2];
extern uint8_t MAX30102_Temp_Data[2];
void MAX30102_Init(void);
void MAX30102_Read_FIFO_Data(uint32_t *Buf);
void MAX30102_Read_Temp_Data(uint8_t *Buf);
uint8_t MAX30102_Get_Revision_ID(void);
uint8_t MAX30102_Get_Part_ID(void);
uint8_t MAX30102_ReadReg(uint8_t RegAddress);
float MAX30102_Temp_Cal(uint8_t *Buf);
void MAX30102_Spo2_Cal_Median_Filter(float *Buf);

#endif

MAX30102_Reg.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#ifndef __MAX30102_Reg_H
#define __MAX30102_Reg_H

//STATUS
#define MAX30102_Interrupt_Status_1 0X00 //中断状态1
#define MAX30102_Interrupt_Status_2 0X01 //中断状态2
#define MAX30102_Interrupt_Enable_1 0x02 //中断使能1
#define MAX30102_Interrupt_Enable_2 0x03 //中断使能2
#define MAX30102_FIFO_Writer_Pointer 0x04 //FIFO写指针
#define MAX30102_Overflow_Counter 0x05 //FIFO满后遗失的采样数
#define MAX30102_FIFO_Read_Pointer 0x06 //FIFO读指针
#define MAX30102_FIFO_Data_Register 0x07 //FIFO数据寄存器
//Configuration
#define MAX30102_FIFO_Configuration 0x08 //FIFO配置
#define MAX30102_Mode_Configuration 0x09 //模式配置
#define MAX30102_SpO2_Configuration 0x0A //血氧测量配置
#define MAX30102_LED1_Pulse_Amplitude_Configuration 0x0C //LED1脉冲波幅配置(RED)
#define MAX30102_LED2_Pulse_Amplitude_Configuration 0x0D //LED2脉冲波幅配置(IR)
#define MAX30102_Proximity_Mode_LED_Pulse_Amplitude 0X10 //接近检测模式LED波幅配置
#define MAX30102_MultiLED_Mode_Control_Registers_SLOT2_SLOT1 0x11 //混合LED模式配置(slot2、slot1)
#define MAX30102_MultiLED_Mode_Control_Registers_SLOT4_SLOT3 0x12 //混合LED模式配置(slot4、slot3)
//DIE TEMPERATURE
#define MAX30102_Die_Temp_Integer 0x1F //温度测量值(整数部分)
#define MAX30102_Die_Temp_Fraction 0x20 //温度测量值(小数部分)
#define MAX30102_Die_Temperature_Config 0x21 //温度测量配置
//PROXIMITY FUNCTION
#define MAX30102_Proximity_Interrupt_Threshold 0x30 //接近检测中断阈值
//PART ID
#define MAX30102_Revision_ID 0XFE //版本ID,从寄存器读取
#define MAX30102_Part_ID 0xFF //器件ID,0x15

#endif

串口数据样例

mode=0,输出原始数据

RED=150445,IR=134586
Temp=28.25
RED=150581,IR=134643
Temp=28.25
RED=150676,IR=134684
Temp=28.25
RED=150872,IR=134769
Temp=28.25
RED=151041,IR=134828
Temp=28.25
RED=151136,IR=134869
Temp=28.25
RED=151271,IR=134928
Temp=28.25
RED=151357,IR=134979
Temp=28.25
RED=151447,IR=135035
Temp=28.25
RED=151501,IR=135065
Temp=28.25
RED=151573,IR=135072
Temp=28.25
RED=151270,IR=134908
Temp=28.25
RED=150767,IR=134666
Temp=28.25
RED=150037,IR=134310
Temp=28.25
RED=149637,IR=134133
Temp=28.25
Waiting…

mode=1,输出血氧值

Spo2=98.968
Spo2=97.083
Spo2=99.789
Spo2=99.755
Spo2=99.537
Spo2=97.666
Spo2=99.740
Spo2=99.955
Spo2=96.622
Spo2=97.839
Spo2=98.715
Spo2=95.240
Spo2=96.473
Spo2=99.735
Spo2=95.161
Spo2=87.345
Spo2=59.356
Spo2=89.408
Spo2=95.111
Spo2=90.659
Spo2=99.778
Spo2=97.260
Spo2=99.744
Spo2=99.481
Spo2=98.376
Spo2=97.231
Spo2=99.917
Spo2=97.851
Spo2=98.049
Spo2=99.458
Spo2=99.815
Spo2=80.416
Waiting…

其他

  • 有时会出现I2C应答正常但是读写数据异常的情况,此时断电重启就可以解决,具体原因未知
  • 代码注释部分为中断功能,使用困难固注释
  • 原始数据使用了中位数滤波,但是结果仍不稳定