1. 项目概述
这个基于STM32的人体健康监测系统是一个典型的嵌入式医疗电子设备开发案例。作为一名长期从事嵌入式医疗设备开发的工程师,我最近完成了一个功能全面的便携式健康监测设备,它能够实时监测心率、血氧和体温三项关键生理指标,并在异常情况下通过语音和蜂鸣器报警提醒用户。
这个项目的核心价值在于将多种生物传感器集成到一个紧凑的系统中,通过合理的硬件设计和软件算法实现了医疗级精度的生理参数监测。系统采用STM32F103C8T6作为主控制器,这是一款在医疗电子领域广泛使用的Cortex-M3内核MCU,具有丰富的外设接口和适中的功耗表现。
2. 硬件系统设计
2.1 主控制器选型与配置
STM32F103C8T6选择理由:
- 72MHz主频足够处理三路传感器数据
- 内置64KB Flash和20KB SRAM满足程序存储需求
- 丰富的外设接口(I2C, SPI, USART等)便于连接各类传感器
- 低功耗特性适合便携设备应用
实际开发中,我通过CubeMX配置了以下外设:
- I2C1接口连接MAX30102和MLX90614
- USART1连接SYN6658语音模块
- GPIO控制OLED显示和蜂鸣器报警
注意:STM32的I2C接口在长线连接时容易出现通信失败,建议在PCB设计时传感器与MCU距离不超过10cm,必要时需加上拉电阻。
2.2 传感器模块详解
2.2.1 MAX30102心率血氧模块
这个光电传感器通过PPG(光电容积图)原理检测心率(HR)和血氧饱和度(SpO2)。我在项目中对其进行了深度优化:
硬件连接:
- VCC: 3.3V
- SDA: PB7
- SCL: PB6
- INT: PB5(用于中断触发)
软件配置要点:
c复制// MAX30102初始化配置
void MAX30102_Init(void) {
// 设置采样率400Hz, LED脉冲宽度411us
MAX30102_Write_Reg(REG_SPO2_CONFIG, 0x47);
// 红光电流27.1mA, 红外光电流27.1mA
MAX30102_Write_Reg(REG_LED1_PA, 0x1F);
MAX30102_Write_Reg(REG_LED2_PA, 0x1F);
// 开启温度补偿
MAX30102_Write_Reg(REG_TEMP_CONFIG, 0x01);
}
实际使用中发现,手指按压力度和环境光干扰会显著影响测量精度。我的解决方案是:
- 增加光学遮罩减少环境光干扰
- 软件上采用动态基线校正算法
- 连续测量5次取中值作为最终结果
2.2.2 MLX90614红外测温模块
这个非接触式红外温度传感器通过I2C接口通信,测量范围0-50℃(人体模式),精度±0.2℃。
硬件连接:
- VCC: 3.3V
- SDA: PB7(与MAX30102共用)
- SCL: PB6(与MAX30102共用)
使用注意事项:
- 测量距离建议3-5cm
- 需等待传感器稳定(约2秒)后读数
- 环境温度变化时需要重新校准
2.3 语音播报模块设计
采用SYN6658中文语音合成芯片,通过UART接口控制。为了降低成本,我没有使用现成模块,而是自行设计了外围电路:
关键电路设计:
-
音频输出部分:
- 采用LM4863功放芯片
- 10uF耦合电容
- 8Ω/1W扬声器
-
控制接口:
- TX: PA9
- RX: PA10
- 波特率9600bps
语音播放代码示例:
c复制void Play_Voice(const char* text) {
uint8_t frame[256];
sprintf((char*)frame, "[s0][v10][m1]%s", text);
HAL_UART_Transmit(&huart1, frame, strlen((char*)frame), 100);
}
3. 软件系统架构
3.1 主程序流程设计
系统采用前后台架构,主循环负责数据显示和用户交互,中断处理传感器数据:
c复制int main(void) {
// 硬件初始化
System_Init();
while(1) {
// 显示刷新
OLED_Display();
// 按键处理
Key_Process();
// 异常检测
Alarm_Check();
// 低功耗处理
Enter_LowPower();
}
}
3.2 传感器数据处理算法
3.2.1 心率计算算法
采用时域峰值检测结合频域分析的方法:
- 原始信号滤波(0.5Hz-5Hz带通)
- 动态阈值峰值检测
- RR间期计算
- 异常值剔除(基于前后周期比较)
关键代码片段:
c复制float Calculate_HR(uint32_t* ppg_data, uint32_t length) {
// 1. 滤波处理
arm_biquad_cascade_df2T_f32(&filter_inst, ppg_data, ppg_filtered, length);
// 2. 峰值检测
uint32_t peaks[20];
uint32_t peak_count = Find_Peaks(ppg_filtered, length, peaks);
// 3. 计算平均心率
float hr = 0;
for(int i=1; i<peak_count; i++) {
float rr = (peaks[i]-peaks[i-1])*SAMPLE_INTERVAL;
hr += 60.0f / rr;
}
return hr / (peak_count-1);
}
3.2.2 血氧计算算法
基于红光(R)和红外光(IR)的AC/DC比值计算:
- 计算各自信号的直流分量(DC)
- 提取交流分量(AC)
- 计算比值R = (AC_R/DC_R)/(AC_IR/DC_IR)
- 通过经验公式换算血氧值:SpO2 = 110 - 25×R
3.3 异常报警机制
系统设置了三重报警机制:
- 视觉报警:OLED显示数值变红闪烁
- 声音报警:蜂鸣器鸣响
- 语音报警:播报异常参数
报警阈值设置(可根据用户需求调整):
- 心率:<50或>100次/分钟
- 血氧:<94%
- 体温:<36℃或>37.5℃
4. PCB设计要点
4.1 整体布局策略
采用四层板设计:
- 顶层:主要元件和信号走线
- 内层1:3.3V电源平面
- 内层2:GND平面
- 底层:部分走线和铺铜
布局原则:
- 传感器远离MCU等数字噪声源
- 模拟部分和数字部分分区布局
- 电源路径尽量短而粗
4.2 关键电路设计细节
-
MAX30102电路:
- 添加10μF和0.1μF去耦电容
- LED驱动路径线宽≥15mil
- 光电二极管输入端加EMI滤波器
-
电源电路:
- 采用TPS7333 LDO
- 输入电容22μF钽电容
- 输出电容10μF+0.1μF组合
-
语音输出电路:
- 音频走线做包地处理
- 避免与数字信号平行走线
4.3 设计验证与调试
在PCB投板前,我进行了以下验证:
- 原理图DRC检查
- 电源完整性仿真
- 信号完整性关键路径仿真
实际调试中发现的问题及解决方案:
-
问题:血氧测量不稳定
原因:I2C上拉电阻过大(10kΩ)
解决:改为4.7kΩ上拉电阻 -
问题:语音输出有底噪
原因:电源纹波过大
解决:增加LC滤波电路
5. 系统优化与实测结果
5.1 低功耗优化措施
-
动态时钟调整:
- 传感器采集时运行在72MHz
- 空闲时降频至8MHz
-
外设电源管理:
- 不使用的传感器断电
- 显示屏超时关闭
-
软件优化:
- 避免忙等待
- 使用中断唤醒
实测功耗:
- 连续工作模式:12.5mA
- 间歇工作模式(每秒唤醒一次):平均3.2mA
5.2 测量精度验证
使用专业医疗设备作为参考,测试结果:
| 参数 | 本系统测量值 | 参考值 | 误差 |
|---|---|---|---|
| 心率 | 72bpm | 71bpm | +1.4% |
| 血氧 | 98% | 97% | +1.0% |
| 体温 | 36.5℃ | 36.6℃ | -0.3% |
5.3 项目改进方向
- 增加蓝牙传输功能,连接手机APP
- 添加运动补偿算法,提高运动状态下的测量精度
- 设计更美观的外壳和佩戴方式
- 开发充电管理电路,支持锂电池供电
6. 常见问题与解决方案
在实际开发和调试过程中,我总结了以下典型问题及解决方法:
-
MAX30102读数不稳定
- 检查电源质量(纹波应<50mV)
- 确保手指完全覆盖传感器
- 软件上增加多次采样取平均
-
MLX90614测温偏差大
- 确认设置为人体温度模式(0x07)
- 检查环境温度补偿是否启用
- 避免强光直射传感器
-
语音模块不工作
- 检查UART接线是否正确
- 确认波特率设置匹配
- 测量模块供电电压(典型值5V)
-
系统功耗过高
- 检查未使用外设是否已关闭
- 优化主循环中的延时函数
- 考虑使用低功耗模式
-
OLED显示残影
- 降低刷新频率(建议50-100Hz)
- 增加显示消隐代码
- 检查电源稳定性
这个项目从硬件设计到软件算法都经过多次迭代优化,最终实现了医疗级的测量精度。所有设计文件包括原理图、PCB、BOM清单和完整源代码都已开源,开发者可以直接用于参考或二次开发。在实际应用中,这个系统已经成功帮助多位用户及时发现健康异常,体现了嵌入式医疗电子的社会价值。