news 2026/6/11 10:22:03

手把手教你用MAX30102和OLED做一个桌面心率血氧监测仪(附STM32完整工程)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手教你用MAX30102和OLED做一个桌面心率血氧监测仪(附STM32完整工程)

从零打造智能心率血氧监测仪:MAX30102与STM32实战指南

在健康监测设备日益普及的今天,能够自主搭建一个精准的心率血氧监测系统不仅是一项有趣的电子项目,更是掌握生物信号处理技术的绝佳途径。本文将带你完整实现基于MAX30102传感器和STM32的桌面监测仪,涵盖硬件选型、算法解析到数据显示的全流程。

1. 项目核心组件解析

MAX30102作为本项目的心脏,是一款集成了红光(660nm)和红外光(880nm)LED、光电检测器、环境光抑制电路的数字传感器。其光学设计原理基于**光电容积图(PPG)**技术——当LED光线穿透人体组织时,动脉搏动会引起光吸收量的微小变化,这些变化被转换为电信号后,通过算法可提取出心率和血氧饱和度(SpO2)参数。

关键组件选型建议:

组件推荐型号技术参数备注
主控STM32F103C8T6Cortex-M3内核,72MHz主频最小系统板即可
传感器MAX30102采样率可达3.2kHz注意选择带FIFO的版本
显示屏SSD1306 0.96寸OLED128x64分辨率,I2C接口省电且可视角度大
电源AMS1117-3.3V最大800mA输出需配合滤波电容

硬件连接时需要特别注意:

  • MAX30102的INT引脚连接STM32的外部中断引脚(如PB9)
  • I2C总线需加上拉电阻(通常4.7kΩ)
  • 传感器背面应贴覆遮光海绵,避免环境光干扰

2. STM32开发环境搭建

使用STM32CubeMX进行工程初始化能大幅提升开发效率。关键配置步骤如下:

  1. 在Pinout视图中启用I2C1(选择PB8为SDA,PB7为SCL)
  2. 配置USART1用于调试输出(波特率115200)
  3. 设置一个定时器(TIM2)用于采样周期控制
  4. 启用PB9作为外部中断输入(下降沿触发)
// CubeMX生成的I2C初始化代码片段 hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 400000; // 标准模式400kHz hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); }

建议工程目录结构:

/Drivers /MAX30102 max30102.c max30102.h /Algorithm algorithm.c algorithm.h /Application /User main.c stm32f1xx_it.c

3. MAX30102驱动开发

传感器初始化需要精细配置多个寄存器:

