stm32智能手表

成为粉丝可看全文。有相关代码、硬件和软件说明图。

主程序流程图

说明图:

主程序代码如下,可以修改为自己适用代码

复制代码
#include "stm32f10x.h"
#include "OLED_I2C.h"
#include "ds1302.h"
#include "ds18b20.h"
#include "usart1.h"
#include "led.h"
#include "delay.h"
#include "max30102_read.h"
#include "myiic.h"
#include "key.h"
#include "iic.h"
#include "stdio.h"
#include "string.h"
#include "adxl345.h"
#include "timer.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define FLASH_SAVE_ADDR  ((u32)0x0800F000) 				//设置FLASH 保存地址(必须为偶数)

#define STM32_RX1_BUF       Usart1RecBuf 
#define STM32_Rx1Counter    RxCounter
#define STM32_RX1BUFF_SIZE  USART1_RXBUFF_SIZE

unsigned char setn=0;
unsigned char  p_r=0;		 						//平年/润年  =0表示平年,=1表示润年
float adx,ady,adz;
float acc;
float acc2,acc3;
u8 flag=0;
u16 bushu=0;
long mileage=0;//里程
u16 mileage_bushu = 0;//里程的步数
u16 bu_long = 40;//步长
long warnMileage=1000;//提醒里程
short temperature=0;
u16 xinlvMin=60,xinlvMax=120;//心率下限上限
u16 spo2Min=80;//血氧下限
u16 tempMax=373;//温度上限
u16 tempMin=150;//温度下限
char display[16];
u8 shanshuo=0;
u8 beepFlag=0x00; //蜂鸣器报警标志
u8 page = 0;      //页面切换变量
u8 sendFlag = 1;

/*定时时间*/
long timeCountRecord=0;
long shi=1,fen=0,miao=0;  
bool startFlag=0;        //开始定时标志
bool timingReminder=0;   //定时时间提醒标志
bool mileageReminder=0;  //里程提醒标志
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 GetHeartRateSpO2(void)
{
	unsigned char x=0;
	
	ReadHeartRateSpO2();  //读取心率血氧
	
	if(page==0)
	{
				//显示相关的信息
				if(((hrAvg!=0)&&(hrAvg>=xinlvMax||hrAvg<=xinlvMin))&&shanshuo==1)
				{
						 OLED_ShowChar((x++)*8,6,' ',2,0);
						 OLED_ShowChar((x++)*8,6,' ',2,0);
						 OLED_ShowChar((x++)*8,6,' ',2,0);
				}
				else
				{
							//显示相关的信息
						OLED_ShowChar((x++)*8,6,hrAvg%1000/100+'0',2,0);
						OLED_ShowChar((x++)*8,6,hrAvg%100/10+'0',2,0);
						OLED_ShowChar((x++)*8,6,hrAvg%10+'0',2,0);
				}
				x=6;
				if(((spo2Avg!=0)&&(spo2Avg<=spo2Min))&&shanshuo==1)
				{
						 OLED_ShowChar((x++)*8,6,' ',2,0);
						 OLED_ShowChar((x++)*8,6,' ',2,0);
						 OLED_ShowChar((x++)*8,6,' ',2,0);
				}
				else
				{
							//显示相关的信息
						OLED_ShowChar((x++)*8,6,spo2Avg%1000/100+'0',2,0);
						OLED_ShowChar((x++)*8,6,spo2Avg%100/10+'0',2,0);
						OLED_ShowChar((x++)*8,6,spo2Avg%10+'0',2,0);
				}
		}
}

