STM32F103C8T6 MAX30102心率血样模块的的使用方法和代码驱动

文档结尾有代码下载链接

🎯 实现效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

🌟 传感器用途

1. 传感器原理

MAX30102 基于光体积描记法(PPG) 工作,其原理是利用人体组织对不同波长光的吸收差异实现生理参数检测:

  • 红光(660nm):血红蛋白(Hb)和氧合血红蛋白(HbO₂)对其吸收差异较大,主要用于血氧饱和度(SpO₂)计算;
  • 红外光(880nm/940nm):受血氧影响较小,更适合心率(HR)检测,且穿透皮肤深度更深,减少皮肤色素干扰;
  • 信号生成:LED 发射的光穿透皮肤后,部分被血液、肌肉、骨骼吸收,剩余光被光电探测器接收并转化为电信号。当心脏跳动时,血液流量变化导致光吸收量波动,形成周期性 PPG 波形,通过分析波形可提取心率和血氧信息。

2. 传感器用途

a.运动康复领域
  • 术后康复监测:用于心脏手术后患者的居家康复,实时监测心率变化,避免剧烈活动导致心脏负担过重。
  • 呼吸训练辅助:结合 PPG 波形的呼吸频率提取(通过 PPG 基线漂移周期),指导慢性阻塞性肺疾病(COPD)患者进行呼吸训练。
b.特殊环境应用
  • 高原血氧监测:在高海拔地区(如登山、高原作业),监测人体血氧饱和度变化,预警高原反应(血氧 < 85% 时触发报警)。
  • 航天航空领域:集成于航天员舱内生命体征监测系统,在微重力环境下稳定检测心率和血氧。
c. 母婴健康领域
  • 胎儿心率监测:通过孕妇腹部微弱的 PPG 信号(需搭配高灵敏度模式),间接监测胎儿心率(需与超声监测校准)。
  • 婴儿睡眠监护:设计为婴儿襁褓传感器,监测睡眠时的心率和呼吸频率,异常时通过蓝牙向家长手机推送报警。
d.工业与安全领域
  • 井下作业监护:矿工安全帽集成传感器,监测井下缺氧环境(低氧导致血氧下降)和心率异常,联动井下报警系统。
  • 高压作业监测:电力工人绝缘手套内置柔性传感器,监测作业时的生理状态,避免高压环境下的突发健康风险。

🌟 传感器的介绍

MAX30102 是由美信研发的高集成度、低功耗心率(HR)与血氧饱和度(SpO₂)检测传感器。它基于光体积描记法(PPG)原理设计,专为医疗健康、消费电子等场景打造,可直接输出数字化生理信号,无需复杂外围电路,是当前智能穿戴、便携式健康设备的核心组件之一。

  • MAX30102 的参数设计充分适配多场景需求。在光学参数方面,其红光 LED 波长为 660±10nm,红外 LED 波长可选 880±10nm 或 940±10nm;配备高响应度硅光电二极管(响应度>0.5A/W @660nm),LED 驱动电流支持 0~60mA 可调(步长 1.875mA),并可动态调整。
  • 电气参数上,工作电压范围为 2.7V~5.5V,兼容 3.3V 主流 MCU,无需电平转换;工作电流根据模式不同有所差异:心率 + 血氧联合模式下为 1.8mA(LED 电流 20mA,采样率 100Hz),仅心率模式为 1.2mA,待机模式低至 0.1μA,关机模式更是<0.01μA;通信接口采用 I2C,速率最高 400kHz,支持双地址(0x56/0x57,由 ADDR 引脚控制)。
  • 环境参数上,工作温度范围为 - 40℃- 85℃,能适应高原、低温户外等极端环境;存储温度为 - 40℃~125℃;抗干扰性突出,内置环境光抑制电路可抵抗>50000 lux 强光干扰(如阳光直射、LED 灯照射),并支持硬件噪声滤波。
  • 在低功耗方面,其待机电流仅 0.1μA,关机电流<0.01μA,可适配纽扣电池(如 CR2032)或锂电池供电的便携式设备,例如智能手环续航可达 7~14 天;同时支持 “脉冲式 LED 驱动” 技术,LED 仅在采样时点亮(如 100Hz 采样率下,单次点亮时间仅 1μs),大幅降低功耗损耗。
  • 灵活性方面,它支持 “仅心率”“仅血氧”“心率 + 血氧联合”3 种工作模式,可按需切换;LED 电流、采样率、FIFO 缓存深度均通过寄存器灵活配置,能平衡检测精度与功耗;还可通过寄存器设定 “心率上下限”“血氧上下限”,参数超限时触发中断(如血氧<90% 时启动报警)。