void MAX30102_Init(void) { // 复位传感器 MAX30102_WriteReg(REG_MODE_CONFIG, 0x40); HAL_Delay(50); // FIFO配置:平均采样4次,几乎满时触发中断 MAX30102_WriteReg(REG_FIFO_CONFIG, 0x4F); // 模式配置:SpO2模式(红光+红外光) MAX30102_WriteReg(REG_MODE_CONFIG, 0x03); // SpO2配置:100Hz采样率,1600us脉冲宽度 MAX30102_WriteReg(REG_SPO2_CONFIG, 0x27); // LED脉冲幅度设置(7mA) MAX30102_WriteReg(REG_LED1_PA, 0x24); // 红光LED MAX30102_WriteReg(REG_LED2_PA, 0x24); // 红外LED // 启用PPG就绪中断 MAX30102_WriteReg(REG_INTR_ENABLE_1, 0xC0); }

数据采集时需注意:

  • 通过中断方式读取FIFO数据更高效
  • 原始数据为18位(0x3FFFF为满量程)
  • 红光和红外光数据各占3字节
// FIFO数据读取示例 void MAX30102_ReadFIFO(uint32_t *pun_red_led, uint32_t *pun_ir_led) { uint8_t ach_i2c_data[6]; HAL_I2C_Mem_Read(&hi2c1, I2C_READ_ADDR, REG_FIFO_DATA, I2C_MEMADD_SIZE_8BIT, ach_i2c_data, 6, 100); *pun_red_led = ((ach_i2c_data[0]<<16) | (ach_i2c_data[1]<<8) | ach_i2c_data[2]) & 0x03FFFF; *pun_ir_led = ((ach_i2c_data[3]<<16) | (ach_i2c_data[4]<<8) | ach_i2c_data[5]) & 0x03FFFF; }

4. 心率血氧算法精解

核心算法流程可分为信号预处理、特征提取和参数计算三个阶段:

信号预处理流程:

  1. 直流分量去除:减去信号均值
  2. 移动平均滤波:4点窗口平滑
  3. 微分运算:获取信号变化率
  4. 汉明窗加权:增强周期特征
// 汉明窗应用代码实现 const uint16_t auw_hamm[5] = { 41, 276, 512, 276, 41 }; for(i=0; i<BUFFER_SIZE-HAMMING_SIZE; i++) { int32_t s = 0; for(k=0; k<HAMMING_SIZE; k++) { s -= an_dx[i+k] * auw_hamm[k]; } an_dx[i] = s / 1146; // 归一化 }

心率检测关键步骤:

  1. 通过find_peaks函数定位脉搏波峰
  2. 计算平均峰间期(RR间期)
  3. 心率(HR) = 60000 / RR间期(ms)

SpO2计算原理:

  1. 分别计算红光(R)和红外光(IR)的AC/DC比值
  2. 比值R = (Red_AC/Red_DC) / (IR_AC/IR_DC)
  3. 通过预校准查找表将R映射为SpO2值

实际应用中,手指的按压力度、环境温度等因素都会影响测量精度。建议在算法中加入运动伪差检测和信号质量评估模块。

5. 数据可视化实现

OLED显示需要优化信息布局以提升可读性:

void Display_Update(uint8_t hr, uint8_t spo2) { OLED_Clear(); // 心率显示区域 OLED_ShowCH(16, 0, "心率:"); OLED_ShowNum(56, 0, hr, 3, 16); OLED_ShowCH(88, 0, "BPM"); // 血氧显示区域 OLED_ShowCH(16, 2, "血氧:"); OLED_ShowNum(56, 2, spo2, 3, 16); OLED_ShowCH(88, 2, "%"); // 波形显示区域(简易版) static uint8_t wave_pos = 0; uint8_t y = 48 - (hr_history[wave_pos]/8); OLED_DrawPoint(wave_pos+32, y); wave_pos = (wave_pos+1)%64; }

对于更专业的数据分析,可以通过串口将原始数据发送到PC,使用Python进行可视化:

# Python串口数据接收示例 import serial import matplotlib.pyplot as plt ser = serial.Serial('COM3', 115200) data = [] for i in range(500): line = ser.readline().decode().strip() ir, red = map(int, line.split(',')) data.append((ir, red)) plt.plot([x[0] for x in data], label='IR') plt.plot([x[1] for x in data], label='Red') plt.legend() plt.show()

6. 项目优化与扩展

提升测量精度的实用技巧:

  • 在传感器表面添加柔光扩散层,改善光路均匀性
  • 采用滑动窗口均值滤波,实时更新基线
  • 添加用户接触检测,避免无效测量

蓝牙传输扩展方案:

  1. 选用HC-05模块(经典蓝牙)或HM-10(BLE)
  2. 修改串口波特率为9600以匹配模块
  3. 设计简单协议封装数据帧
// 蓝牙数据发送格式示例 void BT_SendData(uint8_t hr, uint8_t spo2) { uint8_t buffer[10]; sprintf((char*)buffer, "HR:%03d,O2:%03d\n", hr, spo2); HAL_UART_Transmit(&huart1, buffer, strlen((char*)buffer), 100); }

常见问题排查指南:

现象可能原因解决方案
数据全零I2C通信失败检查上拉电阻和地址(0xAE)
数值波动大接触不良使用绑带固定手指
SpO2显示--信号质量差保持静止15秒以上
心率检测延迟算法参数不当调整采样率为100Hz

完成基础功能后,可考虑添加这些进阶功能:

  • 历史数据存储(SD卡或Flash)
  • 异常心率警报功能
  • 低功耗模式设计(配合RTC唤醒)

这个项目最令人兴奋的部分是看到原始光信号经过处理转化为有意义的生理参数。在实际测试中,保持传感器与皮肤的稳定接触是获取准确数据的关键——有时简单的橡皮筋固定比昂贵的机械结构更有效。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/11 10:18:10

微信客户端远程控制工具包:MQTT桥接+本地部署+云微信联动

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;一套开箱即用的微信远程控制解决方案&#xff0c;通过MQTT协议实现外部系统与微信客户端的双向通信。支持发送消息、接收事件&#xff08;如文本、图片、链接&#xff09;、响应用户交互等核心能力。内置mqtt-g…

作者头像 李华
网站建设 2026/6/11 10:18:08

如何在PC上完美使用Switch控制器:BetterJoy全面解决方案

如何在PC上完美使用Switch控制器&#xff1a;BetterJoy全面解决方案 【免费下载链接】BetterJoy Allows the Nintendo Switch Pro Controller, Joycons and SNES controller to be used with CEMU, Citra, Dolphin, Yuzu and as generic XInput 项目地址: https://gitcode.co…

作者头像 李华
网站建设 2026/6/11 10:14:26

R语言一键计算动态分位数溢出指数:TVP-QVAR模型+DY热力图可视化

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;直接运行就能算出金融市场间实时风险传染强度的R工具包&#xff0c;基于时变参数分位数向量自回归&#xff08;TVP-QVAR&#xff09;模型&#xff0c;支持5%、50%、95%等分位点灵活设定。输入日频或高频资产价格…

作者头像 李华
网站建设 2026/6/11 10:13:19

深度解析MTKClient架构:3个实战场景应用指南

深度解析MTKClient架构&#xff1a;3个实战场景应用指南 【免费下载链接】mtkclient MTK reverse engineering and flash tool 项目地址: https://gitcode.com/gh_mirrors/mt/mtkclient MTKClient是一款专业的开源联发科设备底层操作工具&#xff0c;专为技术爱好者和专…

作者头像 李华
网站建设 2026/6/11 10:13:18

计算机毕业设计之django计算机网络题库平台设计与实现

近年来&#xff0c;科技飞速发展&#xff0c;在经济全球化的背景之下&#xff0c;大数据将进一步提高社会综合发展的效率和速度&#xff0c;大数据技术也会涉及到各个领域&#xff0c;而爬虫实现网站数据可视化在网站数据可视化背景下有着无法忽视的作用。管理信息系统的开发是…

作者头像 李华