void DisplayTemperature(void)//显示温度函数
{
	  unsigned char x=10;//显示的第几个字符
		
	  temperature=DS18B20_Get_Temp();
	  if(page==0)
		{
				if((temperature<=tempMin||temperature>=tempMax)&&shanshuo==1)
				{
						 OLED_ShowChar((x++)*8,2,' ',2,0);
						 OLED_ShowChar((x++)*8,2,' ',2,0);
						 OLED_ShowChar((x++)*8,2,' ',2,0);
						 OLED_ShowChar((x++)*8,2,' ',2,0);
				}
				else
				{
						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 Store_Data(void) //存储数据
{
	  u16 DATA_BUF[10];
	
		DATA_BUF[0] =   bushu;
		DATA_BUF[1] =   mileage_bushu;
		DATA_BUF[2] =   bu_long;
    DATA_BUF[3] =   xinlvMin;   
	  DATA_BUF[4] =   xinlvMax;
	  DATA_BUF[5] =   spo2Min;
	  DATA_BUF[6] =   tempMin;
	  DATA_BUF[7] =   tempMax;
	  DATA_BUF[8] =   (warnMileage>>16)&0xFFFF;
	  DATA_BUF[9] =   (warnMileage>>0)&0xFFFF;
	
	  STMFLASH_Write(FLASH_SAVE_ADDR + 0x20,(u16*)DATA_BUF,10); //写入数据
	
	  DelayMs(50);
}

void Read_Data(void) //读出数据
{
	   u16 DATA_BUF[10];
	
	   STM32F10x_Read(FLASH_SAVE_ADDR + 0x20,(u16*)DATA_BUF,10); //读取数据
	
	   bushu         =  DATA_BUF[0];  
	   mileage_bushu =  DATA_BUF[1]; 
	   bu_long       =  DATA_BUF[2]; 
	   xinlvMin      =  DATA_BUF[3];  
	   xinlvMax      =  DATA_BUF[4]; 
	   spo2Min       =  DATA_BUF[5]; 
	   tempMin       =  DATA_BUF[6];  
	   tempMax       =  DATA_BUF[7]; 
	   warnMileage   =  DATA_BUF[8]<<16|DATA_BUF[9]; 
}

void CheckNewMcu(void)  // 检查是否是新的单片机,是的话清空存储区,否则保留
{
	  u8 comper_str[6];
		
	  STM32F10x_Read(FLASH_SAVE_ADDR,(u16*)comper_str,5);
	  comper_str[5] = '\0';
	  if(strstr((char *)comper_str,"FDYDZ") == NULL)  //新的单片机
		{
			 STMFLASH_Write(FLASH_SAVE_ADDR,(u16*)"FDYDZ",5); //写入"FDYDZ",方便下次校验
			 DelayMs(50);
			 Store_Data();//存储下初始数据
			 DelayMs(50);
	  }
		Read_Data(); //开机读取下相关数据(步数里程卡路里步长)
}

void GetSteps(void)//获取步数函数
{
	  static u16 temp=0;
	  float tempMileage=0.0;
	  u16 x=11; 
	
	  adxl345_read_average(&adx,&ady,&adz,10);//获取数据
		acc=ady;
		
		if(acc>0)//在正轴
		{
			if(acc/10>=4&&flag==1)//加速度值,在正轴值是否大于5,并且flag为1,则视为一个周期完成,步数加1
			{
				flag=0;	
				if(bushu<60000)bushu++;	//步数加1
				if(mileage_bushu<60000)mileage_bushu++;	//步数加1
				if(temp!=bushu)//当步数发生变化才去存储步数
				{
						temp=bushu;
					  Store_Data(); //存储步数
				}
			}
		}
		if(acc<0)//在负轴
		{
			acc=-acc;
			if(acc/10>=4)//加速度值,在负轴是否小于-5
			{
					flag=1;//falg置1
			}
		}
		
		mileage = (mileage_bushu * bu_long)/100;//计算里程
		tempMileage = (float)mileage/1000;//转换为千米
		
		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
		{
				sprintf(display,"%6.3fkm ",tempMileage);
				OLED_ShowStr(48,2,(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/1000);
					OLED_ShowStr(35,4,(u8 *)display,2);
				}					
		}
}

bool press = 0;
void KeySettings(void)//按键设置函数
{
	  unsigned char keynum = 0,i;
	  static u16 pressCount=0;
	  u16 beepCount=0;
	
	  keynum = KEY_Scan(1);//获取按键值
		if(keynum==1)//设置
		{
				setn++;
			  if(page==1)
				{
						if(setn > 5)
						{
								setn=0;
							  sendSetValueFlag=1;
							  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;
							  sendSetValueFlag=1;
								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&=0xFD;
							 }
							 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);
						}
						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);
						}
				}
		}
}
	
