目录

一、设计背景和意义

1.1设计背景

1.2设计意义

二、实物效果展示

2.1实物图片

2.2实物演示视频

三、硬件功能简介

3.1项目功能详解

3.2元器件清单

四、主框图与软件流程图

五、硬件PCB展示

六、软件程序设计

七、项目资料包内容

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


一、设计背景和意义

1.1设计背景

        随着人口老龄化趋势的加剧和慢性疾病发病率的持续上升,公共健康问题正日益成为全球关注的焦点。尤其是在后疫情时代背景下,人们对自身健康状况的关注空前提高,健康监测由传统的医院集中式、被动式管理逐步向个体化、实时化、自主化的方向转变。在此背景下,可穿戴健康监测设备逐渐走入大众生活,其中以智能手环为代表的产品,因其便携性强、功能多样、易于操作等特点,成为智慧医疗与移动健康(Mobile Health, mHealth)领域的重要应用载体。

        智能手环不仅能够帮助用户实时监测诸如心率、血氧、体温、运动步数等关键健康参数,还可以作为慢性病患者自我管理的辅助工具,对疾病的早期预警、恢复期观察及健康行为干预具有积极意义。相比于传统检测方式,基于可穿戴技术的连续动态监测手段能够提供更加全面、连续的生理信息,从而提升疾病风险评估的准确性和响应时效性。

1.2设计意义

        开展一项以STM32嵌入式系统为核心控制平台的“智能心率血氧手环系统”课题研究,不仅具有明显的工程实践价值,也在理论探索层面具有积极意义。该课题融合了多种生理信号采集技术(如光电容积脉搏波检测、数字温度采样、三轴加速度采集等)、低功耗嵌入式系统设计技术以及无线通信技术,旨在构建一个集多参数监测、数据融合处理、运动状态判断、健康阈值预警与APP交互于一体的便携式健康监测系统,提升用户自我健康管理的能力。

        通过本课题的研究,将有助于推动智能穿戴设备向高集成度、智能化、个性化方向发展,也为今后在智慧医疗、康复辅助、老年人看护、运动健康等领域的深入研究和实际部署提供可行的技术方案与平台支持。此外,本项目还能够锻炼学生在传感器应用、嵌入式开发、模块集成、电路设计、蓝牙通信和系统调试等方面的综合工程能力,为后续从事智能硬件或医疗设备开发奠定坚实基础。

二、实物效果展示

2.1实物图片

2.2实物演示视频

【开源】基于STM32的智能心率血氧运动手环

三、硬件功能简介

3.1项目功能详解

  1. DS1302时钟模块显示当前的时间实现掉电保存。
  2. MAX30102采集心率血氧数据
  3. ADXL345三轴加速度传感器通过算法实现运动步数的计数
  4. DS18B20采集体温数据
  5. GPS模块获取经纬度坐标
  6. 数据显示:0.96OLED屏幕显示当前的时间、体温、心率、血氧数据
  7. 阈值设置:可以按键设置心率、血氧、体温的阈值上下限
  8. 声光报警:当心率、血氧、体温数据不在阈值范围内,将会启动声光报警。
  9. 可设定运动时间,运动里程开始运动
  10. 蓝牙App:系统可以链接蓝牙app,app远程获取全部的传感器数据并可以设定修改阈值。

3.2元器件清单

  1. 主控STM32F103C8T6最小系统板
  2. 0.96 OLED显示屏幕
  3. JDY31-SPP蓝牙模块
  4. DS1302时钟模块
  5. GPS模块
  6. MAX30102心率血氧传感器
  7. ADXL345三轴加速度传感器
  8. DS18B20温度传感器
  9. 按键部分

四、主框图与软件流程图

主框图

流程图

五、硬件PCB展示

六、软件程序设计

