【STM32单片机】宠物定时喂食器设计


一、功能简介

本项目使用STM32F103C8T6单片机控制器,使用按键、IIC OLED液晶、蜂鸣器、继电器投喂控制等。
主要功能:
系统运行后,OLED液晶显示初始时间,默认工作在自动投喂模式,可通过矩阵按键S4切换自动/手动模式;当处于手动模式,按下S1键进行投喂开关控制;
当处于自动模式,按下S3键进入投喂时间设置,系统支持3组投喂时间,可按下S3键切换哪一组,再按下S5键选择该组对应的时间位置,按下S1或S2键调节数值,只有设置该组投喂状态为Y时,定时投喂有效。设定好后,按下S6键确定。当时间到达投喂时间,蜂鸣器报警,开启投喂装置,一段时间后自动关闭。


二、软件设计

/*
作者:嗨小易(QQ:3443792007)

*/



//系统数据设置
void sys_data_set(void)
{
	u8 key=0;
	key=KEY_Matrix_Scan();
	//自动手动模式
	if(key==4)
	{
		sys_ctrl.autoflag=!sys_ctrl.autoflag;
		if(sys_ctrl.autoflag==1)
		{
			sys_ctrl.mode=0;
			OLED_ShowString(3*8,16, " ",16);
			OLED_ShowString(3*8,32, " ",16);
			OLED_ShowString(3*8,48, " ",16);
		}
	}
	//手动模式
	if(sys_ctrl.autoflag)
	{
		//投喂开关
		if(key==1)
		{
			if(sys_ctrl.feedflag[0])
			{
				sys_ctrl.feedflag[0]=0;
				LED1=1;//关闭投喂装置
			}
			else
			{
				sys_ctrl.feedflag[0]=1;
				LED1=0;//打开投喂装置
			}
		}
	}
	//自动模式
	else
	{
		//选择要修改的投喂时间模式
		if(key==3)
		{
			sys_ctrl.mode++;
			if(sys_ctrl.mode>3)sys_ctrl.mode=1;
		}
		//进入设置模式
		if(sys_ctrl.mode!=0)
		{
			//在对应模式选择位置
			if(key==5)
			{
				sys_ctrl.cnt++;
				if(sys_ctrl.cnt>2)sys_ctrl.cnt=0;
			}
			//加
			else if(key==1)
			{
				switch(sys_ctrl.mode)
				{
					case 1://投喂1
						switch(sys_ctrl.cnt)
						{
							case 0://时
								sys_ctrl.time[0][0]++;
								if(sys_ctrl.time[0][0]>23)sys_ctrl.time[0][0]=0;
								break;
							case 1://分
								sys_ctrl.time[0][1]++;
								if(sys_ctrl.time[0][1]>59)sys_ctrl.time[0][1]=0;
								break;
							case 2://开关
								sys_ctrl.timeflag[0]=!sys_ctrl.timeflag[0];
								break;
						}
						break;
					case 2://投喂2
						switch(sys_ctrl.cnt)
						{
							case 0://时
								sys_ctrl.time[1][0]++;
								if(sys_ctrl.time[1][0]>23)sys_ctrl.time[1][0]=0;
								break;
							case 1://分
								sys_ctrl.time[1][1]++;
								if(sys_ctrl.time[1][1]>59)sys_ctrl.time[1][1]=0;
								break;
							case 2://开关
								sys_ctrl.timeflag[1]=!sys_ctrl.timeflag[1];
								break;
						}
						break;
					case 3://投喂3
						switch(sys_ctrl.cnt)
						{
							case 0://时
								sys_ctrl.time[2][0]++;
								if(sys_ctrl.time[2][0]>23)sys_ctrl.time[2][0]=0;
								break;
							case 1://分
								sys_ctrl.time[2][1]++;
								if(sys_ctrl.time[2][1]>59)sys_ctrl.time[2][1]=0;
								break;
							case 2://开关
								sys_ctrl.timeflag[2]=!sys_ctrl.timeflag[2];
								break;
						}
						break;
				}
			}
			//减
			else if(key==2)
			{
				switch(sys_ctrl.mode)
				{
					case 1://投喂1
						switch(sys_ctrl.cnt)
						{
							case 0://时
								sys_ctrl.time[0][0]--;
								if(sys_ctrl.time[0][0]<0)sys_ctrl.time[0][0]=23;
								break;
							case 1://分
								sys_ctrl.time[0][1]--;
								if(sys_ctrl.time[0][1]<0)sys_ctrl.time[0][1]=59;
								break;
							case 2://开关
								sys_ctrl.timeflag[0]=!sys_ctrl.timeflag[0];
								break;
						}
						break;
					case 2://投喂2
						switch(sys_ctrl.cnt)
						{
							case 0://时
								sys_ctrl.time[1][0]--;
								if(sys_ctrl.time[1][0]<0)sys_ctrl.time[1][0]=23;
								break;
							case 1://分
								sys_ctrl.time[1][1]--;
								if(sys_ctrl.time[1][1]<0)sys_ctrl.time[1][1]=59;
								break;
							case 2://开关
								sys_ctrl.timeflag[1]=!sys_ctrl.timeflag[1];
								break;
						}
						break;
					case 3://投喂3
						switch(sys_ctrl.cnt)
						{
							case 0://时
								sys_ctrl.time[2][0]--;
								if(sys_ctrl.time[2][0]<0)sys_ctrl.time[2][0]=23;
								break;
							case 1://分
								sys_ctrl.time[2][1]--;
								if(sys_ctrl.time[2][1]<0)sys_ctrl.time[2][1]=59;
								break;
							case 2://开关
								sys_ctrl.timeflag[2]=!sys_ctrl.timeflag[2];
								break;
						}
						break;
				}
			}
			//确定
			else if(key==6)
			{
				sys_ctrl.mode=0;
				OLED_ShowString(3*8,16, " ",16);
				OLED_ShowString(3*8,32, " ",16);
				OLED_ShowString(3*8,48, " ",16);
			}
		}
	}
}

