基于STM32的心率采集器设计
一、系统概述与核心功能
1. 系统定位
基于STM32的心率采集器以“光电信号采集-生物电信号处理-心率算法-低功耗交互”为核心,实现非侵入式心率监测(PPG光电容积法或ECG心电信号法),支持实时显示、异常报警、数据存储与蓝牙传输,适用于个人健康管理、运动监测、医疗辅助等场景。
2. 核心功能模块
| 模块 | 功能描述 |
|---|---|
| 信号采集 | MAX30102(PPG光电传感器,红光/红外LED)或AD8232(ECG心电传感器),采集生理信号 |
| 信号处理 | 数字滤波(带通/陷波)、基线漂移校正、运动伪影消除、峰值检测 |
| 心率计算 | 实时计算BPM(Beats Per Minute),支持静息/运动模式自适应算法 |
| 数据显示 | OLED屏实时显示心率值、波形、电池电量,支持历史数据查看 |
| 数据传输 | 蓝牙BLE(CC2541/DA14531)传输至手机APP,支持云同步(可选Wi-Fi) |
| 用户交互 | 触摸按键(开始/停止/切换界面)、振动马达(异常心率报警)、LED状态指示 |
| 数据存储 | 存储24小时心率数据(时间戳+心率值),支持断点续传 |
| 低功耗设计 | 无操作时进入STOP模式,传感器间歇工作,续航≥7天(200mAh锂电池) |
二、硬件设计方案
1. 核心硬件选型
| 模块 | 型号 | 关键参数 | 接口方式 |
|---|---|---|---|
| 主控MCU | STM32L432KC | 80MHz Cortex-M4,超低功耗(运行<100μA/MHz),256KB Flash,支持USB和DFU升级 | 核心控制器 |
| 心率传感器 | MAX30102(PPG) | 集成红光(660nm)/红外(880nm)LED,16位ADC,I2C接口,支持心率+血氧检测 | I2C1(PB6=SCL,PB7=SDA) |
| 备用传感器 | AD8232(ECG) | 单导联心电,集成右腿驱动(RLD),输出模拟信号,需ADC采集 | ADC1_IN0(PA0) |
| 显示模块 | OLED 12864(I2C) | 0.96寸,128×64像素,自发光,低功耗(<10mA),支持图形显示 | I2C1(复用总线,地址0x3C) |
| 蓝牙模块 | DA14531(BLE5.1) | 超低功耗,传输距离30m,支持OTA升级,与手机APP通信 | UART1(PA9=TX,PA10=RX) |
| 存储模块 | AT24C256(EEPROM) | 256Kb(32KB),I2C接口,存储历史数据(时间+心率值) | I2C1(复用总线,地址0x50) |
| 交互模块 | 触摸按键×2+振动马达 | 触摸按键(CAP1188,低功耗),振动马达(心率异常报警) | I2C2(PC0-PC1)+ GPIO(PC2) |
| 电源模块 | 200mAh锂电池+TP4056 | 3.7V锂电池,TP4056充电(5V Micro USB),XC6206稳压至3.3V | 双电源供电(锂电池+USB) |
2. 硬件电路设计要点
2.1 核心电路连接
- STM32L432最小系统:8MHz外部晶振+32.768kHz RTC晶振(低功耗计时),SWD调试接口(PA13/PA14),复位电路(10kΩ上拉+0.1μF电容)。
- MAX30102传感器:VCC=3.3V,SCL=PB6,SDA=PB7(I2C1,4.7kΩ上拉电阻),INT引脚=PB0(中断输出,数据就绪)。
- AD8232心电传感器:VCC=3.3V,OUTPUT=PA0(ADC1_IN0),LOD=PB1(导联脱落检测),RLD=PB2(右腿驱动)。
2.2 抗干扰设计
- 传感器屏蔽:MAX30102加装黑色硅胶遮光罩,避免环境光干扰。
- 模拟地与数字地隔离:AD8232的AGND与STM32的DGND通过0Ω电阻单点连接。
- 电源滤波:传感器电源输入端并联10μF钽电容+0.1μF瓷片电容,滤除纹波。
三、软件设计与核心代码
1. 系统架构(FreeRTOS多任务调度)
采用FreeRTOS实时操作系统,划分6个核心任务(优先级从高到低):
- 传感器采集任务(优先级5):通过I2C/ADC读取生理信号,初步滤波后发送至队列。
- 信号处理任务(优先级4):带通滤波(0.5~3Hz)、基线漂移校正、运动伪影消除。
- 心率计算任务(优先级3):峰值检测、BPM计算、信号质量评估。
- 显示更新任务(优先级2):更新OLED显示(心率值、波形、电池电量)。
- 蓝牙传输任务(优先级2):打包数据并通过BLE发送至手机APP。
- 低功耗管理任务(优先级1):无操作超时检测,关闭外设,进入STOP模式。
2. 核心代码实现(基于HAL库)
2.1 MAX30102驱动(I2C通信)
#include "max30102.h"
#include "i2c.h"
// MAX30102寄存器地址
#define MAX30102_INT_STATUS 0x00
#define MAX30102_FIFO_WR_PTR 0x04
#define MAX30102_FIFO_DATA 0x07
#define MAX30102_MODE_CONFIG 0x09
#define MAX30102_SPO2_CONFIG 0x0A
#define MAX30102_LED_CONFIG 0x0C
// 初始化MAX30102
uint8_t MAX30102_Init(void) {
uint8_t part_id;
HAL_I2C_Mem_Read(&hi2c1, 0x57<<1, 0xFF, 1, &part_id, 1, 100);
if (part_id != 0x15) return 1; // 器件ID错误
// 配置SpO2模式,100Hz采样率,16位分辨率
MAX30102_WriteReg(MAX30102_MODE_CONFIG, 0x03); // SpO2模式
MAX30102_WriteReg(MAX30102_SPO2_CONFIG, 0x27); // 100Hz,411μs脉冲宽度
MAX30102_WriteReg(MAX30102_LED_CONFIG, 0x24); // 红光/红外LED电流7.6mA
return 0;
}
// 读取FIFO数据(红光+红外)
void MAX30102_ReadFIFO(uint32_t *red, uint32_t *ir) {
uint8_t fifo_data[6];
HAL_I2C_Mem_Read(&hi2c1, 0x57<<1, MAX30102_FIFO_DATA, 1, fifo_data, 6, 100);
*red = ((uint32_t)fifo_data[0] << 16) | ((uint32_t)fifo_data[1] << 8) | fifo_data[2];
*ir = ((uint32_t)fifo_data[3] << 16) | ((uint32_t)fifo_data[4] << 8) | fifo_data[5];
*red &= 0x3FFFFF; // 24位有效数据
*ir &= 0x3FFFFF;
}
2.2 心率计算算法(峰值检测)
#include "heart_rate.h"
// 心率上下文
typedef struct {
uint32_t buffer[100]; // 数据缓冲区
uint8_t idx; // 缓冲区索引
uint32_t last_peak_time; // 上次峰值时间(ms)
uint8_t peak_count; // 峰值计数
uint32_t hr_sum; // 心率总和
} HR_Context_t;
HR_Context_t hr_ctx;
// 带通滤波(0.5~3Hz,对应30~180BPM)
uint32_t BandPass_Filter(uint32_t input) {
static uint32_t prev_input = 0, prev_output = 0;
float alpha = 0.1; // 滤波系数
uint32_t output = alpha * input + (1 - alpha) * prev_output;
prev_input = input;
prev_output = output;
return output;
}
// 峰值检测
uint8_t Peak_Detect(uint32_t current, uint32_t threshold) {
static uint8_t peak_found = 0;
if (current > threshold && !peak_found) {
peak_found = 1;
return 1; // 检测到峰值
}
if (current < threshold * 0.8 && peak_found) {
peak_found = 0; // 峰值结束
}
return 0;
}
// 计算心率(BPM)
uint8_t Calculate_HeartRate(uint32_t red_value) {
uint32_t filtered = BandPass_Filter(red_value);
uint32_t threshold = filtered * 0.8; // 动态阈值
if (Peak_Detect(filtered, threshold)) {
uint32_t current_time = HAL_GetTick();
if (hr_ctx.last_peak_time != 0) {
uint32_t interval = current_time - hr_ctx.last_peak_time;
if (interval > 333 && interval < 2000) { // 30~180BPM
uint8_t hr = 60000 / interval;
hr_ctx.hr_sum += hr;
hr_ctx.peak_count++;
}
}
hr_ctx.last_peak_time = current_time;
}
if (hr_ctx.peak_count >= 5) { // 累计5个峰值计算平均
uint8_t avg_hr = hr_ctx.hr_sum / hr_ctx.peak_count;
hr_ctx.peak_count = 0;
hr_ctx.hr_sum = 0;
return avg_hr;
}
return 0; // 数据不足
}
2.3 蓝牙传输(BLE AT指令)
#include "ble.h"
// 初始化DA14531
void BLE_Init(void) {
char cmd[50];
sprintf(cmd, "AT+NAME=HR_Monitor\r\n");
HAL_UART_Transmit(&huart1, (uint8_t*)cmd, strlen(cmd), 100);
HAL_Delay(100);
sprintf(cmd, "AT+ADVINT=1600\r\n"); // 广播间隔1s
HAL_UART_Transmit(&huart1, (uint8_t*)cmd, strlen(cmd), 100);
HAL_Delay(100);
sprintf(cmd, "AT+START\r\n"); // 开始广播
HAL_UART_Transmit(&huart1, (uint8_t*)cmd, strlen(cmd), 100);
}
// 发送心率数据
void BLE_SendData(uint8_t hr, uint8_t spo2) {
char data[20];
sprintf(data, "{\"hr\":%d,\"spo2\":%d}", hr, spo2);
HAL_UART_Transmit(&huart1, (uint8_t*)data, strlen(data), 100);
}
2.4 主程序框架(FreeRTOS任务)
#include "stm32l4xx_hal.h"
#include "FreeRTOS.h"
#include "task.h"
int main(void) {
HAL_Init();
SystemClock_Config(); // 80MHz
// 初始化外设
MX_I2C1_Init(); // MAX30102/OLED/EEPROM
MX_USART1_UART_Init(); // BLE
MX_ADC1_Init(); // AD8232 ECG(可选)
// 初始化模块
MAX30102_Init();
OLED_Init();
BLE_Init();
// 创建任务
xTaskCreate(Sensor_Task, "Sensor", 256, NULL, 5, NULL);
xTaskCreate(HR_Calc_Task, "HR_Calc", 512, NULL, 4, NULL);
xTaskCreate(Display_Task, "Display", 256, NULL, 3, NULL);
xTaskCreate(BLE_Task, "BLE", 256, NULL, 2, NULL);
xTaskCreate(LowPower_Task, "LowPower", 128, NULL, 1, NULL);
vTaskStartScheduler();
while (1);
}
参考代码 基于STM32的心率采集器设计 www.youwenfan.com/contentcst/133636.html
四、关键技术与优化
1. 心率算法优化
- 自适应阈值:根据信号幅度动态调整峰值检测阈值,适应不同肤色/佩戴松紧度。
- 运动伪影消除:结合加速度传感器(可选)检测运动状态,运动时暂停心率计算或切换至ECG模式。
- 信号质量评估:计算信噪比(SNR),信号质量差时提示用户重新佩戴。
2. 低功耗设计
- 动态采样率:静止时50Hz采样,运动时100Hz采样,降低平均功耗。
- 中断唤醒:MAX30102数据就绪中断唤醒MCU,避免轮询功耗。
- 模块分时供电:OLED/蓝牙/振动马达不用时断电(通过MOS管控制)。
3. 用户体验优化
- 佩戴检测:通过红外LED反射值判断佩戴状态,未佩戴时停止测量。
- 异常报警:心率>120BPM或<50BPM时触发振动马达+屏幕闪烁。
- 数据同步:支持与手机APP同步历史数据,生成24小时趋势图。
五、系统调试与扩展
1. 调试步骤
| 阶段 | 操作 | 工具 |
|---|---|---|
| 硬件调试 | 测量传感器供电(3.3V)、I2C信号质量 | 万用表、示波器(SCL/SDA波形) |
| 信号测试 | 采集静息/运动状态下的原始信号,验证波形 | 串口打印数据,MATLAB/Python分析 |
| 算法验证 | 对比专业心率带,计算误差率(目标<±3BPM) | 心率带、秒表计时验证 |
| 功耗测试 | 测量运行/待机/STOP模式下的电流 | 万用表(串联在电源回路) |
2. 扩展功能
- 血氧监测:利用MAX30102的红光/红外比值计算SpO2(血氧饱和度)。
- 心电监测:集成AD8232实现单导联ECG,检测心律失常。
- 云同步:添加Wi-Fi模块(ESP8266),数据上传至云平台(如OneNET)。
- AI分析:通过机器学习算法识别异常心率模式(如房颤预警)。
六、总结
基于STM32的心率采集器通过MAX30102光电传感器实现非侵入式监测,自适应滤波+峰值检测算法确保准确性,蓝牙BLE实现无线传输,超低功耗设计保障7天续航。
开发建议:
- 优先调试MAX30102的I2C通信,确保原始信号稳定。
- 心率算法需大量临床数据验证,建议覆盖不同年龄、肤色、运动状态。
- 低功耗是穿戴设备的核心竞争力,需从硬件选型到软件策略全面优化。