#include "stm32f10x.h"
#include "OLED_I2C.h"
#include "ds1302.h"
#include "ds18b20.h"
#include "usart1.h"
#include "usart2.h"
#include "led.h"
#include "delay.h"
#include "myiic.h"
#include "key.h"
#include "iic.h"
#include "stdio.h"
#include "string.h"
#include "adxl345.h"
#include "timer.h"
#include "stmflash.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "GPS.h"
#include "wgbd.h"
#include "mmaaxx30102.h"

unsigned char setn=0;
unsigned char  p_r=0;		 						//平年/润年  =0表示平年,=1表示润年
float adx,ady,adz;
float acc;
float acc2,acc3;
u8 flag=0;
int bushu=0;
int mileage=0;//里程
int mileage_bushu = 0;//里程的步数
int bu_long = 40;//步长
long warnMileage=1000;//提醒里程
short temperature=0;
int xinlvMin=60,xinlvMax=120;//心率下限上限
int spo2Min=80;//血氧下限
int tempMax=373;//温度上限
int tempMin=150;//温度下限
char display[16];
char buf[200] = {0};
u8 shanshuo=0;
u8 beepFlag=0x00; //蜂鸣器报警标志
u8 page = 0;      //页面切换变量
/*定时时间*/
long timeCountRecord=0;
int shi=1,fen=0,miao=0;
bool startFlag=0;        //开始定时标志
bool timingReminder=0;   //定时时间提醒标志
bool mileageReminder=0;  //里程提醒标志
uint8_t tiltFlag = 0;
u8 sendFlag = 1;
bool sendSetValueFlag=0;

int32_t hrAvg;//心率
int32_t spo2Avg;//血氧浓度

void DisplayTime(void)//显示时间函数
{
	unsigned char i=0,x=0;
	u16 nian_temp;

	if(setn==0)DS1302_DateRead(&SysDate);//读时间
	nian_temp=2000+SysDate.year;
	if((nian_temp%400==0)||((nian_temp%100!=0)&&(nian_temp%4==0)))  //判断是否为闰年
		p_r=1;
	else
		p_r=0;
	if(setn<8 && page==0)
	{
		OLED_ShowChar((x++)*8,0,'2',2,setn+1-1);
		OLED_ShowChar((x++)*8,0,'0',2,setn+1-1);
		OLED_ShowChar((x++)*8,0,SysDate.year/10+'0',2,setn+1-1);
		OLED_ShowChar((x++)*8,0,SysDate.year%10+'0',2,setn+1-1);
		OLED_ShowChar((x++)*8,0,'-',2,0);
		OLED_ShowChar((x++)*8,0,SysDate.mon/10+'0',2,setn+1-2);
		OLED_ShowChar((x++)*8,0,SysDate.mon%10+'0',2,setn+1-2);
		OLED_ShowChar((x++)*8,0,'-',2,0);
		OLED_ShowChar((x++)*8,0,SysDate.day/10+'0',2,setn+1-3);
		OLED_ShowChar((x++)*8,0,SysDate.day%10+'0',2,setn+1-3);
		OLED_ShowCN(i*16+88,0,0,setn+1-4);//测试显示中文:周
		switch(SysDate.week)
		{
			case 1: OLED_ShowCN(i*16+104,0,1,setn+1-4);//测试显示中文:一
				break;
			case 2: OLED_ShowCN(i*16+104,0,2,setn+1-4);//测试显示中文:二
				break;
			case 3: OLED_ShowCN(i*16+104,0,3,setn+1-4);//测试显示中文:三
				break;
			case 4: OLED_ShowCN(i*16+104,0,4,setn+1-4);//测试显示中文:四
				break;
			case 5: OLED_ShowCN(i*16+104,0,i+5,setn+1-4);//测试显示中文:五
				break;
			case 6: OLED_ShowCN(i*16+104,0,6,setn+1-4);//测试显示中文:六
				break;
			case 7: OLED_ShowCN(i*16+104,0,7,setn+1-4);//测试显示中文:日
				break;
		}
		x=0;
		OLED_ShowChar((x++)*8,2,SysDate.hour/10+'0',2,setn+1-5);
		OLED_ShowChar((x++)*8,2,SysDate.hour%10+'0',2,setn+1-5);
		OLED_ShowChar((x++)*8,2,':',2,0);
		OLED_ShowChar((x++)*8,2,SysDate.min/10+'0',2,setn+1-6);
		OLED_ShowChar((x++)*8,2,SysDate.min%10+'0',2,setn+1-6);
		OLED_ShowChar((x++)*8,2,':',2,0);
		OLED_ShowChar((x++)*8,2,SysDate.sec/10+'0',2,setn+1-7);
		OLED_ShowChar((x++)*8,2,SysDate.sec%10+'0',2,setn+1-7);
	}
}

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)>=220 || ((u16)acc2)>=220)//检测到倾斜
	{
		BEEP=1;
		tiltFlag=1;
	}else{
		BEEP=0;
		tiltFlag=0;
	}
}

