功能模块整合

时间:2024-11-25 06:58:48

程序架构

第一部分:所用到模块的初始化

第二部分:中断部分。利用定时中断实现呼吸灯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]++;
		
		
		//运行指示灯500ms
		if(timer_buff[1] >= 500)
		{
			timer_buff[1] = 0;
			LED_OVERTURN;
			
		}
		
		//RTC显示时间 1000ms
		if(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 header

u8 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); 
	
}