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

说明图:

主程序代码如下,可以修改为自己适用代码
#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;
}
}
}
}
}