void GetHeartRateSpO2(void)
{
	unsigned char x=0;
	if(page==0)
	{
		Get_Max30102_Data();
		//显示相关的信息
		OLED_ShowChar((x++)*8,6,dis_hr%1000/100+'0',2,0);
		OLED_ShowChar((x++)*8,6,dis_hr%100/10+'0',2,0);
		OLED_ShowChar((x++)*8,6,dis_hr%10+'0',2,0);

		x=6;
		//显示相关的信息
		OLED_ShowChar((x++)*8,6,dis_spo2%1000/100+'0',2,0);
		OLED_ShowChar((x++)*8,6,dis_spo2%100/10+'0',2,0);
		OLED_ShowChar((x++)*8,6,dis_spo2%10+'0',2,0);
	}
}

void DisplayTemperature(void)//显示温度函数
{
	unsigned char x=10;//显示的第几个字符
	temperature=DS18B20_Get_Temp();
	if(page==0)
	{
		OLED_ShowChar((x++)*8,2,temperature/100+'0',2,0);
		OLED_ShowChar((x++)*8,2,temperature%100/10+'0',2,0);
		OLED_ShowChar((x++)*8,2,'.',2,0);
		OLED_ShowChar((x++)*8,2,temperature%10+'0',2,0);
	}
}

void GetSteps(void)//获取步数,里程,经纬度函数
{
	static u16 temp=0;
	float tempMileage=0.0;
	u16 x=11; 
	
	adxl345_read_average(&adx,&ady,&adz,10);//获取数据
	acc=ady;
	acc3=adx;
	if(acc>0)//在正轴
	{
		if(acc/10>=10)//加速度值,在正轴值是否大于10,则视为一个周期完成,步数加1
		{
			flag=0;	
			if(bushu<60000)bushu++;	//步数加1
			if(mileage_bushu<60000)mileage_bushu++;	//步数加1
			if(temp!=bushu)//当步数发生变化才去存储步数
			{
				temp=bushu;
				Store_Data(); //存储步数
			}
		}
	}
	if(page==0)
	{
		if(bushu>9999){
			OLED_ShowChar((x++)*8,6,bushu/10000+'0',2,0);
			OLED_ShowChar((x++)*8,6,bushu%10000/1000+'0',2,0);
			OLED_ShowChar((x++)*8,6,bushu%1000/100+'0',2,0);
			OLED_ShowChar((x++)*8,6,bushu%100/10+'0',2,0);
			OLED_ShowChar((x++)*8,6,bushu%10+'0',2,0);
		}else if(bushu>999){
			OLED_ShowChar((x++)*8,6,' ',2,0);
			OLED_ShowChar((x++)*8,6,bushu%10000/1000+'0',2,0);
			OLED_ShowChar((x++)*8,6,bushu%1000/100+'0',2,0);
			OLED_ShowChar((x++)*8,6,bushu%100/10+'0',2,0);
			OLED_ShowChar((x++)*8,6,bushu%10+'0',2,0);
		}else if(bushu>99){
			OLED_ShowChar((x++)*8,6,' ',2,0);
			OLED_ShowChar((x++)*8,6,' ',2,0);
			OLED_ShowChar((x++)*8,6,bushu%1000/100+'0',2,0);
			OLED_ShowChar((x++)*8,6,bushu%100/10+'0',2,0);
			OLED_ShowChar((x++)*8,6,bushu%10+'0',2,0);
		}else if(bushu>9){
			OLED_ShowChar((x++)*8,6,' ',2,0);
			OLED_ShowChar((x++)*8,6,' ',2,0);
			OLED_ShowChar((x++)*8,6,bushu%100/10+'0',2,0);
			OLED_ShowChar((x++)*8,6,bushu%10+'0',2,0);
			OLED_ShowChar((x++)*8,6,' ',2,0);
		}else{
			OLED_ShowChar((x++)*8,6,' ',2,0);
			OLED_ShowChar((x++)*8,6,' ',2,0);
			OLED_ShowChar((x++)*8,6,bushu%10+'0',2,0);
			OLED_ShowChar((x++)*8,6,' ',2,0);
			OLED_ShowChar((x++)*8,6,' ',2,0);
		}
	}else{
		mileage = (mileage_bushu * bu_long)/100;//计算里程
		tempMileage = (float)mileage/1000;//转换为千米
		sprintf(display,"%6.3fkm ",tempMileage);
		OLED_ShowStr(48,2,(u8 *)display,2);
			
		sprintf((char *)display,"Lon:%10.6f ",GPS.longitude_Degree);
		OLED_ShowStr(16*0,4,(u8*)display,2);//显示经度

		sprintf((char *)display,"Lat:%10.6f ",GPS.latitude_Degree);
		OLED_ShowStr(16*0,6,(u8*)display,2);//显示纬度
	}
}

