基于STM32的心率采集器设计

基于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 核心电路连接

2.2 抗干扰设计

三、软件设计与核心代码

1. 系统架构(FreeRTOS多任务调度)

采用FreeRTOS实时操作系统,划分6个核心任务(优先级从高到低):

  1. 传感器采集任务(优先级5):通过I2C/ADC读取生理信号,初步滤波后发送至队列。
  2. 信号处理任务(优先级4):带通滤波(0.5~3Hz)、基线漂移校正、运动伪影消除。
  3. 心率计算任务(优先级3):峰值检测、BPM计算、信号质量评估。
  4. 显示更新任务(优先级2):更新OLED显示(心率值、波形、电池电量)。
  5. 蓝牙传输任务(优先级2):打包数据并通过BLE发送至手机APP。
  6. 低功耗管理任务(优先级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. 心率算法优化

2. 低功耗设计

3. 用户体验优化

五、系统调试与扩展

1. 调试步骤

阶段 操作 工具
硬件调试 测量传感器供电(3.3V)、I2C信号质量 万用表、示波器(SCL/SDA波形)
信号测试 采集静息/运动状态下的原始信号,验证波形 串口打印数据,MATLAB/Python分析
算法验证 对比专业心率带,计算误差率(目标<±3BPM) 心率带、秒表计时验证
功耗测试 测量运行/待机/STOP模式下的电流 万用表(串联在电源回路)

2. 扩展功能

六、总结

基于STM32的心率采集器通过MAX30102光电传感器实现非侵入式监测,自适应滤波+峰值检测算法确保准确性,蓝牙BLE实现无线传输,超低功耗设计保障7天续航。

开发建议

  1. 优先调试MAX30102的I2C通信,确保原始信号稳定。
  2. 心率算法需大量临床数据验证,建议覆盖不同年龄、肤色、运动状态。
  3. 低功耗是穿戴设备的核心竞争力,需从硬件选型到软件策略全面优化。

专注于matlab/simulink,电子电路,编程