基于STM32的智能⼿环
前⾔
这是本⼈⼤四上学期实习时做的⼀个项⽬,希望对各位有所帮助。
物料清单
STM32F411CEU6型号的单⽚机
HP6⼼率⾎压模块
MPU6050六轴传感器模块
SHT20温湿度传感器
OLED显⽰屏
直流电机
五向按键
实现的功能
1.显⽰当前⽇期与时间
2.温湿度测量
3.⼼率测量
4.⾎压测量
5.步数统计
6.闹钟设置
7.显⽰当前的闹钟
8.通过按键选择不同的功能
成果展⽰
菜单选项
通过五向按键的左右两侧切换不同的功能页⾯,按中间按键确认进⼊,再按中间按键退出
(注:右上那盏灯是在测量完⼼率后忘了调⽤关闭PWM灯的函数)
按确认按键进⼊后
图1:温湿度测量。
图2:⼼率测量前的提⽰。
图3:⼼率测量结果–约5s出结果
图4:⾎压测量结果–约1min出结果
图5:闹钟设置–通过上下选择时分秒,左右设置数值,中确认并退出
图6:闹钟响应–动图且电机转动。
图7:显⽰当前设置的闹钟–五向按键往下拨
图8:显⽰步数、卡路⾥、距离
主要代码
main.c
#include"includes.h"
//时间显⽰:0 温湿度:1 ⼼率测量:2 ⾎压测量:3 计步数:4设置闹钟:5
//key_ok值:left减1,right加1;up归0
intmain(void)
{
//初始化
LED_init();
Breath_Light_Init();
Key_init();
Motor_Init();
exti0_init();
tim5_init();
OLED_Init();
Adc_Init();
Sht20_Init();
My_Rtc_Init();
Hp6_Pin_Init();
Mpu6050_Init();
WatchInfo_init();
Rtc_Wakeup_Init();
kaiji_gif();//开机动画
OLED_Clear(0);
while(1)
{
//在tim5的中断服务函数中改变,key_ok值:left减1,right加1;up归0,down:key_ok=6
switch(key_ok)
{
ca0:show_tim();brea释迦牟尼的故事 k;//显⽰当前时间
ca1:show_TH();break;//显⽰当前温湿度
ca2:show_rate();break;//⼼率测量
ca3:show_press();break;//⾎压测量
ca4:show_step();break;//步数计数
ca5:show_tclock();break;//设置闹钟
ca6:show_curclock();break;//显⽰当前闹钟
}
end_work();//收尾⼯作
}
}
show.c–各个功能模块的实现
#include"show.h"
intkey_ok=0;
intkey_enter=0;//确认按钮
//开机动画
voidkaiji_gif(void)
{
Show_Pic(0,0,(u8*)gImage_20);
Delay_ms(100);
Show_Pic(0,0,(u8*)gImage_21);
Delay_ms(100);
Show_Pic(0,0,大芋头 (u8*)gImage_22);
Delay_ms(100);
Show_Pic(0,0,(u8*)gImage_23);
Delay_ms(100);
Show_Pic(0,0,(u8*)gImage_24);
Delay_ms(100);
Show_Pic(0,0,(u8*)gImage_25);
Delay_ms(100);
Show_Pic(0,0,(u千的英语 8*)gImage_26);
Delay_ms(100);
Show_Pic(0,0,(u8*)gImage_27);
Delay_ms(100);
Show_Pic(0,0,(u8*)gImage_28);
Delay_ms(100);
Show_Pic(0,0,(u8*)gImage_29);
Delay_ms(100);
Show_Pic(0,0,(u8*)gImage_30);
Delay_ms(100);
Show_Pic(0,0,(u8*)gImage_31);
Delay_ms(100);
Show_Pic(0,0,(u8*)gImage_32);
Delay_ms(1000);
}
//显⽰当前时间
voidshow_tim(void)
{
u8buf[50]={0};
TIME_DATA*p;
//OLED_Clear(0);
while(key_ok==0)
{
Show_Chine(0,20,4,tim);
p=RTC_getDateAndTime();
sprintf((char*)buf,"20%02d-%英勇的近义词 02d-%02d-%d",p->year,p->month,p->day,p->week);
Show_String(2,0,buf);
sprintf((char*)buf,"%02d:%02d:%02d",p->hour,p->minute,p->cond);
Show_String(4,0,buf);
}
}
//测量温湿度
voidshow_TH(void)
{
floatTem,Hum;
u8buf[50]={0},clear_flag=1;
Show_Pic(0,0,(u8*)RT_Picture);
Show_Chine(2,49,5,rt);
Delay_ms(800);
while(key_enter)
{
if(clear_flag==1)//清屏⼀次
{
OLED_Clear(0);
clear_flag=0;
}
Show_Chine(0,20,5,cur_TH);
Show_Chine(0,20,5,cur_TH);
Tem=Sht20_Mesaure(TEMPEATURE);
Hum=Sht20_Mesaure(HUMIDITY);
sprintf((char*)buf,"Tem:%.2fC",Tem);
Show_String(2,0,buf);
sprintf((char*)buf,"Hum:%.2f%%",Hum);
Show_String(4,0,buf);
Delay_ms(500);
}
}
//测量⼼率
u8rate_flag=0;
voidshow_rate(void)
{
u8data[24]={0},buf[50]={0},clear_flag=1;
Show_Pic(0,0,(u8*)HR_Picture);
Show_Chine(2,65,江苏考试教育院 4,Hr);
Delay_ms(800);
while(key_enter)
{
rate_flag=1;
//清屏两次
if(clear_flag==1)
{
OLED_Clear(0);
Hr_Open();//开启⼼率测量
Show_Pic(0,0,(u8*)HR_Tip);
Delay_ms(5000);
clear_flag=2;
}
if(clear_flag==2)
{
OLED_Clear(0);
clear_flag=0;
}
Get_Hr();//得到测量数据
Get_Result(data);//得到测量结果
PWN_Led();
sprintf((char*)buf,"heartrate:%d",data[7]);
Show_String(2,0,buf);
Delay_ms(1250);
}
}
//测量⾎压
u8Bm_flag=0;
voidshow_press(void)
{
u8data[24]={0},buf[50]={0},clear_flag=1;
Show_Pic(0,0,(u8*)BM_Picture);
Show_Chine(2,65,4,Bm);
Delay_ms(800);
while(key_enter)
{
Bm_flag=1;
//清两次屏幕
if(clear_flag==1)
{
OLED_Clear(0);
Bm_Open();//开启⾎压测量
Show_Pic(0,0,(u8*)BM_Tip);
Delay_ms(2560);
clear_flag=2;
}
if(clear_flag==2)
{
OLED_Clear(0);
clear_flag=0;
}
Get_Bm();//得到测量数据
Get_Result(data);//得到测量结果
if(data[7]==0)
{
//printf("正在测量中!rn");
PWN_Led();//PWM灯
Show_String(2,10,(u8*)"");
}
elif(data[7]==1)
{
sprintf((char*)buf,"Hight:%d",data[10]);
Show_Str智能手机的英文 ing(2,0,buf);
sprintf((char*)buf,"Low:%d",data[11]);
Show_String(4,0,buf);
Bm_Clo();//关闭测量
TIM_SetCompare2(TIM3,0);//关灯
}
elif(data[7]==2)
{
Show_String(2,0,(u8*)"Measureerror!");
Delay_ms(1500);
key_enter=0;//退出测量
Bm_Clo();//关闭测量
TIM_SetCompare2(TIM3,0);//关灯
}
Delay_ms(1280);
}
}
//步数计数
voidshow_step(void)
{
u8err,clear_flag=1;
u8uiBuf[40];
staticsportsInfo_turSportsInfo;
statictimStamp_ttimStamp;
staticu8tempSecond;//保存秒钟暂态量
///timStamp_t*rtcTime;//获取年⽉⽇时分秒
TIME_DATA*rtcTime;//获取年⽉⽇时分秒
accValue_taccValue;
Show_Pic(0,0,(u8*)Step_Pic);
Show_Chine(2,65,4,step);
Delay_ms(800);
while(key_enter)
{
if(clear_flag==1)
{
OLED_Clear(0);
clear_flag=0;
}
Mcu_Read_Mpu6050_XYZ(&accValue);//得到加速度传感器数据
rtcTime=RTC_getDateAndTime();//获取当前RTC的值
if(tempSecond!=)//秒更新
{
tempSecond=;
MsCount=0;//20ms计数变量清零
}
el//秒不更新,1秒等于50*20ms
{
MsCount++;//20ms计数变量++
}
=rtcTime->hour;
=rtcTime->minute;
=rtcTime->cond;
//将三轴数据转换为以g为单位的数据
=((float)(int)/16384)*10;
=((float)(int)/16384)*10;
=((float)(int)/16384)*10;
urSportsInfo=*onSensorChanged(&accValue,&timStamp,WatchInfo_getUrInfo(&err));//调⽤计数算法
sprintf((char*)uiBuf,"Step:%05d",unt);//显⽰步数
Show_String(0,0,uiBuf);
sprintf((char*)uiBuf,"kal:%.1fKAL",es);//显⽰卡路⾥
Show_String(2,2,uiBuf);
sprintf((char*)uiBuf,"dis:%.1fM",ce);//显⽰⾥程
Show_String(4,0,uiBuf);
Delay_ms(20);//以50Hz的频率去读取三轴加速度的XYZ轴加速度值
}
}
//设置闹钟
u8tclk_flag=0;
voidshow_tclock(void)
{
u8clear_flag=1;
OLED_Clear(0);
Show_Pic(0,0,(u8*)Clock_Pic);//闹钟图⽚
Show_Chine(2,65,4,clock);//⽂字:闹钟设置
Delay_ms(800);
while(key_enter)
{
tclk_flag=1;
if(clear_flag教育研究论文 ==1)//进⼊后清⼀次屏
{
OLED_Clear(0);
Show_String(0,0,(u8*)"week:0");
Show_String(2,0,(u8*)"hour:0");
Show_String(4,0,(u8*)"minute:0");
clear_flag=0;
}
alarm_control();//设置闹钟
}
}
//显⽰当前闹钟
vo出塞二首其一 idshow_curclock(void)
{
u8buf[50];
OLED_Clear(0);
Show_Chine(0,20,4,cur_clk);//⽂字:当前闹钟
sprintf((char*)buf,"%d-%02d-%02d",,,);
Show_String(2,20,buf);
Delay_ms(1000);
}
//收尾⼯作
voidend_work(void)
{
//进⼊后且退出时,开启闹钟
if(tclk_flag==1&&key_enter==0)
{
tclk_flag=0;//清标志位
Rtc_Alarm(,,,0);//设置闹钟
OLED_Clear(0);
Show_String(2,0,(u8*)"tsuccess!");//提⽰设置成功
Delay_ms(1500);
key_enter=0;//防⽌⼿抖,多次进⼊
}
//进⼊后且退出时,关闭测量
if(rate_flag==1&&key_enter==0)
{
rate_flag=0;
Hr_Clo();//关闭测量
TIM_SetCompare2(TIM3,0);//关灯
}
if(Bm_flag==1&&key_enter==0)
{
Bm_flag=0;
Bm_Clo();//关闭测量
TIM_SetCompare2(TIM3,0);
}
key_enter=0;
OLED_Clear(0);//清屏
}
必知宏定义
#defineLEFT(ADC_value>=4085)//3.3v
#defineRIGHT(ADC_value>2035&&ADC_value<2050)//4096/2
#defineUP(ADC_value>1020&&ADC_value<1030)//4096/4
#defineDOWN(ADC_value>1360&&ADC_value<1370)//4096/3
定时器5的中断服务函数
通过不同的key_ok值切换不能的功能模块
externintkey_ok;
//定时器5的中断服务函数
voidTIM5_IRQHandler(void)
{
//判断标志位,未按下确认键时进⼊
if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET&&key_enter==0)
{
if(LEFT)
{
Delay_ms(10);
if(LEFT)
{
while(ADC_value>5);
key_ok--;
if(key_ok<0)key_ok=5;
}
}
elif(RIGHT)
{
Delay_ms(10);
if(RIGHT)
{
while(ADC_value>5);
key_ok++;
if(key_ok>5)
{
key_ok=0;
}
}
}
elif(UP)
{
Delay_ms(10);
if(UP)
while(ADC_value>5);
key_ok=0;
}
elif(DOWN)
{
Delay_ms(10);
if(DOWN)
while(ADC_value>5);
key_ok=6;
}
}
//清空标志位
TIM_ClearITPendingBit(TIM5,TIM_IT_Update);
}
外部中断0服务函数–50ms1次
使⽤key_enter全局变量进⼊/退出功能模块
//外部中断0服务函数,改变key_enter值
voidEXTI0_IRQHandler(void)
{
//判断是否有中断请求
if(EXTI_GetITStatus(EXTI_Line0)==SET)
{
key_enter=!key_enter;//⼀开始为0
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
本文发布于:2023-03-22 06:38:39,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/b6119b2cb7d4b45fdfca92c1df6a6004.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:血压监测手环.doc
本文 PDF 下载地址:血压监测手环.pdf
留言与评论(共有 0 条评论) |