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


一、功能简介

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

主要功能:
系统运行后,LCD1602显示传感器采集的心率和血氧值以及当前时间;可通过K3键进入时间修改模式,K3用于切换时、分、秒,K1和K2键调节;时间修改完成后可按下K4键保存并返回主界面。
可通过K4键进入助眠和起床闹铃设置模式,K4用于切换助眠时/分,起床时/分,K1和K2键调节。闹铃设置好后可按下K3键保存并返回主界面。若当前时间到达助眠时间或起床闹钟时间,则开启蜂鸣器闹铃,可通过K2键取消正在闹铃。正常界面下,可通过K1键查阅监测心率和血氧的数据信息,LCD1602显示
心率及血氧的最小和最大值。

主要功能如下:
1、心率/血氧监测
2、助眠/起床闹钟设置
3、闹铃提醒
4、LCD1602液晶显示


二、软件设计

/*
作者:嗨小易(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)
		{
			TR1=0;//关闭定时器
			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();//开机界面显示
			TR1=1;//开启定时器	
		}		
	}
	//加
	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;
			TR1=1;//开启定时器	
		}
		//闹钟设置模式
		else
		{
			TR1=0;//关闭定时器
			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 appdemo_show(void)
{
	u8 i=5;
	sys_parm_init();//系统参数初始化
	lcd1602_init();
	time1_init();
	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();//系统开机界面显示
	TR1=1;//开启定时器

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

//定时器1中断函数
void time1(void) interrupt 3 
{
	static u8 i=0;

	TH1=0XDC;	//给定时器赋初值,定时10ms
	TL1=0X00;
	i++;
	if(i>=100)//1秒到
	{
		i=0;
		sys_ctrl.sec++;
		if(sys_ctrl.sec>=60)//1分
		{
			sys_ctrl.sec=0;
			sys_ctrl.min++;
			if(sys_ctrl.min>=60)//1小时
			{
				sys_ctrl.min=0;
				sys_ctrl.hour++;
				if(sys_ctrl.hour>=24)sys_ctrl.hour=0;
			}
		}
	}
}


三、实验现象

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


联系作者

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

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值