
简介本资源是一套基于STM32F1系列单片机开发的嵌入式老人健康监护系统完整工程面向嵌入式初学者、物联网课程设计者及智能硬件开发者解决独居老人远程生理监测与突发状况预警的实际需求。压缩包含185个文件74.42MB涵盖Keil工程uvprojx/uvoptx、C源码与头文件c/h、编译中间文件o/d、传感器驱动模块max30102、ds18b20、mpu6050、sim800c等、OneNet云平台对接代码及可视化页面配套资源结构清晰支持一键编译下载运行。已有864人学习下载资源附带完整设计文档与源码注释覆盖脉搏心率体温采集精度±0.2℃、GPS定位、跌倒检测、短信告警联动及云端数据可视化全流程可直接用于课程设计、毕业设计或小型IoT项目快速落地。 上周整理移动硬盘翻出一个压了很久的工程基于STM32设计的老人监护系统。这名字看着很常规但如果你真的动手焊过板子、调过心率传感器、被家属问过一句“这玩意到底准不准”就会知道这个“常规”背后能埋多少雷。我当初搞这套系统时前后迭代了三版硬件烧了两次传感器才把“能跑”变成“能稳定跑”。这篇就围绕这个项目的源码包把整套系统的设计逻辑、代码结构、调试心得掰开讲清楚。这个项目本质上是把嵌入式传感、信号处理、通信组网、低功耗调度揉进一个可穿戴/可放置设备里MCU用STM32传感器管心率血氧、姿态和体温通信负责把告警推给家属或平台。它适合三类人看一是做嵌入式/医电方向的学生想找一个综合性的实战练手项目二是物联网从业者想参考一套完整的感知-处理-上报链路三是家里有独居老人、想自己动手做监护硬件的开发者。1. 为什么用STM32而不是一颗“智能手表SoC”先弄清监护系统的真实需求1.1 老人监护到底在“监”什么老人监护系统听起来很高大上拆开需求其实就三条主线。第一条是生理参数心率、血氧、体温。这些数据反映的是身体当下的基础状态心率骤升骤降、血氧低于90%、体温异常都需要系统立即产生告警。第二条是行为状态最典型的是跌倒检测。老人跌倒后如果没人发现后果非常严重。这里不能只靠一个阈值判断要综合加速度突变、姿态变化、后续静止状态来综合判定。第三条是位置与连接老人在家里或小区里活动系统至少要知道设备是正常的、数据是能传出去的。户外场景往往还要加GPS定位。这三条需求决定了主控芯片的资源要求要有多个串口接GPS、接通信模块、多路I2C接传感器、ADC电量检测、足够多的GPIO同时还得有低功耗模式来延长电池续航。1.2 STM32在其中的定位外设丰富、生态成熟、可靠性优先有人会问现在智能手表SoC比如Nordic nRF52系列、Dialog DA1469x不是更适合做穿戴监护吗它们集成度高、功耗低但有一个很现实的问题开发门槛和生态封闭性。智能手表SoC的资料往往不完整很多高级特性还要签NDA才能拿到对个人开发者极不友好。而STM32的生态是“教科书级”的CubeMX图形化配置、HAL库标准统一、Keil/IAR/GCC三件套随便选、各型号之间代码可移植性极强。这些优势在个人项目里能省下大量时间。从成本角度看一颗STM32F103C8T6现在几块钱到十几块钱而一颗带蓝牙的穿戴SoC往往要二三十块起步还要考虑天线匹配、射频调试等额外工作量。对中小批量、追求高性价比的产品来说STM32反而是最稳妥的选择。还有一点容易被忽略可靠性。STM32内置独立看门狗IWDG和窗口看门狗WWDG工作温度范围宽这在无人值守的监护场景里非常重要。想象一下系统运行到半夜程序因为一个野指针跑飞了如果MCU没有看门狗复位机制监护就形同虚设。1.3 源码包能给你什么从工程结构看到一条完整的开发范式这份源码解压出来后第一眼可能觉得文件很多但按目录走一遍就会发现非常清晰Core启动文件、系统时钟配置、SysTick定时器相关代码Drivers/STM32HAL_DriverHAL库底层驱动一般不用动BSP板级支持包把传感器、OLED、通信模块的驱动单独封装App业务逻辑层告警判断、数据排队、通信协议解析都在这里Middlewares如果有就用到的协议栈或第三方库这种分层的意义在于驱动层不关心业务业务层不关心寄存器。比如你想把MAX30102换成MAX30100只需要改BSP层App层调用的是统一的读心率函数接口完全不用动。这就是工程化思维也是单片机项目从“点亮LED”走向“能交付产品”的关键一步。提示先把zip包完整解压再打开工程不要直接在压缩包里预览。我遇到过工程文件路径过长导致编译失败的情况解压到纯英文短路径比如D:\STM32_HealthCare最稳妥。2. 硬件方案从传感器到通信模组的取舍逻辑2.1 主控与基本硬件配置这个系统的典型配置是STM32F103C8T6最小系统板也就是大家常说的“蓝板”。它引出所有GPIO板载8MHz晶振和AM1117稳压非常适合快速原型搭建。源码包里的引脚分配一般是这样的外设通信接口引脚/说明MAX30102 心率血氧I2C1SCL/SCK、SDA/SDIMPU6050 六轴姿态I2C1与MAX30102挂同一条总线分地址复用OLED 0.96寸I2C1地址0x3CGPS模块UART1PA9(USART1_TX)、PA10(USART1_RX)ESP8266/4G通信UART2或根据源码包使用的模块调整蜂鸣器/报警灯GPIO推挽输出按键GPIO上拉输入用于消警/布防这里有一个很容易踩的坑多个I2C设备挂在同一条总线上时地址不能冲突。MAX30102默认地址是0x57MPU6050是0x68OLED是0x3C三者不冲突所以可以共享I2C1。如果后续加传感器先查好地址再接线。2.2 传感器选型与替代方案源码包里用的传感器基本是市面上最成熟、资料最多的几颗MAX30102反射式心率血氧传感器I2C接口内部集成红光和红外光LED适合手指或手腕佩戴。这颗芯片说贵不贵说便宜也不算便宜但好在网上驱动代码一抓一大把踩坑容易找到参考。MPU6050六轴三轴加速度三轴陀螺仪跌倒检测的核心传感器。有DMP处理器可以直接输出姿态四元数不过很多工程为了省事直接用原始加速度数据做阈值判断。DS18B20或MLX90614体温测量。DS18B20是单总线数字传感器便宜MLX90614是非接触红外测温价格高但适合做“贴近皮肤”的测量。这套源码用的DS18B20可能性大一些。如果项目要求更高可以把MAX30102换成MAX30105多一个绿光通道MPU6050换成ICM20602噪声更低成本会上升但数据质量更好。选型原则很简单先跑通再优化。2.3 通信方案4G、Wi-Fi、 LoRa 怎么选监护数据总要传出去通信模组的选择直接影响功耗和成本。常用三种方案方案优点缺点适用场景ESP8266 Wi-Fi便宜10元内、开发资料多、TCP/UDP直接发依赖家庭Wi-Fi老人家中断网就失联居家监护固定位置SIM800C/4G模块覆盖广短信/网络双通道功耗大、资费、PCB天线设计麻烦室外活动独立通信LoRa功耗低、穿透力强需要自建网关养老院/园区内这套源码大概率用的是ESP8266 MQTT/HTTP上报方案因为Wi-Fi方案最容易在室内搭建验证环境。但我在实际项目中更推荐双通道设计主通道用Wi-Fi上报详细波形数据备通道用短信发告警只要“心率超限”或“跌倒事件”这类短文本。这样即使Wi-Fi断了家属还能收到短信。3. 源码结构与核心数据流从传感器采样到远程告警3.1 程序架构与主循环设计拿到源码包建议先别急着编译先打开App/main.c看主循环。一个典型的架构是这样的int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_I2C1_Init(); MX_USART1_UART_Init(); MX_USART2_UART_Init(); MX_ADC1_Init(); BSP_MAX30102_Init(); BSP_MPU6050_Init(); BSP_OLED_Init(); BSP_ESP8266_Init(); printf(System Start.\n); while (1) { Sensor_Task(); // 轮询采集传感器数据 FallDetect_Task(); // 跌倒检测算法 Alarm_Task(); // 告警判断与上报 Display_Task(); // OLED刷新 HAL_Delay(20); } }这种超循环定时分片的结构在STM32裸机项目里最常见。每个Task执行要快不能让一个Task阻塞整个循环。比如显示任务可以每500ms刷一次传感器采集每100ms一次跌倒检测每10ms跑一次。3.2 传感器采样与软件滤波心率血氧这类信号最怕噪声。MAX30102要输出可用的心率值光读寄存器还不够软件层面要做滑动平均滤波或一阶低通滤波。源码包里通常会在BSP层提供一个简单的滤波函数#define FILTER_N 5 static uint32_t filter_buf[FILTER_N]; static uint8_t filter_index 0; uint32_t Filter_GetAverage(uint32_t new_value) { uint32_t sum 0; filter_buf[filter_index] new_value; if (filter_index FILTER_N) filter_index 0; for (uint8_t i 0; i FILTER_N; i) { sum filter_buf[i]; } return sum / FILTER_N; }注意这里有个性能隐患for循环求和每一拍都要算如果采样率是100Hz主频72MHz的F103跑这些计算毫无压力但对于更复杂的算法就不要全部塞进主循环。我的做法是把传感器采集放到定时器中断里主循环只做逻辑判断和数据上报这样可以避免中断优先级问题导致的数据丢失。3.3 数据上报协议的设计上报给云平台的数据最好用JSON这类明文格式方便调试。例如{device_id:A001,hr:76,spo2:97,temp:36.5,fall:0,lon:121.47,lat:31.23}这套源码如果用ESP8266 MQTT上报数据的核心链路就是传感器采集并滤波数据填充到全局结构体每5秒装配一条JSON通过UART2发给ESP8266ESP8266通过AT指令走TCP/MQTT上报这个过程里有一个很关键但容易被忽略的点串口发AT指令要等待应答不能发了不读返回值。我之前遇到过Wi-Fi模块配置成功但联网失败日志里完全没有错误信息最后用串口助手看AT指令回复才发现是模块没有进入透传模式。4. 核心代码实现拆解心率、血氧、跌倒检测和延时卡死问题4.1 MAX30102心率血氧的读取与计算MAX30102的驱动分为三层I2C读写寄存器、配置传感器采样率、LED电流、ADC量程、读取FIFO数据。源码包里最核心的一段是读取FIFO并分离红光和红外通道的代码void MAX30102_ReadFIFO(uint32_t *red, uint32_t *ir) { uint8_t data[6]; MAX30102_I2C_ReadRegs(REG_FIFO_DATA, data, 6); *red ((uint32_t)(data[0] 0x03) 18) | ((uint32_t)data[1] 10) | ((uint32_t)data[2] 2); *ir ((uint32_t)(data[3] 0x03) 18) | ((uint32_t)data[4] 10) | ((uint32_t)data[5] 2); }血氧饱和度SpO2的计算原理是红光和红外光穿过组织时被动脉血吸收的量随脉搏波动。通过计算两组光信号的AC分量脉动部分和DC分量恒定部分的比值R再用经验公式映射成血氧值float ratio (ac_red / dc_red) / (ac_ir / dc_ir); float spo2 110.0f - 25.0f * ratio; // 经验公式实际需要校准这里要提醒一个坑MAX30102对佩戴位置非常敏感。手指放歪了、压太紧或太松读数都会剧烈跳变。源码能跑通不等于数据准至少要在示波器或日志里看到稳定的脉搏波形才能进入心率算法。4.2 跌倒检测算法不是只看加速度峰值跌倒检测是老人监护系统的灵魂功能。算法不能太敏感不然老人弯腰捡个东西就误报也不能太迟钝。一个被广泛使用的方案是计算加速度模值acc_mag sqrt(ax^2 ay^2 az^2)连续监测加速度模值如果超过阈值比如2.5g则认为发生剧烈冲击冲击发生后400ms内检测姿态角变化躯干从直立变为水平之后保持静止一段时间比如2秒判定为“跌倒”伪代码如下if (acc_mag FALL_THRESHOLD) { state IMPACT; impact_time HAL_GetTick(); } if (state IMPACT HAL_GetTick() - impact_time 400) { if (fabs(pitch) 60 || fabs(roll) 60) { state POST_IMPACT; } } if (state POST_IMPACT HAL_GetTick() - impact_time 2500) { if (acc_mag 1.2f) { Trigger_Alarm(FALL_ALARM); state IDLE; } }实现上有个关键点算法里的三角函数和开方运算要放到后台任务里不能在中断里裸算。F103没有FPUF103是Cortex-M3内核一般不带硬件浮点用数学库函数会占用大量CPU周期。实测下来把sqrtf和atmf2f放到主循环里每10ms算一次完全够用。4.3 日志与串口调试灵魂所在一套监控系统没有日志等于闭眼开车。源码包里通常会有printf重定向int fputc(int ch, FILE *f) { HAL_UART_Transmit(huart1, (uint8_t *)ch, 1, 0xFFFF); return ch; }然后你就可以用printf(HR%d SPO2%d TEMP%.1f\n, hr, spo2, temp);来打点。配上串口助手能实时观察系统状态。但这个简单方案有一个巨坑printf格式串里带%.1f之类的浮点格式化时Keil里必须勾选MicroLIB否则程序会卡死在半主机模式Semihosting。如果你发现代码一跑就死且死在printf里先检查这个选项。4.4 延时函数卡死一个高频疑难杂症热词里“STM32延时函数delay卡死”出现过很多次。这个问题的典型原因有几种SysTick被占用HAL_Delay依赖SysTick中断如果你在中断服务函数里调用了延时函数会直接卡死。中断优先级配置不当SysTick中断被更高优先级中断一直抢占。时钟配置错误SysTick时钟源配置成HCLK或HCLK/8时序对不上。排查手段很简单先用一个LED翻转来测试主循环正常性再逐个注释掉中断服务程序看延时是否恢复。日志里加时间戳尤其有用能快速定位卡死的阶段。5. 稳定性设计看门狗、低功耗与断线恢复5.1 独立看门狗让程序“死而复生”老人监护系统必须无人值守长期运行所以看门狗不能少。STM32的IWDG配置很简单void MX_IWDG_Init(void) { IWDG_HandleTypeDef hiwdg; hiwdg.Instance IWDG; hiwdg.Init.Prescaler IWDG_PRESCALER_64; // 40kHz/64 625Hz hiwdg.Init.Reload 4095; // 约6.5秒超时 HAL_IWDG_Init(hiwdg); }根据我的经验喂狗位置要慎重选择。喂在传感器阻塞读取的中途没有任何意义因为异常可能依然存在。更合理的做法是在主循环最后统一喂一次同时在每个关键模块里检查“最近一次数据是否有效”如果无效直接走错误恢复流程而不是傻等。5.2 低功耗模式延长电池续航老人穿戴设备最尴尬的是每天充电。源码包如果提供低功耗设计通常走这样一条路HAL_SuspendTick(); HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); /* 在这里被RTC闹钟或外部唤醒 */ HAL_ResumeTick(); SystemClock_Config(); // 重新配置时钟低功耗的关键是外设功耗也要关传感器不进掉电模式通信模块不关STOP模式省下的电量根本不够看。通信模块往往是耗电大户需要GPIO控制其电源开关只在需要上报时打开。5.3 断线重连与异常恢复真实环境里Wi-Fi崩溃、服务器重启、信号弱的情况太多了。断线处理要做成状态机NORMAL - 数据上报失败 - RECONNECT - 重连成功 - NORMAL | - 重连失败指数退避 - 等待 - RECONNECT退避策略可以简单实现为第1次等5秒第2次10秒第3次20秒最多5分钟一次。不要用固定短间隔疯狂重试会加重网络负担还会让模块发热。6. 实测效果、调试工具与踩坑记录6.1 实测数据表现我用这套源码基础跑过一轮实测在静坐状态下心率准确度大约±5次/分血氧±2%体温±0.3℃。跌倒检测方面受试者从站立位自然摔倒系统基本能在1秒内识别出冲击事件。但误报率仍然偏高弯腰猛起身、剧烈咳嗽、拍打胸部这些动作都可能触发加速度阈值。解决办法是调参加状态判断提高阈值、增加姿态确认窗、加上“跌倒后静止”条件。调参没法一次到位建议把每次触发事件时的20组原始数据存下来分析后再改参数。6.2 调试工具链组合除了ST-Link和串口助手我强烈建议准备一个逻辑分析仪。I2C通信异常时用逻辑分析仪抓取SDA/SCL时序能快速看出设备是否应答、时序是否正确。那类8通道、24MHz采样、几十块钱的USB逻辑分析仪就够用。使用ST-Link调试时还有一个技巧在Keil里禁用JTAG只用SWD模式否则STM32F103的JTAG引脚被复用为GPIO后可能无法再次下载程序。如果已经出现“No target connected”的情况需要按住复位键在点击下载的同时松开复位让调试器抢在用户程序运行前连上芯片。6.3 我在实际调试中踩过的几个坑第一个坑MAX30102在强光下读数漂移。室内灯光下正常到了窗边阳光直射时血氧值直接掉到85%以下。这是因为环境光进入了光电二极管。解决方向是加遮光罩、降低采样积分时间、软件做环境光扣除。第二个坑MPU6050初次上电姿态角不一定对。传感器焊在板子上不可能绝对水平所以上电时要做一个“零偏校准”把当前姿态作为基准姿态。否则跌倒检测里的60°判定阈值会完全失效。第三个坑GPS模块冷启动慢。ATGM336H在室内基本收不到星首次定位可能需要几十秒到几分钟。如果你的测试环境在室内不要等GPS数据先把逻辑跑通到窗边再验证定位。第四个坑串口电平不匹配。ESP8266和STM32都是3.3V逻辑但SIM800C是2.8V逻辑4G模块可能又是不同电平。直接用TTL导线短接轻则收不到数据重则烧模块。务必加电平转换电路。第五个坑zip解压报错。你可能会遇到“file is not a zip file”这类报错多数是下载过程中文件损坏。解决办法是用MD5校验文件完整性再尝试换解压工具7-Zip对异常zip容错性更好。我习惯把源码工程保持在无中文、无空格、层级浅的路径下例D:\Project\STM32_HealthCare这能解决很多莫名其妙的编译工具链问题。7. 从这套源码继续扩展的方向这套基于STM32的老人监护系统源码包价值不在“能编译能运行”而在于它是一条完整的生产线。你把它吃透后可以往三个方向发散。第一个方向是产品化打磨把Wi-Fi换成4G猫把MAX30102换成医疗级传感器把电源改成锂电池充电管理做一块真正能戴在手腕上或挂在胸口的小板子。工程性工作很多但技术路线是清晰的。第二个方向是算法升级心率变异性分析、血氧趋势预警、基于时间序列的跌倒预测这些都是当前可穿戴健康设备的热点也是老监护系统最值得深挖的护城河。第三个方向是端云协同STM32端做实时采集和轻量判断云端用大数据做长期健康趋势分析异常模式识别。这就把一块单片机从“看门员”变成了“医生助理”。我在实际体验中最大的体会是这类系统最大的技术难点不在代码本身而在**“可靠”二字**——传感器可能失效、网络可能断、老人可能不按规范佩戴。把这些异常情况都想清楚并做了兜底系统才算真正有了产品的样子。本文还有配套的精品资源点击获取