//系统功能控制
void sys_fun_ctrl(void)
{
	static u8 oneflag=0;
	//自动模式下
	if(sys_ctrl.autoflag==0)
	{
		//第1组投喂时间开启
		if(sys_ctrl.timeflag[0]==1)
		{
			if(oneflag==0)
			{
				//投喂时间达到
				if(sys_ctrl.time[0][0]==sys_ctrl.hour && sys_ctrl.time[0][1]==sys_ctrl.min)
				{
					sys_ctrl.feedflag[0]=1;
					LED1=0;//打开投喂装置
					BEEP_Alarm(100,100);
					sys_ctrl.alarm_cnt++;
					if(sys_ctrl.alarm_cnt>=10)
					{
						sys_ctrl.alarm_cnt=0;
						oneflag=1;
					}	
				}
			}
			else
			{
				if((sys_ctrl.time[0][1]+1)==sys_ctrl.min)
				{
					oneflag=0;
					sys_ctrl.feedflag[0]=0;
					LED1=1;//关闭投喂装置
				}
			}
		}
		//第2组投喂时间开启
		else if(sys_ctrl.timeflag[1]==1)
		{
			if(oneflag==0)
			{
				//投喂时间达到
				if(sys_ctrl.time[1][0]==sys_ctrl.hour && sys_ctrl.time[1][1]==sys_ctrl.min)
				{
					sys_ctrl.feedflag[1]=1;
					LED1=0;//打开投喂装置
					BEEP_Alarm(100,100);
					sys_ctrl.alarm_cnt++;
					if(sys_ctrl.alarm_cnt>=10)
					{
						sys_ctrl.alarm_cnt=0;
						oneflag=1;
					}	
				}
			}
			else
			{
				if((sys_ctrl.time[1][1]+1)==sys_ctrl.min)
				{
					oneflag=0;
					sys_ctrl.feedflag[1]=0;
					LED1=1;//关闭投喂装置
				}
			}
		}
		//第3组投喂时间开启
		else if(sys_ctrl.timeflag[2]==1)
		{
			if(oneflag==0)
			{
				//投喂时间达到
				if(sys_ctrl.time[2][0]==sys_ctrl.hour && sys_ctrl.time[2][1]==sys_ctrl.min)
				{
					sys_ctrl.feedflag[2]=1;
					LED1=0;//打开投喂装置
					BEEP_Alarm(100,100);
					sys_ctrl.alarm_cnt++;
					if(sys_ctrl.alarm_cnt>=10)
					{
						sys_ctrl.alarm_cnt=0;
						oneflag=1;
					}	
				}
			}
			else
			{
				if((sys_ctrl.time[2][1]+1)==sys_ctrl.min)
				{
					oneflag=0;
					sys_ctrl.feedflag[2]=0;
					LED1=1;//关闭投喂装置
				}
			}
		}
	}
}

//应用控制系统
void app_sys_ctrl_demo(void)
{
	LED_Init();
	USART1_Init(115200);
	OLED_Init();
	KEY_Matrix_Init();
	BEEP_Init();
	TIM3_Init(1000,36000-1);  //定时500ms
	sys_parm_init();//系统参数初始化
	
	sys_open_show();//系统开机界面显示
	
	while(1)
	{
		sys_data_get();//系统数据获取
		sys_data_show();//系统数据显示
		sys_data_set();//系统数据设置
		sys_fun_ctrl();//系统功能控制
	}
}



三、实验现象

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

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


联系作者

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

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值