当前位置: 首页 > article >正文

【单片机仿真】基于51单片机的宠物喂食系统设计

目录

一、主要功能

二、硬件资源

三、程序编程

四、实现现象


一、主要功能

基于51单片机,两个按键调整重量阈值的大小,如果mpx4117压力传感器测重没超过阈值,
则电机转动,表示投喂,蜂鸣器发出滴滴声,如果超过阈值,则全部停止;
同时,再加三个按键,一个按键按下切换到闹钟设置模式,一个按键按下切换时和分的调整,
一个按键按下则增加时或者分,当系统时间到达所设置的时间后,显示屏显示50,
表示要投喂的重量,此时电机转动,蜂鸣器发出滴滴声

二、硬件资源

基于KEIL5编写C++代码,PROTEUS8.15进行仿真,全部资源在页尾,提供安装包。

三、程序编程

#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#include "LCD1602.h"
#include "DS1302.h"

//IO设置
//****************************************************
sbit CS   =  P2^3;        //ADC0832引脚定义
sbit CLK  =  P2^4;
sbit DIO  =  P2^5;
sbit key1 =  P1^3;
sbit key2 =  P1^4;
sbit key3 =  P1^5;
sbit key4 =  P1^6;
sbit key5 =  P1^7;
sbit beep =  P2^6;
sbit out1 =  P3^0;
sbit out2 =  P3^1;

unsigned char KEY_NUM = 0;
bit Flag_KEY_Set = 0;
unsigned char KEY2_Count = 0;
static uchar u,U,YL;
static int numbermax=100,flag=0,time_num,flag1=0,hournum=8,minutenum=0,miaonum=0,flag2 = 0;

void ajpd(void);
void twpd(void);
void sjqh(void);
void nzpd(void);
void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}


uchar get_AD_Res()          //ADC0832启动读取函数
{
	uchar i, data1=0, data2=0;
	CS=0;
	
	CLK=0;DIO=1;_nop_();
	CLK=1;_nop_();
	
	CLK=0;DIO=1;_nop_(); 
	CLK=1;_nop_();
	
	CLK=0;DIO=0;_nop_();
	CLK=1;_nop_();
	
	CLK=0;DIO=1;_nop_(); 
	
	for(i=0; i<8; i++)
	{
		CLK=1;_nop_();
		CLK=0;_nop_();
		data1=(data1<<1)|(uchar)DIO; 
	}
	
	for(i=0; i<8; i++)
	{
		data2=data2|(uchar)DIO<<i;
		CLK=1;_nop_();
		CLK=0;_nop_();
	}
	CS=1;
	
	return(data1 == data2)?data1:0;
}

//显示实时时钟
//****************************************************
void Display_RTCC()
{
	unsigned char *weeklist[7]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
	LCD1602_write_com(0x80);							//指针设置到第一行第1列
	
	LCD1602_prints("20");
	LCD1602_printc(DS1302Buffer.Year/10 + 0x30);	 //显示Year高位
	LCD1602_printc(DS1302Buffer.Year%10 + 0x30);	 //显示Year低位
	LCD1602_printc('-');
	LCD1602_printc(DS1302Buffer.Month/10 + 0x30);	 //显示Month高位
	LCD1602_printc(DS1302Buffer.Month%10 + 0x30);	 //显示Month低位
	LCD1602_printc('-');
	LCD1602_printc(DS1302Buffer.Day/10 + 0x30);		 //显示Day高位
	LCD1602_printc(DS1302Buffer.Day%10 + 0x30);		 //显示Day低位

	LCD1602_write_com(0x80+13);							 //指针设置到第一行第14列
	LCD1602_prints(weeklist[DS1302Buffer.Week -1]);

	LCD1602_write_com(0xc0);				 //指针设置到第二行第1列
	LCD1602_printc(DS1302Buffer.Hour/10 + 0x30);	 //显示Hour高位
	LCD1602_printc(DS1302Buffer.Hour%10 + 0x30);	 //显示Hour低位
	LCD1602_printc(':');
	LCD1602_printc(DS1302Buffer.Minute/10 + 0x30);	 //显示Minute高位
	LCD1602_printc(DS1302Buffer.Minute%10 + 0x30);	 //显示Minute低位
	LCD1602_printc(':');
	LCD1602_printc(DS1302Buffer.Second/10 + 0x30);	 //显示Second高位
	LCD1602_printc(DS1302Buffer.Second%10 + 0x30);	 //显示Second低位	
}


