【STM32项目开源】基于STM32的人体健康监测系统

目录

一、设计背景和意义

1.1设计背景

1.2设计意义

二、实物效果展示

2.1实物图片

2.2实物演示视频

三、硬件功能简介

3.1项目功能详解

3.2元器件清单

四、主框图与软件流程图

五、硬件PCB展示

六、软件程序设计

七、项目资料包内容

资料获取:查看主页介绍"充哥单片机设计"


一、设计背景和意义

1.1设计背景

随着医疗技术的进步与人均寿命的提高,全球人口老龄化问题日益严峻。据国家统计局数据显示,中国60岁及以上老年人口已接近3亿,占全国总人口的比重持续上升,预计在2035年前后将进入"深度老龄化"社会。在这一背景下,传统的家庭照护与机构养老服务日益显现出人力紧张、响应不及时、监护盲区等诸多现实问题,尤其是针对独居、高龄、慢性病患者等重点老年群体,其突发性健康事件(如高热、低血氧、心律异常、意外摔倒)极具风险,若未能及时发现与干预,极易造成严重后果。

1.2设计意义

本课题的研究不仅具有突出的技术整合与工程实现价值,更体现了信息技术在社会民生领域的广泛应用前景。通过构建低成本、可部署、功能完备的养老监护系统,不仅能够有效填补传统养老方式在安全监护方面的不足,还可为社区居家养老、智慧医疗、远程健康管理等更广泛的应用场景提供技术支撑,具有较高的社会价值与推广潜力。

二、实物效果展示

2.1实物图片

2.2实物演示视频

【开源】基于STM32的人体健康监测系统

三、硬件功能简介

3.1项目功能详解

1.传感器检测:检测体温、心率、血氧等健康相关数据

2.跌倒检测:ADXL345检测是否跌倒

3.GPS定位:实时检测定位坐标的经纬度数据

4.数据显示:0.96OLED屏幕显示全部的传感器数据以及传感器的阈值等数据

5.App远程监控:通过蓝牙模块连接App远程监控全部传感器数据

6.阈值数据设定:系统通过按键设定阈值

7.报警:检测到体温超过阈值、心率超过阈值、血氧低于阈值会开启或检测到摔倒蜂鸣器报警

3.2元器件清单

  1. 主控STM32F103C8T6最小系统板
  2. 0.96OLED显示屏幕
  3. ESP8266联网WIFI(ESP01S)
  4. DS18B20温度传感器
  5. MAX30102心率血氧传感器
  6. ADXL345三轴加速度传感器
  7. GPS定位模块
  8. 按键

四、主框图与软件流程图

主框图

流程图

五、硬件PCB展示

六、软件程序设计

cpp 复制代码
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "string.h"
#include "max30102.h"
#include "ds18b20.h"
#include "beep.h"
#include "key.h"
#include "timer.h"
#include "oled.h"
#include "adxl345.h"
#include "iic.h"
 
double lat_minutes = 32.138118;
double lon_minutes = 116.447290;
 
#define GPS_STR_LEN 48
 
unsigned char display[16];
 
/****  数据变量  ****/
 
int temp_door = 38;
int oxy_door = 90;
int heart_door = 100;
 
uint8_t send_time = 3;
uint8_t printd_flag = 0;
 
float adx,ady,adz;
float acc,acc2;
uint8_t tiltFlag = 0;
uint8_t fallTime = 0;
 
/****  菜单变量  ****/
uint8_t option = 0;			//阈值选项
uint8_t key_num = 0;		//按键赋值
uint8_t page_id = 1;		//页面ID
 
/****  功能函数声明  ****/
void oled_show_onepage();		//第一屏显示内容
void oled_show_twopage();	//第二屏显示内容
 
void get_all_sensor_data();		//传感器数据采集
void Sensor_Data_Handle();		//不同模式下控制效果
void FallDetection(void);		//摔倒检测
 
