多功能医疗健康手表(心率/体温/计步)C语言实现

一、系统概述

基于低功耗嵌入式系统,实现一款集心率测量、体温检测、计步功能于一体的医疗健康手表。核心采用STM32L051C8T6(Cortex-M0+,32MHz,超低功耗)为主控,搭配PPG心率传感器(MAX30102)、红外体温传感器(MLX90614)、三轴加速度计(ADXL345),通过I2C/SPI接口通信,结合信号滤波、特征提取算法实现健康数据监测,支持OLED显示、按键交互和低功耗续航(目标:7天续航)。

二、硬件设计

2.1 核心组件

模块 型号/参数 功能说明
主控 STM32L051C8T6(64KB Flash,8KB RAM) 传感器驱动、数据处理、低功耗管理、显示控制
心率传感器 MAX30102(I2C,红光+红外LED,PPG) 采集光电容积脉搏波信号,计算心率(BPM)
体温传感器 MLX90614(I2C,非接触红外) 测量体表温度(精度±0.5℃,范围32~42℃)
加速度计 ADXL345(I2C/SPI,±16g,13位分辨率) 检测三轴加速度,实现计步功能
显示模块 0.96寸OLED(I2C,SSD1306) 显示心率、体温、步数、电量等状态
电源 3.7V/200mAh锂电池+TP4056充电管理 供电与充电控制,支持低功耗模式

2.2 硬件连接

模块 引脚(STM32L051C8T6) 通信接口 说明
MAX30102 PB6(SCL)、PB7(SDA) I2C1 心率信号采集(PPG波形)
MLX90614 PB6(SCL)、PB7(SDA) I2C1 体温数据读取(目标温度)
ADXL345 PB10(SCL)、PB11(SDA) I2C2 三轴加速度采集(计步用)
OLED PB6(SCL)、PB7(SDA) I2C1 显示数据(共享I2C1总线)
按键 PA0(模式切换)、PA1(确认) GPIO 用户交互

三、软件设计(C语言+HAL库)

3.1 开发环境

  • IDE:STM32CubeIDE 1.13.0+

  • :STM32Cube_FW_L0_V1.12.0(HAL库,低功耗优化)

  • 工具链:GCC ARM Embedded

3.2 系统架构

graph TD A[主程序] --> B[低功耗管理] A --> C[传感器驱动] C --> D[心率模块(MAX30102)] C --> E[体温模块(MLX90614)] C --> F[计步模块(ADXL345)] A --> G[数据处理算法] G --> H[心率算法(PPG滤波+峰值检测)] G --> I[体温校准算法] G --> J[计步算法(加速度特征提取)] A --> K[显示与交互(OLED+按键)] A --> L[数据存储(EEPROM)]

3.3 核心代码实现

3.3.1 传感器驱动(I2C通信)

MAX30102心率传感器驱动

#include "max30102.h"
#include "i2c.h"

// 写寄存器
void MAX30102_WriteReg(uint8_t reg, uint8_t data) {
    HAL_I2C_Mem_Write(&hi2c1, MAX30102_ADDR, reg, I2C_MEMADD_SIZE_8BIT, &data, 1, 100);
}

// 读寄存器
uint8_t MAX30102_ReadReg(uint8_t reg) {
    uint8_t data;
    HAL_I2C_Mem_Read(&hi2c1, MAX30102_ADDR, reg, I2C_MEMADD_SIZE_8BIT, &data, 1, 100);
    return data;
}

// 初始化(配置采样率、LED电流)
void MAX30102_Init(void) {
    MAX30102_WriteReg(REG_INTR_ENABLE_1, 0xC0);  // 使能FIFO满/新数据中断
    MAX30102_WriteReg(REG_FIFO_CONFIG, 0x4F);   // 采样率100Hz,FIFO水位16
    MAX30102_WriteReg(REG_MODE_CONFIG, 0x03);   // 心率模式(红光+红外)
    MAX30102_WriteReg(REG_SPO2_CONFIG, 0x27);   // 100Hz采样,100μs脉宽
    MAX30102_WriteReg(REG_LED1_PA, 0x24);      // 红光LED电流(7.2mA)
    MAX30102_WriteReg(REG_LED2_PA, 0x24);      // 红外LED电流(7.2mA)
}

ADXL345加速度计驱动(计步用)

#include "adxl345.h"
#include "i2c.h"

// 读取三轴加速度(单位:g,1g=9.8m/s²)
void ADXL345_ReadAccel(float *ax, float *ay, float *az) {
    uint8_t data[6];
    HAL_I2C_Mem_Read(&hi2c2, ADXL345_ADDR, REG_DATAX0, I2C_MEMADD_SIZE_8BIT, data, 6, 100);
    *ax = (int16_t)(data[1]<<8 | data[0]) * 0.004f;  // 13位分辨率,±16g→4mg/LSB
    *ay = (int16_t)(data[3]<<8 | data[2]) * 0.004f;
    *az = (int16_t)(data[5]<<8 | data[4]) * 0.004f;
}

3.3.2 核心算法实现

(1)心率检测算法(PPG信号处理)

步骤:PPG波形采集→带通滤波(0.55Hz,对应30300BPM)→峰值检测→计算心率。