void main()
{
    LCD1602_Init();									//初始化LCD1602
    LCD1602_delay_ms(1);
    LCD1602_set_position(0,0);//指针设置到第一行第1列
    LCD1602_prints("Hello World!");
    LCD1602_set_position(0,13);//指针设置到第一行第13列
    LCD1602_prints("STC");
	  LCD1602_delay_ms(500);
  	LCD1602_write_com(0x01);					//清屏指令
	  DS1302_Init();									//初始化DS1302
	  beep = 0;
    while(1)
    {
			if(flag==0)
			{
	  DS1302_GetTime(&DS1302Buffer);							//获取当前RTCC值
	  if(Flag_Time_Refresh==1&& Flag_KEY_Set == 0)			//数据更新时才刷新LCD
		{
			Flag_Time_Refresh = 0;
			Display_RTCC();				//显示实时时钟		
		}
				
		u=get_AD_Res();	   //压力传感器
	  U=(250*u)/128;    
	  YL=200*U/250;
    LCD_ShowNum(2,14,YL,3);
		LCD_ShowNum(2,10,numbermax,3);
	  }
		ajpd(); //按键判断
		twpd();  //投喂判断
		nzpd(); //闹钟判断
		sjqh(); // 时间切换
		time_num++;											    //计时变量+1
		if(time_num == 5000)
		{
			time_num = 0;
		}
		
    }
}

void nzpd() //闹钟判断
{
	if(flag==0)
	{
	if(DS1302Buffer.Hour == hournum && DS1302Buffer.Minute == minutenum && DS1302Buffer.Second > miaonum)
	{
		flag2 = 1;
		numbermax = 50;
		LCD_ShowNum(2,10,numbermax,3);
		out1 = 1;
		out2 = 0;
		beep=1;
		Delay(300);
		beep=0;
		Delay(300);
	}
	else
	{
		flag2 = 0;
	}
}
}
void sjqh() //时间切换
{
	if(flag == 2)
	{
	if(flag1 == 1)
	{
		if(time_num % 100 == 0 )
		{
		LCD1602_set_position(0,0);//指针设置到第一行第1列
    LCD1602_prints("nao zhong");
		LCD1602_set_position(1,0);//指针设置到第二行第1列
	  LCD1602_printc(hournum/10 + 0x30);	 //显示Hour高位
	  LCD1602_printc(hournum%10 + 0x30);	 //显示Hour低位
	  LCD1602_printc(':');
	  LCD1602_printc(minutenum/10  + 0x30);	 //显示Minute高位
	  LCD1602_printc(minutenum/10  + 0x30);	 //显示Minute低位
	  LCD1602_printc(':');
	  LCD1602_printc(miaonum/10  + 0x30);	 //显示Second高位
	  LCD1602_printc(miaonum/10  + 0x30);	 //显示Second低位	
		}
		
		if(time_num % 200 == 0 )
		{
			LCD1602_set_position(1,1);
			LCD1602_printc("      ");
		}
	}
	
		if(flag1 == 2)
	{
		if(time_num % 100 == 0 )
		{
		LCD1602_set_position(0,0);//指针设置到第一行第1列
    LCD1602_prints("nao zhong");
		LCD1602_set_position(1,0);//指针设置到第二行第1列
	  LCD1602_printc(hournum/10 + 0x30);	 //显示Hour高位
	  LCD1602_printc(hournum%10 + 0x30);	 //显示Hour低位
	  LCD1602_printc(':');
	  LCD1602_printc(minutenum/10  + 0x30);	 //显示Minute高位
	  LCD1602_printc(minutenum%10  + 0x30);	 //显示Minute低位
	  LCD1602_printc(':');
	  LCD1602_printc(miaonum/10  + 0x30);	 //显示Second高位
	  LCD1602_printc(miaonum/10  + 0x30);	 //显示Second低位	
		}
		
		if(time_num % 200 == 0 )
		{
			LCD1602_set_position(1,4);
			LCD1602_printc("      ");
		}
	}
	
		if(flag1 == 3)
	{
		if(time_num % 100 == 0 )
		{
		LCD1602_set_position(0,0);//指针设置到第一行第1列
    LCD1602_prints("nao zhong");
		LCD1602_set_position(1,0);//指针设置到第二行第1列
	  LCD1602_printc(hournum/10 + 0x30);	 //显示Hour高位
	  LCD1602_printc(hournum%10 + 0x30);	 //显示Hour低位
	  LCD1602_printc(':');
	  LCD1602_printc(minutenum/10  + 0x30);	 //显示Minute高位
	  LCD1602_printc(minutenum%10  + 0x30);	 //显示Minute低位
	  LCD1602_printc(':');
	  LCD1602_printc(miaonum/10  + 0x30);	 //显示Second高位
	  LCD1602_printc(miaonum/10  + 0x30);	 //显示Second低位	
		}
		
		if(time_num % 200 == 0 )
		{
			LCD1602_set_position(1,7);
			LCD1602_printc("      ");
		}
	}
 }
}
	
