【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设计,视频分享,技术交流。

相关推荐
QQ19284999062 小时前
基于STM32无刷直流电机调速蓝牙APP无线监测控制系统
stm32·嵌入式硬件·mongodb
好家伙VCC6 小时前
STM32与51单片机的区别:是否应该直接学习STM32?
stm32·学习·51单片机
szpc16216 小时前
28V_1MHZ电子烟,无线鼠标,医疗器械等专用恒频升压转换器超小体积封装
单片机·嵌入式硬件·计算机外设
luckyluckypolar8 小时前
STM32——SPI
stm32·单片机·嵌入式硬件·物联网
极客小张9 小时前
基于STM32MP157与OpenCV的嵌入式Linux人脸识别系统开发设计流程
linux·stm32·单片机·opencv·物联网
浅陌pa10 小时前
24:RTC实时时钟
c语言·stm32·单片机·嵌入式硬件
敲上瘾10 小时前
多态的使用和原理(c++详解)
开发语言·数据结构·c++·单片机·aigc·多态·模拟
小熊在忙fpga11 小时前
STM32如何修改外部晶振频率和主频
stm32·单片机·嵌入式硬件
学习日记hhh12 小时前
STM32G431RBT6(蓝桥杯)串口(发送)
stm32·单片机·嵌入式硬件
老李的森林12 小时前
嵌入式开发--STM32延时函数重构
stm32·单片机·嵌入式硬件·重构·延时