void UsartSendReceiveData(void)   //串口发送接收数据
{
	  char *str1=0,*str2=0,i;
	  int  setValue=0;
	  char setvalue[4]={0};
	
	  if(strlen(STM32_RX1_BUF) > 0)
		{
			  DelayMs(10);
			  
			  if(strstr(STM32_RX1_BUF,"setHeartMin:")!=NULL)    //接收到设置心率下限的指令
				{
						str1 = strstr(STM32_RX1_BUF,"setHeartMin:");
					  
					  while(*str1 < '0' || *str1 > '9')        //判断是不是0到9有效数字
						{
								str1 = str1 + 1;
								DelayMs(10);
						}
						i = 0;
						while(*str1 >= '0' && *str1 <= '9')        //判断是不是0到9有效数字
						{
								setvalue[i] = *str1;
								i ++; str1 ++;
								if(*str1 == '\r')break;            //换行符,直接退出while循环
								DelayMs(10);
						}
						setvalue[i] = '\0';            //加上结尾符
						setValue = atoi(setvalue);
						if(setValue>=0 && setValue<=300)
						{
								xinlvMin = setValue;    //设置的心率下限
							  DisplaySetValue();
							  Store_Data();//存储数据
						}
				}
			
				if(strstr(STM32_RX1_BUF,"setHeartMax:")!=NULL)		//接收到设置心率上限的指令
				{
						str1 = strstr(STM32_RX1_BUF,"setHeartMax:");
					  
					  while(*str1 < '0' || *str1 > '9')        //判断是不是0到9有效数字
						{
								str1 = str1 + 1;
								DelayMs(10);
						}
						i = 0;
						while(*str1 >= '0' && *str1 <= '9')        //判断是不是0到9有效数字
						{
								setvalue[i] = *str1;
								i ++; str1 ++;
								if(*str1 == '\r')break;            //换行符,直接退出while循环
								DelayMs(10);
						}
						setvalue[i] = '\0';            //加上结尾符
						setValue = atoi(setvalue);
						if(setValue>=0 && setValue<=300)
						{
								xinlvMax = setValue;    //设置的心率上限
							  DisplaySetValue();
							  Store_Data();//存储数据
						}
				}
				
				if(strstr(STM32_RX1_BUF,"setSpo2Min:")!=NULL)  //接收到设置血氧下限的指令
				{
						str1 = strstr(STM32_RX1_BUF,"setSpo2Min:");
					  
					  while(*str1 != ':')        //判断是不是0到9有效数字
						{
								str1 = str1 + 1;
								DelayMs(10);
						}
						str1 = str1 + 1;
						i = 0;
						while(*str1 >= '0' && *str1 <= '9')        //判断是不是0到9有效数字
						{
								setvalue[i] = *str1;
								i ++; str1 ++;
								if(*str1 == '\r')break;            //换行符,直接退出while循环
								DelayMs(10);
						}
						setvalue[i] = '\0';            //加上结尾符
						setValue = atoi(setvalue);
						if(setValue>=0 && setValue<=200)
						{
								spo2Min = setValue;    //设置的血氧下限
							  DisplaySetValue();
							  Store_Data();//存储数据
						}
				}
				
				if(strstr(STM32_RX1_BUF,"setTempMin:")!=NULL)  //接收到设置温度下限的指令
				{
						str1 = strstr(STM32_RX1_BUF,"setTempMin:");
					  
					  while(*str1 < '0' || *str1 > '9')        //判断是不是0到9有效数字
						{
								str1 = str1 + 1;
								DelayMs(10);
						}
						i = 0;
						while(*str1 >= '0' && *str1 <= '9')        //判断是不是0到9有效数字
						{
								setvalue[i] = *str1;
								i ++; str1 ++;
								if(*str1 == '.')break;            //换行符,直接退出while循环
								DelayMs(10);
						}
						if(*str1 == '.')
						{
								str1 = str1 + 1;
						}
						if(*str1 >= '0' && *str1 <= '9')
						{
								setvalue[i] = *str1;
						}
						i = i + 1;
						setvalue[i] = '\0';            //加上结尾符
						setValue = atoi(setvalue);
						if(setValue>=0 && setValue<=999)
						{
								tempMin = setValue;    //设置的温度下限
							  DisplaySetValue();
							  Store_Data();//存储数据
						}
				}
				
				if(strstr(STM32_RX1_BUF,"setTempMax:")!=NULL)  //接收到设置温度上限的指令
				{
						str1 = strstr(STM32_RX1_BUF,"setTempMax:");
					  
					  while(*str1 < '0' || *str1 > '9')        //判断是不是0到9有效数字
						{
								str1 = str1 + 1;
								DelayMs(10);
						}
						i = 0;
						while(*str1 >= '0' && *str1 <= '9')        //判断是不是0到9有效数字
						{
								setvalue[i] = *str1;
								i ++; str1 ++;
								if(*str1 == '.')break;            //换行符,直接退出while循环
								DelayMs(10);
						}
						if(*str1 == '.')
						{
								str1 = str1 + 1;
						}
						if(*str1 >= '0' && *str1 <= '9')
						{
								setvalue[i] = *str1;
						}
						i = i + 1;
						setvalue[i] = '\0';            //加上结尾符
						setValue = atoi(setvalue);
						if(setValue>=0 && setValue<=999)
						{
								tempMax = setValue;    //设置的温度上限
							  DisplaySetValue();
							  Store_Data();//存储数据
						}
				}
				
				if(strstr(STM32_RX1_BUF,"setSteps:")!=NULL)  //接收到设置步长的指令
				{
						str1 = strstr(STM32_RX1_BUF,"setSteps:");
					  
					  while(*str1 < '0' || *str1 > '9')        //判断是不是0到9有效数字
						{
								str1 = str1 + 1;
								DelayMs(10);
						}
						i = 0;
						while(*str1 >= '0' && *str1 <= '9')        //判断是不是0到9有效数字
						{
								setvalue[i] = *str1;
								i ++; str1 ++;
								if(*str1 == '\r')break;            //换行符,直接退出while循环
								DelayMs(10);
						}
						setvalue[i] = '\0';            //加上结尾符
						setValue = atoi(setvalue);
						if(setValue>=0 && setValue<=200)
						{
								bu_long = setValue;    //设置的步长
							  DisplaySetValue();
							  Store_Data();//存储数据
						}
				}
				
				if(strstr(STM32_RX1_BUF,"setMileage:")!=NULL)  //接收到设置里程的指令
				{
						str1 = strstr(STM32_RX1_BUF,"setMileage:");
					  
					  while(*str1 < '0' || *str1 > '9')        //判断是不是0到9有效数字
						{
								str1 = str1 + 1;
								DelayMs(10);
						}
						i = 0;
						while(*str1 >= '0' && *str1 <= '9')        //判断是不是0到9有效数字
						{
								setvalue[i] = *str1;
								i ++; str1 ++;
								if(*str1 == '.')break;            //换行符,直接退出while循环
								DelayMs(10);
						}
						if(*str1 == '.')
						{
								str1 = str1 + 1;
						}
						while(*str1 >= '0' && *str1 <= '9')        //判断是不是0到9有效数字
						{
								setvalue[i] = *str1;
								i ++; str1 ++;
								if(*str1 == '\r')break;            //换行符,直接退出while循环
								DelayMs(10);
						}
						setvalue[i] = '\0';            //加上结尾符
						setValue = atoi(setvalue);
						if(setValue>=0 && setValue<=999)
						{
								warnMileage = setValue*10;    //设置的提醒里程
							  DisplaySetValue();
							  Store_Data();//存储数据
						}
				}
				
				if(strstr(STM32_RX1_BUF,"warntime")!=NULL)  //接收到设置提醒时间的指令
				{
					  press=1;
					
					  BEEP = 1;
						DelayMs(80);
					  BEEP = 0;
					
						str2 = strstr(STM32_RX1_BUF,"warntime");
					  
					  while(*str2 < '0' || *str2 > '9')        //判断是不是0到9有效数字
						{
								str2 = str2 + 1;
								DelayMs(10);
						}
						i = 0;
						while(*str2 >= '0' && *str2 <= '9')        //判断是不是0到9有效数字
						{
								setvalue[i] = *str2;
								i ++; str2 ++;
								if(*str2 == ':')break;         
								DelayMs(10);
						}
						setvalue[i] = '\0';            //加上结尾符
						setValue = atoi(setvalue);
						if(setValue>=0 && setValue<=99)
						{
								shi = setValue;   //提醒时间的小时
							  displayTimeCunt();
						}
						str2 = str2 + 1;
						i = 0;
						while(*str2 >= '0' && *str2 <= '9')        //判断是不是0到9有效数字
						{
								setvalue[i] = *str2;
								i ++; str2 ++;
							  if(*str2 == ':')break;         
								DelayMs(10);
						}
						setvalue[i] = '\0';            //加上结尾符

						setValue = atoi(setvalue);
						if(setValue>=0 && setValue<=59)
						{
								fen = setValue;   //提醒时间的分钟
							  displayTimeCunt();
						}
						
						str2 = str2 + 1;
						i = 0;
						while(*str2 >= '0' && *str2 <= '9')        //判断是不是0到9有效数字
						{
								setvalue[i] = *str2;
								i ++; str2 ++;
								if(*str2 == '\r')break;         
								DelayMs(10);
						}
						setvalue[i] = '\0';            //加上结尾符
						setValue = atoi(setvalue);
						if(setValue>=0 && setValue<=59)
						{
								miao = setValue;   //提醒时间的秒
							  displayTimeCunt();
						}
				}
				
				if(strstr(STM32_RX1_BUF,"stepsClear")!=NULL)   //收到步数清零指令
				{
					  press=1;
					
					  BEEP = 1;
						DelayMs(80);
					  BEEP = 0;
					
						bushu = 0;
						Store_Data();  //存储数据
				}
				
				if(strstr(STM32_RX1_BUF,"mileageClear")!=NULL)  //收到里程清零指令
				{
					  press=1;
					
					  BEEP = 1;
						DelayMs(80);
					  BEEP = 0;
					
						mileage=0;
						mileage_bushu=0;
						
						Store_Data(); //存储数据
				}
				
				if(strstr(STM32_RX1_BUF,"timeClear")!=NULL) //收到时间清零指令
				{
					  press=1;
					
					  BEEP = 1;
						DelayMs(80);
					  BEEP = 0;
					  timingReminder=0;
						beepFlag&=0xFD;
					  startFlag=0;
						timeCountRecord=0;
				}
				
				if(strstr(STM32_RX1_BUF,"startTiming")!=NULL) //收到开始定时指令
				{
					  press=1;
					
					  BEEP = 1;
						DelayMs(80);
					  BEEP = 0;
					
						startFlag=1;
				}
				
				if(strstr(STM32_RX1_BUF,"pauseTiming")!=NULL)//收到暂停定时指令
				{
					  press=1;
					
					  BEEP = 1;
						DelayMs(80);
					  BEEP = 0;
					
						startFlag=0;
				}
				
				if(strstr(STM32_RX1_BUF,"offMileage")!=NULL)  //收到关闭里程提醒指令
				{
					  press=1;
					
					  BEEP = 1;
						DelayMs(80);
					  BEEP = 0;
					
						mileageReminder=0;
				}
				
				if(strstr(STM32_RX1_BUF,"offTime")!=NULL)//收到关闭时间提醒指令
				{
					  press=1;
					
					  BEEP = 1;
						DelayMs(80);
					  BEEP = 0;
					
						timingReminder=0;
						beepFlag&=0xFD;
				}
				
				memset(STM32_RX1_BUF, 0, STM32_RX1BUFF_SIZE);//清除缓存
				STM32_Rx1Counter = 0;
		}
	
	  /* 蓝牙发送数据 */
	  if(sendFlag==1)
		{
			  sendFlag = 0;
				printf("$Heartrate:%d#,$Spo2:%d#,$Temperature:%4.1f#,",hrAvg,spo2Avg,(float)temperature/10);
				printf("$Steps:%d#,$Mileage:%6.3f#,",bushu,(float)mileage/1000);
				printf("$Hour:%02d#,",(int)(timeCountRecord/3600));
				printf("$Min:%02d#,",(int)(timeCountRecord%3600/60));
				printf("$Sec:%02d#",(int)(timeCountRecord%3600%60));
			
			  printf("send ok.");
			
			  if(sendSetValueFlag==1)
				{
						sendSetValueFlag=0;
					
					  DelayMs(500);
					
					  printf("$setHeartMin:%d#,",xinlvMin);
						printf("$setHeartMax:%d#,",xinlvMax);
						printf("$setSpo2Min:%d#,",spo2Min);
						printf("$setTempMin:%4.1f#,",(float)tempMin/10);
						printf("$setTempMax:%4.1f#,",(float)tempMax/10);
					  printf("send test data.");
						printf("$setLength:%d#,",bu_long);
						printf("$setMileage:%5.2f#\r\n",(float)warnMileage/1000);
				}
		}
}