void DisplaySetValue(void) //显示设置值
{
	if(page==0)
	{
		if(setn==8||setn==9)  //显示心率
		{
			OLED_ShowChar(48,4,xinlvMin/100+'0',2,setn+1-8);//显示
			OLED_ShowChar(56,4,xinlvMin%100/10+'0',2,setn+1-8);//显示
			OLED_ShowChar(64,4,xinlvMin%10+'0',2,setn+1-8);//显示
			OLED_ShowChar(48,6,xinlvMax/100+'0',2,setn+1-9);//显示
			OLED_ShowChar(56,6,xinlvMax%100/10+'0',2,setn+1-9);//显示
			OLED_ShowChar(64,6,xinlvMax%10+'0',2,setn+1-9);//显示
		}
		if(setn==10)
		{
			OLED_ShowChar(48,4,spo2Min/100+'0',2,setn+1-10);//显示
			OLED_ShowChar(56,4,spo2Min%100/10+'0',2,setn+1-10);//显示
			OLED_ShowChar(64,4,spo2Min%10+'0',2,setn+1-10);//显示
		}
		if(setn==11||setn==12)  //显示温度上限限设置
		{
			OLED_ShowChar(48,4,tempMin/100+'0',2,setn+1-11);//显示
			OLED_ShowChar(56,4,tempMin%100/10+'0',2,setn+1-11);//显示
			OLED_ShowChar(64,4,'.',2,setn+1-11);
			OLED_ShowChar(72,4,tempMin%10+'0',2,setn+1-11);//显示
					
			OLED_ShowChar(48,6,tempMax/100+'0',2,setn+1-12);//显示
			OLED_ShowChar(56,6,tempMax%100/10+'0',2,setn+1-12);//显示
			OLED_ShowChar(64,6,'.',2,setn+1-12);
			OLED_ShowChar(72,6,tempMax%10+'0',2,setn+1-12);//显示
		}
	}else{
		if(setn==4)  //显示步长
		{
			sprintf((char *)display,"%dcm  ",bu_long);
			OLED_ShowStr(48, 4, (u8*)display, 2);
		}	
        if(setn==5)  //显示提醒公里
		{
			sprintf(display,"%6.3fkm ",(float)warnMileage);
			OLED_ShowStr(35,4,(u8 *)display,2);	
		}				
	}
}