int main(void)
{
	delay_init();			//系统延时函数初始化
	OLED_Init();		 	//OLED初始化
	uart2_init(9600);		//串口2初始化,波特率9600
	USART1_Config();		//串口1初始化,波特率9600
	uart3_init(9600);		//串口3初始化,波特率9600
	DS18B20_Init();			//DS18B20温度检测初始化
	MAX30102_Init();		//心率血氧检测初始化
	un_min=0x3FFFF;
	un_max=0;
	Max30102_right_data();
	BEEP_Init();			//蜂鸣器初始化
	beep = 0;
	KEY_Init();				//按键初始化	
 	IIC_init();				//ADXL345摔倒检测初始化
	adxl345_init();	 
	TIME_Config();			//定时器初始化
	while(1)
	{
		get_all_sensor_data();		//传感器数据采集
		if(Time_Period[1]>1000)		//Time_Period[1] 在定时器中累加
		{
			Time_Period[1] = 0;
			if(page_id == 1){			//屏幕更新
				oled_show_onepage();
			}else if(page_id == 2){
				oled_show_twopage();
			}
			if(tiltFlag==1){		//摔倒后,每隔一段时间进行语音播报提醒
				send_time++;
				if(send_time>=5){
					send_time=0;
					BY_U2_SendBuff(sound_buf,7);
				}
			}
			printd_flag = !printd_flag;
			if(printd_flag==1){		//蓝牙消息发送
				printf("\r\n\r\n\r\n\r\n");	
				printf("*********************\r\n");
				printf("心率:%d次/分钟 血氧:%d%%\r\n",dis_hr,dis_spo2);
				printf("体温:%d℃\r\n",body_temp);
				if(tiltFlag==1)printf("老人摔倒\r\n");
				else printf("活动正常\r\n");
				printf("经度:%10.6f\r\n",lon_minutes);
				printf("纬度:%10.6f\r\n",lat_minutes);
				printf("*********************\r\n");
			}				
		}
		Sensor_Data_Handle();		//数据处理
	}
}
 
void Sensor_Data_Handle()
{
	//体温超过阈值 或 心率超过阈值 或 血氧低于阈值且大于0,蜂鸣器报警提醒
	if(body_temp>temp_door||dis_hr>heart_door||(dis_spo2<oxy_door&&dis_spo2>0)||tiltFlag==1)beep=1;
	else beep=0;
}
void get_all_sensor_data()		//获取数据
{
	body_temp = DS18B20_Get_Temp();		//获取DS18B20体温数据
	Get_Max30102_Data();				//获取心率血氧数据
	FallDetection();					//摔倒检测
 
}
// 心(0) 率(1) 血(2) 氧(3) 体(4) 温(5) ℃(6) 宠(7) 物(8) 状(9) 态(10) 正(11) 常(12) 经(13) 纬(14) 度(15) 阈(16) 值(17)
// 活(18) 动(19) 老(20) 人(21) 摔(22) 倒(23)
void oled_show_onepage(){
	
	OLED_ShowChinese(16*0,0,0,16,1);			//心
	OLED_ShowChinese(16*1,0,1,16,1);			//率
	OLED_ShowChar(16*2,0,':',16,1);
	OLED_ShowNum(16*2+8,0,dis_hr,3,16,1);		//心率数据
	
	OLED_ShowChinese(16*4,0,2,16,1);			//血
	OLED_ShowChinese(16*5,0,3,16,1);			//氧
	OLED_ShowChar(16*6,0,':',16,1);
	OLED_ShowNum(16*6+8,0,dis_spo2,3,16,1);		//血氧数据
 
	OLED_ShowChinese(16*0,16,4,16,1);			//体
	OLED_ShowChinese(16*1,16,5,16,1);			//温
	OLED_ShowChar(16*2,16,':',16,1);
	OLED_ShowNum(16*2+8,16,body_temp,2,16,1);	//体温数据
	
	if(tiltFlag==1){
		OLED_ShowChinese(16*4,16,20,16,1);
		OLED_ShowChinese(16*5,16,21,16,1);
		OLED_ShowChinese(16*6,16,22,16,1);
		OLED_ShowChinese(16*7,16,23,16,1);
	}else {
		OLED_ShowChinese(16*4,16,18,16,1);
		OLED_ShowChinese(16*5,16,19,16,1);
		OLED_ShowChinese(16*6,16,11,16,1);
		OLED_ShowChinese(16*7,16,12,16,1);		
	}
 
	sprintf((char *)display,"%10.6f ",lon_minutes);
	OLED_ShowChinese(16*0,32,13,16,1);			//经
	OLED_ShowChinese(16*1,32,15,16,1);			//度
	OLED_ShowChar(16*2,32,':',16,1);
	OLED_ShowString(16*3,32,(u8*)display,16, 1);//显示经度
 
	sprintf((char *)display,"%10.6f ",lat_minutes);
	OLED_ShowChinese(16*0,48,14,16,1);			//纬
	OLED_ShowChinese(16*1,48,15,16,1);			//度
	OLED_ShowChar(16*2,48,':',16,1);
	OLED_ShowString(16*3,48,(u8*)display,16, 1);//显示纬度
	
	OLED_Refresh();
}
 