int main(void)
{
	unsigned char i;
	
	DelayInit();
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	
	KEY_Init(); //按键初始化
	DelayMs(200);
	I2C_Configuration(); //IIC初始化
	OLED_Init(); //OLED初始化
	CheckNewMcu();
  OLED_CLS();//清屏
	DS18B20_Init();
	DS1302_Init(&SysDate);
	uart1_Init(9600);   
	DelayMs(100);
	for(i=0;i<8;i++)OLED_ShowCN(i*16,2,i+8,0);//测试显示中文:欢迎使用使能手环
	DelayMs(1000);
	OLED_CLS();//清屏
	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初始化
	Init_MAX30102();//MAX30102初始化
	memset(STM32_RX1_BUF, 0, STM32_RX1BUFF_SIZE);//清除缓存
	STM32_Rx1Counter = 0;
	TIM2_Init(99,719);   //定时器初始化,定时1ms
	//Tout = ((arr+1)*(psc+1))/Tclk ; 
	//Tclk:定时器输入频率(单位MHZ)
	//Tout:定时器溢出时间(单位us)
	while(1)
	{
		  shanshuo=!shanshuo;
		  KeySettings();
	    DisplayTime();
		  displayTimeCunt();
		  if(setn == 0)//不在设置状态下,读取相关数据
			{
					DisplayTemperature();
					GetSteps();
					GetHeartRateSpO2();
			}
			UsartSendReceiveData();
			DelayMs(10);
	}
}

