【Proteus仿真】【STM32单片机】智能助眠机系统设计

文章目录


一、功能简介

本项目使用Proteus8仿真STM32单片机控制器,使用蜂鸣器闹铃模块、LCD1602显示模块、心率血氧模块、PCF8691 ADC模块、按键模块等。

主要功能:

系统运行后,LCD1602显示传感器采集的心率和血氧值以及当前时间;可通过K3键进入时间修改模式,K3用于切换时、分、秒,K1和K2键调节;时间修改完成后可按下K4键保存并返回主界面。

可通过K4键进入助眠和起床闹铃设置模式,K4用于切换助眠时/分,起床时/分,K1和K2键调节。闹铃设置好后可按下K3键保存并返回主界面。若当前时间到达助眠时间或起床闹钟时间,则开启蜂鸣器闹铃,可通过K2键取消正在闹铃。

正常界面下,可通过K1键查阅监测心率和血氧的数据信息,LCD1602显示心率及血氧的最小和最大值。


二、软件设计

c 复制代码
/*
作者:嗨小易(QQ:3443792007)

*/


//系统数据显示
void sys_data_show(void)
{
	while(1)
	{
		//未查阅
		if(sys_ctrl.find==0)
		{
			//未进入设置闹钟模式
			if(sys_ctrl.set_alarm_mode==0)
			{
				//显示时间
				lcd1602_show_nums(6,0,sys_ctrl.hour,2,0x80);
				lcd1602_show_nums(9,0,sys_ctrl.min,2,0x80);
				lcd1602_show_nums(12,0,sys_ctrl.sec,2,0x80);
					
				//心率显示
				lcd1602_show_nums(3,1,sys_ctrl.heart,3,0);
				//血氧显示
				lcd1602_show_nums(12,1,sys_ctrl.oxygen,3,0);
				
				//时间调节位置闪烁
				switch(sys_ctrl.set_time_mode)
				{
					case 1://时
						lcd1602_show_string(6,0,"  ");
						delay_ms(50);
						lcd1602_show_nums(6,0,sys_ctrl.hour,2,0x80);
						break;
					case 2://分
						lcd1602_show_string(9,0,"  ");
						delay_ms(50);
						lcd1602_show_nums(9,0,sys_ctrl.min,2,0x80);
						break;
					case 3://秒
						lcd1602_show_string(12,0,"  ");
						delay_ms(50);
						lcd1602_show_nums(12,0,sys_ctrl.sec,2,0x80);
						break;
				}	
			}
			//进入闹钟设置模式
			else
			{
				//显示助眠时间
				lcd1602_show_nums(7,0,sys_ctrl.alarm_time[0][0],2,0x80);
				lcd1602_show_nums(10,0,sys_ctrl.alarm_time[0][1],2,0x80);
				//显示起床时间
				lcd1602_show_nums(7,1,sys_ctrl.alarm_time[1][0],2,0x80);
				lcd1602_show_nums(10,1,sys_ctrl.alarm_time[1][1],2,0x80);
				
				//时间调节位置闪烁
				switch(sys_ctrl.set_alarm_mode)	
				{
					case 1://助眠时
						lcd1602_show_string(7,0,"  ");
						delay_ms(50);
						lcd1602_show_nums(7,0,sys_ctrl.alarm_time[0][0],2,0x80);
						break;
					case 2://助眠分
						lcd1602_show_string(10,0,"  ");
						delay_ms(50);
						lcd1602_show_nums(10,0,sys_ctrl.alarm_time[0][1],2,0x80);
						break;
					case 3://起床时
						lcd1602_show_string(7,1,"  ");
						delay_ms(50);
						lcd1602_show_nums(7,1,sys_ctrl.alarm_time[1][0],2,0x80);
						break;
					case 4://起床分
						lcd1602_show_string(10,1,"  ");
						delay_ms(50);
						lcd1602_show_nums(10,1,sys_ctrl.alarm_time[1][1],2,0x80);
						break;
				}	
			}	
		}
		//正在查阅
		else
		{
			//显示心率最小和最大值
			lcd1602_show_nums(8,0,sys_ctrl.heart_lh[0],3,0x80);
			lcd1602_show_nums(12,0,sys_ctrl.heart_lh[1],3,0x80);
			//显示血氧最小和最大值
			lcd1602_show_nums(8,1,sys_ctrl.oxygen_lh[0],3,0x80);
			lcd1602_show_nums(12,1,sys_ctrl.oxygen_lh[1],3,0x80);	
		}

		break;			
	}
}


