程序架构
第一部分:所用到模块的初始化
第二部分:中断部分。利用定时中断实现呼吸灯、RTC显示时间、动态图片切换、超时检测以及息屏等功能
第三部分:主逻辑循环部分。采用的是状态机扫描的方式进行的,根据按键控制页编号变量,然后页编号控制相应的功能。
具体程序如下:
主逻辑循环部分:
int a = 10;int main(void)
{u8 key = 0;function_init();/*开机功能*/page_open();a++;while(1){key = fun_key_scan();//按键控制页编号变量if(key == KEY_Right && key_ok_flag==0){page_flag = 1;timer_buff[7] = 0; //息屏计时开始OLED_clear();if(!oled_sta_flag) //不息屏状态{page++;if(page>6){page = 1;}}else{OLED_writeByte(0xAF,OLED_CMD);oled_sta_flag = 0;}}else if(key == KEY_Left && key_ok_flag==0){page_flag = 1;timer_buff[7] = 0; //息屏计时开始OLED_clear();if(!oled_sta_flag){page--;if(page<1){page = 6;} }else{OLED_writeByte(0xAF,OLED_CMD);oled_sta_flag = 0;}}//页编号变量控制界面显示switch(page){case 1: function_page1();break;case 2: function_page2(key);break;case 3: function_page3();break;case 4: function_page4();break;case 5: function_page5();break;case 6: function_page6();break;}}return 0;
}
中断部分:
/***********************************************
*函数名 :TIM1_BRK_TIM9_IRQHandler
*函数功能 :TIM9中断服务函数
*函数参数 :无
*函数返回值:无
*函数描述 :
************************************************/
u32 timer_buff[10];
u8 pic_n = 0;
RTC_t val;
u8 heart_pic_n = 0;
u8 oled_sta_flag = 0;
void TIM1_BRK_TIM9_IRQHandler(void)
{//判断是定时器9的更新中断信号触发if(TIM9->SR & (1<<0)){//清除中断标志位TIM9->SR &= ~(1<<0);//紧急事件timer_buff[1]++;timer_buff[2]++;timer_buff[3]++;timer_buff[4]++;timer_buff[5]++;timer_buff[6]++;timer_buff[7]++;//运行指示灯500msif(timer_buff[1] >= 500){timer_buff[1] = 0;LED_OVERTURN;}//RTC显示时间 1000msif(timer_buff[2] >= 1000){timer_buff[2] = 0;//在设置时间模式下暂听获取时间if(key_ok_flag==0 && (page==2 || page==3)){val = get_time();fun_flag = 1;}}//timer_buff[3]== 100解锁按键标志位if(timer_buff[3] == 100){ MOTOR_VAL = 0;}//动态图片切换const u8 *pics[] = {pic_0,pic_1,pic_2,pic_3,pic_4,pic_5,pic_6};if(timer_buff[4] >= 50){ if(page==1){pic_n++;if(pic_n>=102){pic_n=0;} fun_flag = 1;}//oled_dis_pic(0,1,64,64,tkr64x64[pic_n]); timer_buff[4] = 0;}//心率开始5秒失败退出时间定时if(timer_buff[5] == 5000){ }//心率动态图if(timer_buff[6] == 300){ if(page == 4){heart_pic_n++;if(heart_pic_n>1){heart_pic_n=0;}fun_flag = 1;}timer_buff[6] = 0;}//10s息屏if(timer_buff[7] >= 10000){ if(page !=4 && page != 5 && key_ok_flag==0){OLED_writeByte(0xAE,OLED_CMD);oled_sta_flag = 1;}timer_buff[7] = 0;}}
}
每页功能模块部分:
#include "main.h" // Device headeru8 page_flag = 1;
u8 fun_flag = 1;
u8 key_ok_flag = 0;
u8 page = 0;RTC_t time = {2024,4,17,3,15,30,45};/***********************************************
*函数名 :function_init
*函数功能 :初始haul配置
*函数参数 :无
*函数返回值:无
*函数描述 :
************************************************/
void function_init(void)
{NVIC_SetPriorityGrouping(5); //抢占2位 响应2位led_init(); //LED灯初始化配置usart1_init(115200); //串口初始化tim2_ch3_pwm_motor(); //振动电机初始化fun_key_init(); //五方向按键OLED_init(); //OLED初始化RTC_init(time); //RTC初始化sht20_init(); //SHT20初始化Hp_6_init(); //HP6初始化MPU6050_init(); //MPU6050初始化配置tim9_interrupt_ms(1);
}/***********************************************
*函数名 :page_open
*函数功能 :开机界面
*函数参数 :无
*函数返回值:无
*函数描述 :
************************************************/
void page_open(void)
{timer_buff[3] = 101;oled_dis_pic(0,2,128,64,open_pic);MOTOR_VAL = 1000;tim11_delay_ms(500);MOTOR_VAL = 0;OLED_clear();page++;
}/***********************************************
*函数名 :function_page1
*函数功能 :1号页功能
*函数参数 :无
*函数返回值:无
*函数描述 :动态图
************************************************/
void function_page1(void)
{//只执行一次的程序if(page_flag == 1){oled_dis_str(3,70,"信盈达",16);page_flag = 0;}//执行多次高刷程序if(fun_flag == 1){oled_dis_pic(0,2,64,64,(u8 *)(tkr64x64+pic_n)); fun_flag = 0;}}/***********************************************
*函数名 :function_page2
*函数功能 :2号页功能
*函数参数 :无
*函数返回值:无
*函数描述 :时间显示
************************************************/
void function_page2(u8 key)
{u8 buff[30] = {0};//只执行一次程序if(page_flag){timer_buff[2] = 1000; //到此页面马上获取时间显示printf("你好,第二页\r\n");page_flag = 0;}//执行多次高刷程序if(fun_flag == 1 && key_ok_flag==0){//转换时间成字符串sprintf((char *)buff,"%d.%d.%d ",val.year,val.mon,val.day);oled_dis_str(1,30,buff,16);sprintf((char *)buff,"%02d:%02d:%02d",val.h,val.m,val.s);oled_dis_str(3,0,buff,24);sprintf((char *)buff,"week:%d",val.week);oled_dis_str(6,40,buff,16);fun_flag = 0;}//垂直界面进出设置模式static u8 set_list = 0;static RTC_t t_val;if(key == KEY_OK){key_ok_flag = !key_ok_flag; OLED_clear();//进入到设置界面if(key_ok_flag == 1){set_list = 0;//只显示时间sprintf((char *)buff,"%02d:%02d:%02d",val.h,val.m,val.s);oled_dis_str(2,set_list,buff,24);oled_dis_str(5,set_list,"--",24);t_val = val;printf("获取原始时间\r\n");}//退出设置界面if(key_ok_flag == 0){//如果没有修改时间值,继续获取RTC原本运行时间if(t_val.h!=val.h || t_val.m!=val.m || t_val.s!=val.s){set_time(val);}timer_buff[2] = 1000; //马上获取时间显示}}//定位更改的时间(时 分 秒)else if(key_ok_flag==1 && key == KEY_Right){oled_dis_str(5,set_list," ",24);set_list+=48;if(set_list>96) {set_list=0;}oled_dis_str(5,set_list,"--",24);}else if(key_ok_flag==1 && key == KEY_Left){oled_dis_str(5,set_list," ",24);set_list-=48;if(set_list>200){set_list = 96;}oled_dis_str(5,set_list,"--",24);}//根据定位调整数值 上调else if(key_ok_flag==1 && key == KEY_UP){if(set_list==0) //调整小时{//时间数据结构体中的小时成员val.h++;if(val.h>23) {val.h = 0;}
// sprintf((char *)buff,"%02d",val.h);
// oled_dis_str(2,set_list,buff,24);}else if(set_list==48) //调整分钟{//时间数据结构体中的分钟成员val.m++;if(val.m>59) {val.m = 0;}
// sprintf((char *)buff,"%02d",val.m);
// oled_dis_str(2,set_list,buff,24);}else if(set_list==96) //调整秒{//时间数据结构体中的秒成员val.s++;if(val.s>59) {val.s = 0;}
// sprintf((char *)buff,"%02d",val.s);
// oled_dis_str(2,set_list,buff,24);}sprintf((char *)buff,"%02d:%02d:%02d",val.h,val.m,val.s);oled_dis_str(2,0,buff,24);}//根据定位调整数值 下调 else if(key_ok_flag==1 && key == KEY_Down){if(set_list==0) //调整小时{//时间数据结构体中的小时成员val.h--;if(val.h>200) {val.h = 23;}sprintf((char *)buff,"%02d",val.h);oled_dis_str(2,set_list,buff,24);}else if(set_list==48) //调整分钟{//时间数据结构体中的分钟成员val.m--;if(val.m>200) {val.m = 59;}}else if(set_list==96) //调整秒{//时间数据结构体中的秒成员val.s--;if(val.s>200) {val.s = 59;}}sprintf((char *)buff,"%02d:%02d:%02d",val.h,val.m,val.s);oled_dis_str(2,0,buff,24);}}/***********************************************
*函数名 :function_page3
*函数功能 :3号页功能
*函数参数 :无
*函数返回值:无
*函数描述 :温湿度显示
************************************************/
void function_page3(void)
{TRH_n trh_data; u8 buff[30];//只执行一次程序if(page_flag){if(val.h>=6 && val.h<18) //白天图片{oled_dis_pic(0,0,64,64,sun);}else //黑天{oled_dis_pic(0,0,64,64,night);}//关闭心率HP_6_CloseRate(); page_flag = 0;}//执行多次高刷程序//停留此界面,在这两个时间点变换图片if((val.h==6 || val.h==18) && val.m==0 && val.s==0){page_flag = 1;}//获取温度trh_data = sht20_rec_val(SHT20_T);//转换成字符串sprintf((char *)buff,"T:%0.1f℃",trh_data.t);//显示字符串oled_dis_str(1,65,buff,16);//获取湿度trh_data = sht20_rec_val(SHT20_RH);//转换成字符串sprintf((char *)buff,"RH:%d%%",trh_data.rh);//显示字符串oled_dis_str(4,65,buff,16);}/***********************************************
*函数名 :function_page4
*函数功能 :4号页功能
*函数参数 :无
*函数返回值:无
*函数描述 :心率测量功能
************************************************/
void function_page4(void)
{static u8 err;u8 result = 0;u8 buff[20];static u8 old_val;//只执行一次程序if(page_flag){//关闭血压HP_6_Closebp();//显示界面提示oled_dis_str(1,80,"心率",16);oled_dis_str(4,80,"test",16);oled_dis_pic(0,0,54,54,heart[1]);//开启心率测量err = HP_6_OpenRate();//超时启动报告传感器错误if(err == 0){oled_dis_str(4,80,"err!",16);}page_flag = 0;}//执行多次高刷程序if(fun_flag == 1 && err){oled_dis_pic(0,0,54,54,heart[heart_pic_n]);fun_flag = 0;}//获取心率数据HP_6_GetRateResult(&result); if(result!=0 && err && old_val!=result) {old_val = result;sprintf((char *)buff,"%03d",result);oled_dis_str(4,70,buff,24);} }/***********************************************
*函数名 :function_page5
*函数功能 :5号页功能
*函数参数 :无
*函数返回值:无
*函数描述 :血压测量功能
************************************************/
void function_page5(void)
{u8 bpResult[2] = {0};u8 buff[20];//只执行一次程序if(page_flag){//关闭心率HP_6_CloseRate();//显示测试量血压图片oled_dis_pic(0,0,54,54,bmp);oled_dis_str(1,80,"血压",16);oled_dis_str(3,80,"test",16);//开启血压u8 err = HP_6_Openbp();//超时启动报告传感器错误if(err == 0){oled_dis_str(3,80,"err!",16);}page_flag = 0;}//执行多次高刷程序HP_6_Get_bpResult(bpResult);if(bpResult[0]!=0 && bpResult[1]!=0){sprintf((char *)buff,"H:%3dPa",bpResult[0]);oled_dis_str(3,70,buff,16);sprintf((char *)buff,"L:%3dPa",bpResult[1]);oled_dis_str(5,70,buff,16);}}/***********************************************
*函数名 :function_page6
*函数功能 :6号页功能
*函数参数 :无
*函数返回值:无
*函数描述 :MPU6050
************************************************/
void function_page6(void)
{ACCG_t ag;u8 buff[15];//只执行一次程序if(page_flag){//关闭血压HP_6_Closebp();page_flag = 0;}//执行多次高刷程序//获取六轴数据ag = ReadAcceData();/*显示*/sprintf((char *)buff,"Ax:%0.1f Gx:%0.1f ",ag.x_Axis ,ag.x_Gxis );oled_dis_str(0,2,buff,16);sprintf((char *)buff,"Ay:%0.1f Gy:%0.1f ",ag.y_Axis,ag.y_Gxis);oled_dis_str(2,2,buff,16);sprintf((char *)buff,"Az:%0.1f Gz:%0.1f ",ag.z_Axis,ag.z_Gxis);oled_dis_str(4,2,buff,16); }