void KeySettings(void)//按键设置函数
{
	unsigned char keynum = 0,i;
	static u16 pressCount=0;
	bool press = 0;
	u16 beepCount=0;
	
	keynum = KEY_Scan(1);//获取按键值
	if(keynum==1)//设置
	{
		setn++;
		if(page==1)
		{
			if(setn > 5){
				setn=0;
				Store_Data();
				OLED_CLS();//清屏
				for(i=0;i<2;i++)OLED_ShowCN(i*16,2,i+44,0);//显示中文:里程
				OLED_ShowChar(32,2,':',2,0);
			}
			if(setn==4){
				OLED_CLS();//清屏
				for(i=0;i<4;i++)OLED_ShowCN(i*16+32,0,i+46,0);//测试显示中文:设置步长
			}
			if(setn==5){
				for(i=0;i<6;i++)OLED_ShowCN(i*16+16,0,i+50,0);//测试显示中文:设置提醒里程
			}
		}else{
			if(setn > 12){
				setn=0;
				OLED_CLS();//清屏
				for(i=0;i<2;i++)OLED_ShowCN(i*16,4,i+16,1);//测试显示中文:心率
				for(i=0;i<2;i++)OLED_ShowCN(i*16+48,4,i+18,1);//测试显示中文:血氧
				for(i=0;i<2;i++)OLED_ShowCN(i*16+95,4,i+20,1);//测试显示中文:步数
				OLED_ShowCentigrade(112, 2);    //℃
				DelayMs(50);
				Store_Data();
			}
			if(setn==8){
				OLED_CLS();//清屏
				for(i=0;i<4;i++)OLED_ShowCN(i*16+32,0,i+22,0);//测试显示中文:设置心率
				for(i=0;i<2;i++)OLED_ShowCN(i*16,4,i+26,0);   //测试显示中文:下限
				for(i=0;i<2;i++)OLED_ShowCN(i*16,6,i+28,0);   //测试显示中文:上限
				OLED_ShowChar(34,4,':',2,0);
				OLED_ShowChar(34,6,':',2,0);
			}
			if(setn==10){
				for(i=0;i<4;i++)OLED_ShowCN(i*16+32,0,i+30,0);//测试显示中文:设置血氧
				for(i=0;i<2;i++)OLED_ShowCN(i*16,4,i+26,0);   //测试显示中文:下限
				OLED_ShowStr(0,6,"                ", 2);
			}
			if(setn==11){
				for(i=0;i<4;i++)OLED_ShowCN(i*16+32,0,i+34,0);//测试显示中文:设置温度
				for(i=0;i<2;i++)OLED_ShowCN(i*16,4,i+26,0);   //测试显示中文:下限
				for(i=0;i<2;i++)OLED_ShowCN(i*16,6,i+28,0);   //测试显示中文:上限
				OLED_ShowChar(34,4,':',2,0);
				OLED_ShowChar(34,6,':',2,0);
			}
		}
		DisplaySetValue();
	}
	if(keynum==2)//加
	{
		if(setn == 0 && page==1){
			if(pressCount<10)pressCount++;
			if(press==0){
				press=1;
				BEEP=1;
				DelayMs(100);
				BEEP=0;
				if(timingReminder==1)  //如果是提醒时间到了,先关闭提醒
				{
					timingReminder=0;
					beepFlag&=0xEF;
				}else{
					startFlag=!startFlag;
				}
			}
			if(pressCount>=5)   //长按进行时间清零
			{
				startFlag=0;
				timeCountRecord=0;
				while(beepCount<1000)
				{
					BEEP=1;
					beepCount++;
					DelayMs(1);
				}
				BEEP=0;
				pressCount=0;
			}
		}
		if(page==1){
			if(setn == 1)//设置提醒时间的小时
			{
				shi++;if(shi == 100)shi=0;
			}
			if(setn == 2)//设置提醒时间的分钟
			{
				fen++;if(fen == 60)fen=0;
			}
			if(setn == 3)//设置提醒时间的秒
			{
				miao++;if(miao == 60)miao=0;
			}
			if(setn == 4)//设置步长
			{
				if(bu_long<200)bu_long++;
			}
			if(setn == 5)//设置提醒里程
			{
				if(warnMileage<20000)warnMileage+=10;
			}
		}else{
			if(setn == 1)//设置年
			{
				SysDate.year ++;
				if(SysDate.year == 100)SysDate.year=0;
				DS1302_DateSet(&SysDate);//设置时间
			}
			if(setn == 2)//设置月
			{
				SysDate.mon ++;
				if(SysDate.mon == 13)SysDate.mon = 1;
				if((SysDate.mon==4)||(SysDate.mon==6)||(SysDate.mon==9)||(SysDate.mon==11))
				{
					if(SysDate.day>30)SysDate.day=1;
				}else{
					if(SysDate.mon==2){
						if(p_r==1){
							if(SysDate.day>29)
								SysDate.day=1;
						}else{
							if(SysDate.day>28)
								SysDate.day=1;
						}
					}
				}
				DS1302_DateSet(&SysDate);//设置时间
			}
			if(setn == 3)//设置日
			{
				SysDate.day ++;
				if((SysDate.mon==1)||(SysDate.mon==3)||(SysDate.mon==5)||(SysDate.mon==7)||(SysDate.mon==8)||(SysDate.mon==10)||(SysDate.mon==12))//大月
				{
					if(SysDate.day==32)//最大31天
						SysDate.day=1;//从1开始
				}else{
					if(SysDate.mon==2)//二月份
					{
						if(p_r==1)//闰年
						{
							if(SysDate.day==30)//最大29天
								SysDate.day=1;
						}else{
							if(SysDate.day==29)//最大28天
								SysDate.day=1;
						}
					}else{
						if(SysDate.day==31)//最大30天
							SysDate.day=1;
					}
				}
				DS1302_DateSet(&SysDate);//设置时间
			}
			if(setn == 4)//设置星期
			{
				SysDate.week ++;
				if(SysDate.week == 8)SysDate.week=1;
				DS1302_DateSet(&SysDate);//设置时间
			}
			if(setn == 5)//设置时
			{
				SysDate.hour ++;
				if(SysDate.hour == 24)SysDate.hour=0;
				DS1302_DateSet(&SysDate);//设置时间
			}
			if(setn == 6)//设置分
			{
				SysDate.min ++;
				if(SysDate.min == 60)SysDate.min=0;
				DS1302_DateSet(&SysDate);//设置时间
			}
			if(setn == 7)//设置秒
			{
				SysDate.sec ++;
				if(SysDate.sec == 60)SysDate.sec=0;
				DS1302_DateSet(&SysDate);//设置时间
			}
			if((setn==8)&&(xinlvMax-xinlvMin>1))xinlvMin++;
			if((setn==9)&&(xinlvMax<300))xinlvMax++;
			if((setn==10)&&(spo2Min<200))spo2Min++; 
			if((setn==11)&&(tempMax-tempMin>1))tempMin++; 
			if((setn==12)&&(tempMax<999))tempMax++; 
		}
		DisplaySetValue();
	}else{
		if(press==1){
			press=0;
			pressCount=0;
		}
	}
	if(keynum==3)//减
	{
		if(page==1){  
			if(setn == 0){
				if(mileageReminder==1)   //如果是提醒里程到了,先关闭提醒
				{
					mileageReminder=0;
					BEEP=0;
				}else if(mileageReminder==0){   //里程清零
					mileage=0;
					mileage_bushu=0;
					Store_Data(); //存储步数
				}
			}
			if(setn == 1)//设置提醒时间的小时
			{
				if(shi == 0)shi=100;shi --;
			}
			if(setn == 2)//设置提醒时间的分钟
			{
				if(fen == 0)fen=60;fen --;
			}
			if(setn == 3)//设置提醒时间的秒
			{
				if(miao == 0)miao=60;miao --;
			}
			if(setn == 4)//设置步长
			{
				if(bu_long>0)bu_long--;
			}
			if(setn == 5)//设置提醒里程
			{
				if(warnMileage>=10)warnMileage-=10;
			}
		}else{
			if(setn == 1)//设置年
			{
				if(SysDate.year == 0)SysDate.year=100;
				SysDate.year --;
				DS1302_DateSet(&SysDate);
//								DS1302_Init(&SysDate);
//								DS1302_DateRead(&SysDate);//读时间
			}
			if(setn == 2)//设置月
			{
				if(SysDate.mon == 1)SysDate.mon=13;
				SysDate.mon --;
				if((SysDate.mon==4)||(SysDate.mon==6)||(SysDate.mon==9)||(SysDate.mon==11))
				{
					if(SysDate.day>30)SysDate.day=1;
				}
				else
				{
					if(SysDate.mon==2){
						if(p_r==1){
							if(SysDate.day>29)SysDate.day=1;
						}else{
							if(SysDate.day>28)SysDate.day=1;
						}
					}
				}
				DS1302_DateSet(&SysDate);
			}
			if(setn == 3)//设置日
			{
				SysDate.day --;
				if((SysDate.mon==1)||(SysDate.mon==3)||(SysDate.mon==5)||(SysDate.mon==7)||(SysDate.mon==8)||(SysDate.mon==10)||(SysDate.mon==12))
				{
					if(SysDate.day==0)SysDate.day=31;
				}else{
					if(SysDate.mon==2){
						if(p_r==1){
							if(SysDate.day==0)SysDate.day=29;
						}else{
							if(SysDate.day==0)SysDate.day=28;
						}
					}else{
						if(SysDate.day==0)SysDate.day=30;
					}
				}
				DS1302_DateSet(&SysDate);
			}
			if(setn == 4)//设置星期
			{
				if(SysDate.week == 1)SysDate.week=8;
				SysDate.week --;
				DS1302_DateSet(&SysDate);
			}
			if(setn == 5)//设置时
			{
				if(SysDate.hour == 0)SysDate.hour=24;
				SysDate.hour --;
				DS1302_DateSet(&SysDate);
			}
			if(setn == 6)//设置分
			{
				if(SysDate.min == 0)SysDate.min=60;
				SysDate.min --;
				DS1302_DateSet(&SysDate);
			}
			if(setn == 7)//设置秒
			{
				if(SysDate.sec == 0)SysDate.sec=60;
				SysDate.sec --;
				DS1302_DateSet(&SysDate);
			}
			if((setn==8)&&(xinlvMin>0))xinlvMin--;
			if((setn==9)&&(xinlvMax-xinlvMin>1))xinlvMax--;
			if((setn==10)&&(spo2Min>0))spo2Min--; 
			if((setn==11)&&(tempMin>0))tempMin--; 
			if((setn==12)&&(tempMax-tempMin>1))tempMax--; 
		}
		DisplaySetValue();
	}
	if(keynum==4&&page==0)//步数清零
	{
		bushu = 0;
		Store_Data();
	}
	if(keynum==5 && setn == 0)//切换显示界面
	{
		page=!page;
		OLED_CLS();//清屏
		if(page==0)
		{
			for(i=0;i<2;i++)OLED_ShowCN(i*16,4,i+16,1);//测试显示中文:心率
			for(i=0;i<2;i++)OLED_ShowCN(i*16+48,4,i+18,1);//测试显示中文:血氧
			for(i=0;i<2;i++)OLED_ShowCN(i*16+95,4,i+20,1);//测试显示中文:步数
			OLED_ShowCentigrade(112, 2);    //℃
		}else{
			for(i=0;i<2;i++)OLED_ShowCN(i*16,2,i+44,0);//显示中文:里程
			OLED_ShowChar(32,2,':',2,0);
		}
	}
}