//系统数据设置
void sys_data_set(void)
{
	u8 key=0;
	static u8 oneflag=0;
	
	key=KEY_Scan(0);
	//设置时间
	if(key==KEY3_PRESS)
	{
		//未进入设置闹钟模式
		if(sys_ctrl.set_alarm_mode==0)
		{
			TIM_Cmd(TIM2,DISABLE);//关闭定时器
			sys_ctrl.set_time_mode++;
			if(sys_ctrl.set_time_mode>=4)sys_ctrl.set_time_mode=1;	
		}
		//闹钟设置模式,确定
		else
		{
			oneflag=0;
			sys_ctrl.set_alarm_mode=0;
			sys_open_show();//开机界面显示
			TIM_Cmd(TIM2,ENABLE);//开启定时器	
		}		
	}
	//加
	else if(key==KEY1_PRESS)
	{
		//时间设置模式
		switch(sys_ctrl.set_time_mode)
		{
			case 1://时
				sys_ctrl.hour++;
				if(sys_ctrl.hour>23)sys_ctrl.hour=0;
				break;
			case 2://分
				sys_ctrl.min++;
				if(sys_ctrl.min>59)sys_ctrl.min=0;
				break;
			case 3://秒
				sys_ctrl.sec++;
				if(sys_ctrl.sec>59)sys_ctrl.sec=0;
				break;
		}	
		//闹钟设置模式
		switch(sys_ctrl.set_alarm_mode)
		{
			case 1://助眠时
				sys_ctrl.alarm_time[0][0]++;
				if(sys_ctrl.alarm_time[0][0]>23)sys_ctrl.alarm_time[0][0]=0;
				break;
			case 2://助眠分
				sys_ctrl.alarm_time[0][1]++;
				if(sys_ctrl.alarm_time[0][1]>59)sys_ctrl.alarm_time[0][1]=0;
				break;
			case 3://起床时
				sys_ctrl.alarm_time[1][0]++;
				if(sys_ctrl.alarm_time[1][0]>23)sys_ctrl.alarm_time[1][0]=0;
				break;
			case 4://起床分
				sys_ctrl.alarm_time[1][1]++;
				if(sys_ctrl.alarm_time[1][1]>59)sys_ctrl.alarm_time[1][1]=0;
				break;		
		}
		//正常模式下,查阅血氧心率信息
		if(sys_ctrl.set_time_mode==0 && sys_ctrl.set_alarm_mode==0)
		{
			sys_ctrl.find=!sys_ctrl.find;
			//查阅
			if(sys_ctrl.find==1)
			{
				lcd1602_clear();
				lcd1602_show_string(0,0," Heart->000-000");
				lcd1602_show_string(0,1,"Oxygen->000-000");		
			}
			//退出查阅
			else
			{
				sys_open_show();//开机界面显示	
			}	
		}	
	}
	//减
	else if(key==KEY2_PRESS)
	{
		//时间设置模式
		switch(sys_ctrl.set_time_mode)
		{
			case 1://时
				sys_ctrl.hour--;
				if(sys_ctrl.hour<0)sys_ctrl.hour=23;
				break;
			case 2://分
				sys_ctrl.min--;
				if(sys_ctrl.min<0)sys_ctrl.min=59;
				break;
			case 3://秒
				sys_ctrl.sec--;
				if(sys_ctrl.sec<0)sys_ctrl.sec=59;
				break;
		}
		//闹钟设置模式
		switch(sys_ctrl.set_alarm_mode)
		{
			case 1://助眠时
				sys_ctrl.alarm_time[0][0]--;
				if(sys_ctrl.alarm_time[0][0]<0)sys_ctrl.alarm_time[0][0]=23;
				break;
			case 2://助眠分
				sys_ctrl.alarm_time[0][1]--;
				if(sys_ctrl.alarm_time[0][1]<0)sys_ctrl.alarm_time[0][1]=59;
				break;
			case 3://起床时
				sys_ctrl.alarm_time[1][0]--;
				if(sys_ctrl.alarm_time[1][0]<0)sys_ctrl.alarm_time[1][0]=23;
				break;
			case 4://起床分
				sys_ctrl.alarm_time[1][1]--;
				if(sys_ctrl.alarm_time[1][1]<0)sys_ctrl.alarm_time[1][1]=59;
				break;		
		}
		sys_ctrl.alarm_flag=0;//解除闹铃			
	}
	//确定
	else if(key==KEY4_PRESS)
	{
		//时间设置模式
		if(sys_ctrl.set_time_mode!=0)
		{
			sys_ctrl.set_time_mode=0;
			TIM_Cmd(TIM2,ENABLE);//开启定时器	
		}
		//闹钟设置模式
		else
		{
			TIM_Cmd(TIM2,DISABLE);//关闭定时器
			if(oneflag==0)//只显示1次界面
			{
				oneflag=1;
				lcd1602_clear();
				lcd1602_show_string(0,0,"Sleep->00:00");
				lcd1602_show_string(0,1,"Alarm->00:00");	
			}
			sys_ctrl.set_alarm_mode++;
			if(sys_ctrl.set_alarm_mode>=5)sys_ctrl.set_alarm_mode=1;	
		}	
	}
}