void TIM2_IRQHandler(void)//定时器2中断服务程序,用于记录时间
{ 
	  static u16 timeCount1 = 0;
	  static u16 timeCount2 = 0;
	  static u16 timeCount3 = 0;
	  static u16 timeCount4 = 0;
	
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
		{ 
				TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断标志位  
			
			  /*  蜂鸣器提醒优先级:跌倒 > 心率血氧温度报警 > 时间提醒 > 里程提醒  */
			
			  if(timingReminder==1 && (!(beepFlag&0x01))) //时间提醒
				{
						timeCount1 ++;
					  if(timeCount1==1)BEEP=1;
					  if(timeCount1==100)BEEP=0;
					  if(timeCount1>=1000)
						{
							timeCount1=0;
						}
				}
				else
				{
						timeCount1=0;
				}
			
				timeCount2 ++;
			
				if(timeCount2 >= 1000)   //1s
				{
						timeCount2 = 0;
					  if(startFlag==1)
						{
								if(timeCountRecord<(98*3600+59*60))
								{
										timeCountRecord ++;          //时间计时
								}
								
								if(timeCountRecord==(shi*3600+fen*60+miao))//时间到了提醒标志置1
								{
										 timingReminder=1;
									   beepFlag|=0x02;
								}
						}
						sendFlag = 1;
				}
				
			  timeCount3 ++;
				if(timeCount3 >= 100) 
				{
						timeCount3=0;

						if(((hrAvg!=0)&&(hrAvg>=xinlvMax||hrAvg<=xinlvMin))||((spo2Avg!=0)&&(spo2Avg<=spo2Min))||(temperature>=tempMax||temperature<=tempMin))//不在范围蜂鸣器报警
						{
							BEEP=~BEEP;
							beepFlag|=0x01;
							
						}else
						{	
							beepFlag&=0xFE;
							
							if(timingReminder==0 && mileageReminder==0 && press==0)BEEP=0;
							if(mileage>=warnMileage)   //里程达标,提醒标志置1 
							{
									if((beepFlag>>2)==0)
									{
											beepFlag|=0x04;
											mileageReminder=1;
									}
							}
							else
							{
									beepFlag&=0xFB;
									mileageReminder=0;
							}
						}
				}
				
				timeCount4 ++;
				if(timeCount4>=50)  //50ms
				{
					  static u8 BeepCount=0;
					
						timeCount4=0;
					  
						if(mileageReminder==1 && (!(beepFlag&0x03)))   //里程到了蜂鸣器提醒
						{
								BeepCount++;
								if(BeepCount==3)BEEP=1;
								if(BeepCount==6)BEEP=0; 
								if(BeepCount==9)BEEP=1;
								if(BeepCount==12)BEEP=0;
								if(BeepCount==15)BEEP=1;
								if(BeepCount==18)BEEP=0; 
							
								if(BeepCount==40)
								{
										BEEP=0;
										BeepCount=0;
								}
						}
				}
		}
}
相关推荐
u***u6855 天前
HarmonyOS在智能手表中的开发
华为·harmonyos·智能手表
电子工程师-C5115 天前
基于单片机的智能手表
单片机·嵌入式硬件·智能手表
小Mei数码说17 天前
华为WATCH 5:连接心与心,让生活更美好
华为·智能手表
康语智能1 个月前
小康AI家庭医生:以科技之翼,守陪伴之初心
大数据·人机交互·智能手表
2401_885405511 个月前
定位守护童年,科技构筑安全屏障
科技·物联网·安全·小程序·宠物·web app·智能手表
SPFFC189380330532 个月前
AI玩具排线专业生产与全球营销策略
人工智能·学习·智能手机·显示器·智能手表·平板·游戏机
3DVisionary3 个月前
工业级蓝光三维扫描仪:助力汽车零部件高精度检测与质量提升
汽车·智能手表·汽车零部件检测·蓝光三维扫描技术·高精度测量·质量控制与优化·智能制造解决方案
小白嘎嘎4 个月前
智能手表:小恐龙游戏
游戏·智能手表
Svan.5 个月前
Portable Watch:基于STM32的便携智能手表
arm开发·驱动开发·stm32·嵌入式硬件·硬件工程·pcb工艺·智能手表