void ajpd()  //按键判断
{
	if(!key4)
	{
		numbermax++;
		while(!key4);
	}
	 if(!key5)
	{
		numbermax--;
		while(!key5);
	}
	
	if(!key1) //切换模式
	{
		flag++;
		if(flag>2)
		{
			flag=0;
		}
		if(flag==1)
		{
		LCD1602_write_com(0x01);					//清屏指令
		LCD1602_set_position(0,0);//指针设置到第一行第1列
    LCD1602_prints("nao zhong");
		LCD1602_set_position(1,0);//指针设置到第二行第1列
	  LCD1602_printc(0 + 0x30);	 //显示Hour高位
	  LCD1602_printc(8 + 0x30);	 //显示Hour低位
	  LCD1602_printc(':');
	  LCD1602_printc(0 + 0x30);	 //显示Minute高位
	  LCD1602_printc(0 + 0x30);	 //显示Minute低位
	  LCD1602_printc(':');
	  LCD1602_printc(0 + 0x30);	 //显示Second高位
	  LCD1602_printc(0 + 0x30);	 //显示Second低位	
		}
		while(!key1);
	}
	
		if(!key2) //切换时间
	{
		flag1++;
		if(flag1>3)
		{
			flag1=1;
		}
		while(!key2);
	}
	
	if(!key3)
	{
		if(flag1==1)
		{
			hournum++;
			if(hournum>24)
			{
				hournum=0;
			}
		}
		
		if(flag1==2)
		{
			minutenum++;
			if(minutenum>60)
			{
				minutenum=0;
			}
		}
		
	while(!key3);
	}
}

void twpd() //投喂判断
{
	if(flag2 == 0)
	{
	if(YL>numbermax)
	{
		out1=0;
		out2=0;
		beep=0;
	}
	else
	{
		out1=1;
		out2=0;
		beep=1;
		Delay(300);
		beep=0;
		Delay(300);
	}
 }
	
}

四、实现现象

具体动态效果看B站演示视频:

基于51单片机的宠物喂食系统设计_哔哩哔哩_bilibili

全部资料(源程序、仿真文件、安装包、演示视频):

通过百度网盘分享的文件:基于51单片机的宠物喂食系统设计.zip
链接:https://pan.baidu.com/s/1hxCikh5QDz6SodvzQIOn4w 
提取码:hszh 
--来自百度网盘超级会员V4的分享


http://www.kler.cn/a/303691.html

相关文章:

  • 软件设计师考试大纲
  • 【代码审计】常见漏洞专项审计-业务逻辑漏洞审计
  • 2个word内容合并
  • arcgis做buffer
  • 开源模型应用落地-qwen模型小试-Qwen2.5-7B-Instruct-tool usage入门-Qwen-Agent深入学习(四)
  • C++单例模式与多例模式
  • 8个前端库-小且美
  • 【Qt】Qml界面中嵌入C++ Widget窗口
  • 万界星空科技电池MES具体功能及解决方案
  • Go 语言的优势
  • 【油猴脚本】00005案例 Tampermonkey油猴脚本动态渲染表格列,列的值,“默认无值”
  • 【C++算法】分治——归并
  • Golang path/filepath包详解:高效路径操作与实战案例
  • 《论面向方面的编程技术及其应用》写作框架,软考高级系统架构设计师
  • 在OpenEuler(欧拉)系统上用kubeadm部署(k8s)Kubernetes集群
  • 【运维监控】系列文章汇总索引
  • linux_L1_linux重启服务器
  • MySQL字符集的转换
  • Integer 缓存
  • Three.js 实战【4】—— 3D地图渲染
  • 【Linux 从基础到进阶】Docker 容器技术基础与应用
  • MySQL事务【后端 13】
  • triton之ttir学习
  • 在C++中,如何避免出现Bug?
  • 第二百三十一节 JPA教程 - JPA Transient示例、 JPA ID注释示例
  • 【ArcGIS Pro】扩展模块 Nuget 使用