🎯 单片机连接硬件图

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

🌟 驱动思路

MAX30102 与 STM32F103 的驱动思路为 “硬件层配置→传感器初始化→数据交互→信号处理→参数输出” 的完整闭环。

步骤 1:硬件初始化

  • 首先进行 I2C 接口的初始化。配置 STM32F103C8T6 的 I2C,设置通信速率为 400kHz,使能 I2C 外设。在初始化过程中,需要配置相关的 GPIO 引脚为复用功能,设置 I2C 的时钟频率、地址模式等参数,确保 I2C 通信能够正常进行。接着进行传感器的上电检测。

步骤 2:传感器配置

  • 测模式选择:根据需求配置为 “心率 + 血氧联合模式”(同时输出红光、红外光数据)、“仅心率模式”(仅红外光工作,降低功耗)或 “仅血氧模式”(红光与红外光交替工作)。
  • LED 参数配置:调整红光与红外光的驱动电流(通常 20~30mA),平衡 “信号强度” 与 “功耗”—— 电流过低会导致信号微弱,过高则增加功耗并加速 LED 老化 。
  • 采样率与分辨率:设定采样率(如 100Hz 用于静息监测,200Hz 用于运动场景)与 ADC 分辨率(优先选 18 位,确保捕捉微弱的血液流动信号)。
  • FIFO 缓存配置:设置 FIFO 缓存深度(如 16 或 32 个样本),让传感器暂存多组数据后再触发中断,减少 STM32 的读取频率,降低系统开销。

步骤 3:数据读取

  • 通过 I2C 连续读取传感器的 “FIFO 数据寄存器”(共 6 字节,分别对应红光、红外光的原始数据);读取前需先读取 “中断状态寄存器” 并清除中断标志,防止后续重复触发;读取后通过移位、拼接将 6 字节数据转换为红光、红外光的 16 位数值。
  • 数据有效性筛选:对读取的红光、红外光数据进行初步判断(如数据是否高于最低阈值),过滤因传感器未贴紧皮肤(数据过弱)、环境光干扰(数据异常)导致的无效值;若数据无效,重置数据缓存索引,重新等待下一轮数据;若有效,将数据存入预设的缓存数组(为后续信号处理做准备)。

步骤 4:数据转换与处理

  • 心率计算:根据频域峰值对应的频率,结合采样率与 FFT 点数,换算为每分钟心跳数(心率 = 频率 ×60)。
  • 血氧计算:基于 “红光与红外光对氧合 / 未氧合血红蛋白的吸收差异”,计算 “红外光交流分量 / 红外光直流分量” 与 “红光交流分量 / 红光直流分量” 的比值(R 值),代入行业通用的二次经验公式(如 SpO₂=-45.06×R²+30.35×R+94.85),得到血氧饱和度(SpO₂)。

🎯 单片机程序代码

main.c

#include "stm32f10x.h"  
#include "string.h"  
#include "stdio.h" 
#include "delay.h"   
#include "bsp_usart.h"
#include "oled.h"
#include "MAX30102.h"
#include "blood.h"
int main(void)
{
	NVIC_PriorityGroupConfig (NVIC_PriorityGroup_2);
	SysTick_Init(72);  //系统时钟初始化 
	usart1_init(115200);//串口1初始化
	printf("USART1 OK!\r\n");
	usart2_init(9600);//串口1初始化
	usart3_init(115200);//串口3初始化	
	OLED_Init();
	MAX30102_Init();		//心率传感器初始化
	OLED_ShowString(0,0,"MAX30102");
	while(1)
	{
		blood_Loop();
		OLED_ShowString(0,2,"心率");
    OLED_ShowNum(40,2,g_blooddata.heart,3,16);
		OLED_ShowString(0,4,"血氧");
    OLED_ShowNum(40,4,g_blooddata.SpO2,2,16);
	}
}