//系统功能控制
void sys_fun_ctrl(void)
{
	//还未开启闹铃
	if(sys_ctrl.alarm_flag==0)
	{
		//正常模式下,检查时间是否达到
		if(sys_ctrl.set_time_mode==0 && sys_ctrl.set_alarm_mode==0)
		{
			//如果助眠时间达到,开启蜂鸣器提示音
			if(sys_ctrl.alarm_time[0][0]==sys_ctrl.hour)//时
			{
				if(sys_ctrl.alarm_time[0][1]==sys_ctrl.min)//分
				{
					if(sys_ctrl.sec==0)//秒
						sys_ctrl.alarm_flag=1;//闹铃	
				}		
			}
			//如果起床时间到达,开启蜂鸣器提示音
			if(sys_ctrl.alarm_time[1][0]==sys_ctrl.hour)//时
			{
				if(sys_ctrl.alarm_time[1][1]==sys_ctrl.min)//分
				{
					if(sys_ctrl.sec==0)//秒
						sys_ctrl.alarm_flag=1;//闹铃	
				}			
			}
		}		
	}
	//开始闹铃
	else 
	{
		beep_alarm(1,10000);
	}
}

//应用控制系统
void appdemo_show(void)
{
	u8 i=5;
	sys_parm_init();//系统参数初始化
	KEY_Init();
	BEEP_Init();
	pcf8591_init();
	lcd1602_init();//LCD1602初始化
	TIM2_Init(400-1,70);//定时10ms
	while(i--)
	{
		//血氧心率获取
		sys_ctrl.heart=pcf8591_read_adcvalue(1);
		sys_ctrl.heart=cal_map(sys_ctrl.heart,0,255,0,200);
		sys_ctrl.heart_lh[0]=sys_ctrl.heart;//初始值作为最小值
		sys_ctrl.heart_lh[1]=sys_ctrl.heart;//初始值作为最大值

		sys_ctrl.oxygen=pcf8591_read_adcvalue(0);
		sys_ctrl.oxygen=cal_map(sys_ctrl.oxygen,0,255,0,200);
		sys_ctrl.oxygen_lh[0]=sys_ctrl.oxygen;//初始值作为最小值
		sys_ctrl.oxygen_lh[1]=sys_ctrl.oxygen;//初始值作为最大值

		delay_ms(100);
	}
	sys_open_show();//系统开机界面显示
	TIM_Cmd(TIM2,ENABLE); //打开定时器

	while(1)
	{
		sys_data_get();//系统数据获取
		sys_data_show();//系统数据显示
		sys_data_set();//系统数据设置
		sys_fun_ctrl();//系统功能控制		
	}
}

三、实验现象

B站演示视频:https://space.bilibili.com/444388619



联系作者

视频地址:https://space.bilibili.com/444388619/video

专注于51单片机、STM32、国产32、DSP、Proteus、ardunio、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。

相关推荐
TESmart碲视42 分钟前
HKS201-M24 大师版 8K60Hz USB 3.0 适用于 2 台 PC 1台显示器 无缝切换 KVM 切换器
单片机·嵌入式硬件·物联网·游戏·计算机外设·电脑·智能硬件
花落已飘2 小时前
STM32中实现shell控制台(shell窗口输入实现)
stm32·单片机·嵌入式硬件
花落已飘2 小时前
STM32中实现shell控制台(命令解析实现)
stm32·shell
没有钱的钱仔2 小时前
STM32低功耗模式全面指南
css·stm32·css3
牵牛老人4 小时前
Qt处理USB摄像头开发说明与QtMultimedia与V4L2融合应用
stm32·单片机·qt
宇钶宇夕5 小时前
针对工业触摸屏维修的系统指南和资源获取途径
单片机·嵌入式硬件·自动化
和风化雨6 小时前
stm32的三种开发方式
stm32·单片机·嵌入式硬件
kanhao1006 小时前
三态逻辑详解:单片机GPIO、计算机总线系统举例
单片机·嵌入式硬件
竹照煜_ysn9 小时前
STM32
stm32·单片机·嵌入式硬件
蓬荜生灰10 小时前
永磁无刷电机旋转原理
单片机·嵌入式硬件