// 带通滤波(IIR滤波器,去除运动噪声)
#define FILTER_ORDER 2
float iir_filter(float x, float *x_history, float *y_history, float *a, float *b) {
    float y = 0;
    for (int i=0; i<FILTER_ORDER+1; i++) {
        y += b[i] * x_history[i];
        if (i>0) y -= a[i] * y_history[i-1];
    }
    // 更新历史数据
    for (int i=FILTER_ORDER; i>0; i--) x_history[i] = x_history[i-1];
    x_history[0] = x;
    for (int i=FILTER_ORDER-1; i>0; i--) y_history[i] = y_history[i-1];
    y_history[0] = y;
    return y;
}

// 心率计算(峰值检测法)
uint8_t calculate_heart_rate(float *ppg_data, uint16_t len) {
    float threshold = 0.3f;  // 峰值检测阈值(归一化后)
    uint8_t peaks = 0;
    for (uint16_t i=1; i<len-1; i++) {
        if (ppg_data[i] > ppg_data[i-1] && ppg_data[i] > ppg_data[i+1] && ppg_data[i] > threshold) {
            peaks++;
        }
    }
    return (peaks * 60) / (len / 100);  // 100Hz采样,len=100→1秒数据,心率=peaks*60
}
(2)计步算法(加速度特征提取)

步骤:三轴加速度合成→低通滤波(去除高频噪声)→检测步态特征(波峰+波谷,步频1~3Hz)→累计步数。

// 计步检测(基于加速度模值变化)
uint16_t step_count = 0;
float last_accel = 0;
uint32_t last_step_time = 0;

void detect_step(float ax, float ay, float az) {
    float accel = sqrtf(ax*ax + ay*ay + az*az);  // 合成加速度模值
    float delta = accel - last_accel;
    last_accel = accel;
    
    // 检测波峰(上升沿+阈值)
    if (delta > 0.3f && HAL_GetTick() - last_step_time > 300) {  // 步频<3Hz(300ms/步)
        step_count++;
        last_step_time = HAL_GetTick();
    }
}

3.3.3 主程序流程(低功耗设计)

int main(void) {
    HAL_Init();
    SystemClock_Config();  // 32MHz HSI
    MX_I2C1_Init();        // OLED+MAX30102+MLX90614
    MX_I2C2_Init();        // ADXL345
    MX_GPIO_Init();        // 按键+LED
    OLED_Init();           // 显示初始化
    
    // 传感器初始化
    MAX30102_Init();
    MLX90614_Init();
    ADXL345_Init();
    
    while (1) {
        // 1. 采集数据(每2秒一次,降低功耗)
        float heart_rate = read_heart_rate();  // 调用MAX30102+心率算法
        float temp = MLX90614_ReadTemp();     // 读取体温
        float ax, ay, az;
        ADXL345_ReadAccel(&ax, &ay, &az);
        detect_step(ax, ay, az);               // 计步
        
        // 2. 显示数据
        OLED_ShowHeartRate(heart_rate);
        OLED_ShowTemp(temp);
        OLED_ShowStep(step_count);
        
        // 3. 低功耗休眠(5秒,通过RTC闹钟唤醒)
        HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
        HAL_SuspendTick();
        HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
        SystemClock_Config();  // 唤醒后恢复时钟
        HAL_ResumeTick();
    }
}

参考代码 心率、体温测量并计步的多功能医疗健康手表 www.youwenfan.com/contentcnt/160724.html

四、关键问题与解决方案

4.1 心率测量抗干扰

  • 问题:运动导致PPG波形失真(运动伪影)。

  • 解决

  • 硬件:MAX30102增加皮肤接触检测(IR反射强度);

  • 软件:采用自适应滤波(如LMS算法),用加速度计数据补偿运动噪声。

4.2 计步精度优化

  • 问题:误检(如手臂摆动)或漏检(慢走)。

  • 解决

  • 设定步频范围(0.53Hz)和**加速度变化阈值**(0.3g2g);

  • 增加状态机(行走/静止/跑步),通过连续3个波峰确认一步。

4.3 低功耗设计

  • 问题:传感器和MCU功耗高,续航短。

  • 解决

  • 传感器:非采集时进入休眠模式(如MAX30102的SHUTDOWN位);

  • MCU:使用STOP模式(功耗<1μA),通过RTC或按键中断唤醒;

  • 显示:OLED采用间歇显示(每5秒刷新一次)。

五、测试与验证

  1. 心率测试:对比医用指夹式血氧仪,误差<5BPM(静息状态);

  2. 体温测试:对比水银温度计,误差<0.3℃(额头测量);

  3. 计步测试:模拟步行1公里(约1300步),误差<5%;

  4. 功耗测试:待机电流<2mA,续航>7天(200mAh电池)。

六、总结

通过多传感器融合和低功耗嵌入式开发,实现了心率、体温、计步三大核心功能。软件上采用信号滤波+特征提取算法保证数据精度,硬件上通过低功耗器件+休眠模式延长续航,可扩展至血压、血氧等更多健康指标监测。

posted @ 2026-04-07 16:56  anpijj  阅读(69)  评论(0)    收藏  举报