void displayTimeCunt(void)  //显示定时时间
{
	if(page==1){
		if(setn==0){
			OLED_ShowChar(32,0,timeCountRecord/3600/10+'0',2,0);
			OLED_ShowChar(40,0,timeCountRecord/3600%10+'0',2,0);
			OLED_ShowChar(48,0,':',2,0);
			OLED_ShowChar(56,0,timeCountRecord%3600/60/10+'0',2,0);
			OLED_ShowChar(64,0,timeCountRecord%3600/60%10+'0',2,0);
			OLED_ShowChar(72,0,':',2,0);
			OLED_ShowChar(80,0,timeCountRecord%3600%60/10+'0',2,0);
			OLED_ShowChar(88,0,timeCountRecord%3600%60%10+'0',2,0);
		}else{
			if(setn<4){
				OLED_ShowChar(32,0,shi/10+'0',2,setn+1-1);
				OLED_ShowChar(40,0,shi%10+'0',2,setn+1-1);
				OLED_ShowChar(48,0,':',2,0);
				OLED_ShowChar(56,0,fen/10+'0',2,setn+1-2);
				OLED_ShowChar(64,0,fen%10+'0',2,setn+1-2);
				OLED_ShowChar(72,0,':',2,0);
				OLED_ShowChar(80,0,miao/10+'0',2,setn+1-3);
				OLED_ShowChar(88,0,miao%10+'0',2,setn+1-3);
			}
		}
	}
}

