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

相关推荐
萧技电创EIIA27 分钟前
基于stc12单片机的PID恒温烙铁设计
单片机·嵌入式硬件·pid过程控制
光子物联单片机2 小时前
STM32G474单片机开发入门(八)内部FLASH详解及读写实战
stm32·单片机·嵌入式硬件·mcu
BreezeJuvenile2 小时前
通用定时器_输入捕获介绍及案例实操
stm32·单片机·嵌入式硬件·输入捕获·通用定时器
时空自由民.3 小时前
无人机系统耗电,低功耗管理问题解决方法(chatgpt)
单片机·嵌入式硬件·无人机
时空自由民.3 小时前
无人机系统耗电,低功耗管理问题解决方法(腾讯元宝)
单片机·嵌入式硬件·无人机
清风6666664 小时前
基于单片机的双档输出数字直流电压源设计
单片机·mongodb·毕业设计·nosql·课程设计
牛马大师兄4 小时前
STM32独立看门狗IWDG与窗口看门狗WWDG知识梳理笔记
笔记·stm32·单片机·嵌入式硬件·嵌入式·看门狗
夜月yeyue4 小时前
STM32 Flash 访问加速器详解(ART Accelerator)
linux·单片机·嵌入式硬件·uboot·bootloard
A9better5 小时前
嵌入式开发学习日志37——stm32之USART
stm32·嵌入式硬件·学习
国科安芯9 小时前
ASP4644芯片低功耗设计思路解析
网络·单片机·嵌入式硬件·安全