void oled_show_twopage(){
	
	uint8_t a,b,c,d;
	if(option==1){a=0;b=1;c=1;d=1;}
	else if(option==2){a=1;b=0;c=1;d=1;}
	else if(option==3){a=1;b=1;c=0;d=1;}
	else {a=1;b=1;c=1;d=1;}
	
	OLED_ShowChinese(16*0,0,0,16,1);			//	"心"
	OLED_ShowChinese(16*1,0,1,16,1);			//	"率"
	OLED_ShowChinese(16*2,0,16,16,1);			//	"阈"
	OLED_ShowChinese(16*3,0,17,16,1);			//	"值"
	OLED_ShowChar(16*4,0,':',16,1);				//	":"
	OLED_ShowNum(16*4+8,0,heart_door,3,16,a);		//	heart_door
	
	OLED_ShowChinese(16*0,16,2,16,1);			//	"血"
	OLED_ShowChinese(16*1,16,3,16,1);		  	//	"氧"
	OLED_ShowChinese(16*2,16,16,16,1);			//	"阈"
	OLED_ShowChinese(16*3,16,17,16,1);			//	"值"
	OLED_ShowChar(16*4,16,':',16,1);			//	":"
	OLED_ShowNum(16*4+8,16,oxy_door,3,16,b);		//	oxy_door
 
	
	OLED_ShowChinese(16*0,32,4,16,1);		//	"体"
	OLED_ShowChinese(16*1,32,5,16,1);		//	"温"
	OLED_ShowChinese(16*2,32,16,16,1);		//	"阈"
	OLED_ShowChinese(16*3,32,17,16,1);		//	"值"
	OLED_ShowChar(16*4,32,':',16,1);			//	":"
	OLED_ShowNum(16*4+8,32,temp_door,3,16,c);		//	temp_door
 
	
	OLED_Refresh();
}
 
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)  //检测更新中断是否发生
	{
	key_num = KEY_Scan(0);		//按键扫描赋值
	switch(key_num)
	{
		case 1:		//按键1按下
			if(page_id==1){
				page_id=2;
				OLED_Clear();oled_show_twopage();
			}else if(page_id==2){
				option++;
				if(option>3){
					option=0;
					page_id=1;
					OLED_Clear();oled_show_onepage();
				}else oled_show_twopage();
			}
			break;
		case 2:		//按键2按下
			if(page_id==2){
				if(option==1)heart_door+=1;
				else if(option==2)oxy_door+=1;
				else if(option==3)temp_door+=1;
				oled_show_twopage();
			}
			break;
		case 3:		//按键3按下
			if(page_id==2){
				if(option==1)heart_door-=1;
				else if(option==2)oxy_door-=1;
				else if(option==3)temp_door-=1;
				oled_show_twopage();
			}
			break;
		case 4:		//按键4按下
//			BY_U2_SendBuff(sound_buf,7);
			lanya_flag = 0;
			break;
 
	}
		
		Time_Period[0]++;
		Time_Period[1]++;
		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清楚更新中断标志位,如果不清除,会一直进中断
	}
}
 
void FallDetection(void)//倾斜检测
{
	  u8 i;
	  adxl345_read_average(&adx,&ady,&adz,10);//获取数据
		acc=ady;
	  acc2=adx;
		if(acc<0)acc=-acc;
    if(acc2<0)acc2=-acc2;
		if(((u16)acc)>=190 || ((u16)acc2)>=190)//检测到倾斜
		{
			tiltFlag=1;
		}else{
			tiltFlag=0;
		}
		
}

七、项目资料包内容

资料获取:查看主页介绍"充哥单片机设计"

相关推荐
来自晴朗的明天42 分钟前
16、电压跟随器(缓冲器)电路
单片机·嵌入式硬件·硬件工程
钰珠AIOT1 小时前
在同一块电路板上同时存在 0805 0603 不同的封装有什么利弊?
嵌入式硬件
代码游侠1 小时前
复习——Linux设备驱动开发笔记
linux·arm开发·驱动开发·笔记·嵌入式硬件·架构
代码游侠12 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
xuxg200514 小时前
4G 模组 AT 命令解析框架课程正式发布
stm32·嵌入式·at命令解析框架
CODECOLLECT16 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen16 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制
全栈游侠19 小时前
STM32F103XX 02-电源与备份寄存器
stm32·单片机·嵌入式硬件
Lsir10110_19 小时前
【Linux】中断 —— 操作系统的运行基石
linux·运维·嵌入式硬件
深圳市九鼎创展科技21 小时前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算