int main(void)
{
	unsigned char i;
	uint16_t sss;
	DelayInit();
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE); //改变指定管脚的映射完全禁用(JTAG+SW-DP)
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//改变指定管脚的映射,JTAG-DP 禁用 + SW-DP 使能
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	I2C_Configuration(); //IIC初始化
	OLED_Init(); //OLED初始化
	uart2_init(9600);
	KEY_Init(); //按键初始化
	DelayMs(200);
	CheckNewMcu();
#if 1
    OLED_CLS();//清屏
	DS18B20_Init();
	DS1302_Init(&SysDate);
	DS1302_DateSet(&SysDate);
	DelayMs(100);
	for(i=0;i<8;i++)OLED_ShowCN(i*16,2,i+8,0);//测试显示中文:欢迎使用使能手环
	DS1302_DateRead(&SysDate);//读时间
	OLED_CLS();//清屏
	for(i=0;i<2;i++)OLED_ShowCN(i*16,4,i+16,1);//测试显示中文:心率
	for(i=0;i<2;i++)OLED_ShowCN(i*16+48,4,i+18,1);//测试显示中文:血氧
	for(i=0;i<2;i++)OLED_ShowCN(i*16+95,4,i+20,1);//测试显示中文:步数
	OLED_ShowCentigrade(112, 2);    //℃
	IIC_init();//IIC初始化
	adxl345_init();//ADXL345初始化
	MAX30102_Init();
	mun_min=0x3FFFF;
	mun_max=0;
	Max30102_right_data();
//	Init_MAX30102();//MAX30102初始化
	memset(STM32_RX1_BUF, 0, STM32_RX1BUFF_SIZE);//清除缓存
	STM32_Rx1Counter = 0;
	TIM2_Init(99,719);   //定时器初始化,定时1ms
//	printf("1445552");
	uart1_Init(9600);
#endif
	while(1)
	{
//		shanshuo=!shanshuo;
		shanshuo = 1;
		KeySettings();			//按键设置函数
		DisplayTime();			//显示时间函数
		displayTimeCunt();		//显示定时时间
		if(setn == 0)//不在设置状态下,读取相关数据
		{
			DisplayTemperature();	//显示温度函数
			GetSteps();				//获取步数,里程,经纬度函数
			GetHeartRateSpO2();		//读取心率血氧
//			DelayMs(200);
			FallDetection();		//倾斜检测
		}
//		UsartSendReceiveData();
	}
}

七、项目资料包内容

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

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