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

【Proteus仿真】基于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/316800.html

相关文章:

  • 24/11/13 算法笔记<强化学习> DQN算法
  • LeetCode【0031】下一个排列
  • [Docker#8] 容器配置 | Mysql | Redis | C++ | 资源控制 | 命令对比
  • 【Rust练习】21.动态数组 Vector
  • git commit 校验
  • 应对JSON解析键值对乱序问题的实用解决方案
  • JSON合并工具
  • JVM-类加载器的双亲委派模型详解
  • 前后端数据交互 笔记03(get和post方法)
  • 使用 Azure Functions 开发 Serverless 应用:详解与实战
  • LeetCode 1014. 最佳观光组合 一次遍历数组,时间复杂度O(n)
  • 【matlab】将程序打包为exe文件(matlab r2023a为例)
  • Linux文件IO(三)-Linux系统如何管理文件
  • 【基础知识】网络套接字编程
  • QT-MOC元对象系统详解
  • 【小程序】微信小程序课程 -1 安装与配置
  • 【2025】基于微信小程序的人工智能课程学习平台的设计与实现(源码+文档+解答)
  • 职业技能大赛-自动化测试笔记分享
  • while语句
  • CANdela/Diva系列8--如何生成0x27服务解锁的DLL
  • MySQL 数据库课程设计详解与操作示例
  • Java : 图书管理系统
  • ArcGIS Pro SDK (十四)地图探索 6 图形与工具
  • AIGC7: 高通骁龙AIPC开发者沙龙过程记录A
  • 力扣刷题之2398.预算内的最多机器人数目
  • Shelly实测天工的音乐创作功能,写了一首歌,来听听效果