MAX30102.c

#include "MAX30102.h"
#include "delay.h"   

uint16_t fifo_red;
uint16_t fifo_ir;
uint8_t max30102_int_flag=0;  		//中断标志
void MAX30102_GPIO(void)
{	

	GPIO_InitTypeDef GPIO_InitStructure;
	
	
	
	RCC_APB2PeriphClockCmd(MAX30102_INTPin_CLK,ENABLE);
	/* 选择按键用到的GPIO */	
  GPIO_InitStructure.GPIO_Pin = MAX30102_INTPin_Pin;
  /* 配置为浮空输入 */	
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_Init(MAX30102_INTPin_PORT, &GPIO_InitStructure);

}


uint8_t Max30102_reset(void)
{
	if(IIC_Write_Byte(MAX30102_Device_address,REG_MODE_CONFIG, 0x40))
        return 1;
    else
        return 0;    
}

void MAX30102_Config(void)
{
	IIC_Write_Byte(MAX30102_Device_address,REG_INTR_ENABLE_1,0xc0);//// INTR setting
	IIC_Write_Byte(MAX30102_Device_address,REG_INTR_ENABLE_2,0x00);//
	IIC_Write_Byte(MAX30102_Device_address,REG_FIFO_WR_PTR,0x00);//FIFO_WR_PTR[4:0]
	IIC_Write_Byte(MAX30102_Device_address,REG_OVF_COUNTER,0x00);//OVF_COUNTER[4:0]
	IIC_Write_Byte(MAX30102_Device_address,REG_FIFO_RD_PTR,0x00);//FIFO_RD_PTR[4:0]
	
	IIC_Write_Byte(MAX30102_Device_address,REG_FIFO_CONFIG,0x0f);//sample avg = 1, fifo rollover=false, fifo almost full = 17
	IIC_Write_Byte(MAX30102_Device_address,REG_MODE_CONFIG,0x03);//0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
	IIC_Write_Byte(MAX30102_Device_address,REG_SPO2_CONFIG,0x27);	// SPO2_ADC range = 4096nA, SPO2 sample rate (50 Hz), LED pulseWidth (400uS)  
	IIC_Write_Byte(MAX30102_Device_address,REG_LED1_PA,0x32);//Choose value for ~ 10mA for LED1
	IIC_Write_Byte(MAX30102_Device_address,REG_LED2_PA,0x32);// Choose value for ~ 10mA for LED2
	IIC_Write_Byte(MAX30102_Device_address,REG_PILOT_PA,0x7f);// Choose value for ~ 25mA for Pilot LED
}

void max30102_read_fifo(void)
{
  uint16_t un_temp;
	uint8_t data=0;
  fifo_red=0;
  fifo_ir=0;
  uint8_t ach_i2c_data[6];
  
  //read and clear status register
  IIC_Read_Array(MAX30102_Device_address,REG_INTR_STATUS_1,&data,1);
  IIC_Read_Array(MAX30102_Device_address,REG_INTR_STATUS_2,&data,1);
  
  ach_i2c_data[0]=REG_FIFO_DATA;
	
	IIC_Read_Array(MAX30102_Device_address,REG_FIFO_DATA,ach_i2c_data,6);
	
  un_temp=ach_i2c_data[0];
  un_temp<<=14;
  fifo_red+=un_temp;
  un_temp=ach_i2c_data[1];
  un_temp<<=6;
  fifo_red+=un_temp;
  un_temp=ach_i2c_data[2];
	un_temp>>=2;
  fifo_red+=un_temp;
  
  un_temp=ach_i2c_data[3];
  un_temp<<=14;
  fifo_ir+=un_temp;
  un_temp=ach_i2c_data[4];
  un_temp<<=6;
  fifo_ir+=un_temp;
  un_temp=ach_i2c_data[5];
	un_temp>>=2;
  fifo_ir+=un_temp;
	

}
void MAX30102_Init(void)
{
	IIC_GPIO_INIT();
	MAX30102_GPIO();
	Max30102_reset();
	MAX30102_Config();
}

🎯 代码下载链接

https://download.csdn.net/download/qq_41954594/92128179

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