首页 > 其他分享 >【Proteus仿真】基于51单片机的宠物喂食系统设计

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

时间:2024-09-18 11:53:15浏览次数:14  
标签:10 显示 DS1302Buffer 51 单片机 printc Proteus LCD1602 0x30

目录

一、主要功能

二、硬件资源

三、程序编程

四、实现现象


一、主要功能

基于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的分享

标签:10,显示,DS1302Buffer,51,单片机,printc,Proteus,LCD1602,0x30
From: https://blog.csdn.net/2401_84985327/article/details/142329604

相关文章

  • 【Proteus仿真】基于51单片机的L298N电机电速调节
    目录一、主要功能二、硬件资源三、程序编程四、实现现象一、主要功能基于51单片机,L298N电机驱动连接电机,采用调节PWM占空比来控制电机速度转动。仿真图:编辑二、硬件资源基于KEIL5编写C++代码,PROTEUS8.15进行仿真,全部资源在页尾,提供安装包。1、51单片机2、L298N......
  • CMS32L051驱动WS2812B全彩灯-PWM+DMA模式
    文章目录概要代码小结概要基于中微CMS32L051驱动WS2812B全彩灯,使用PWM+DMA模式。参照中微的串口uartSendReceive,该例程中有使用DMA进行串口数据的收发。代码main.c/******************************************************************************************......
  • CMS32L051使用旋转编码器
    文章目录概要代码小结概要CMS32L051使用外部中断的方式识别旋转编码器的方向。选取其中一个信号A进行外部中断触发,由于信号A空闲时处于高电平,因此初始化时外部中断使用下降沿触发;触发第一个下降沿后,判断当前是否已经触发了上升沿,如果已经触发上升沿,则需要判断当前......
  • CMS32L051定时器时钟选择
    文章目录概要代码小结概要CMS32L051的定时器搭载两个通用定时器单元,每个单元含有4个通道。每个通用定时器单元有4个16位定时器。各16位定时器称为“通道”,既能分别用作独立的定时器,也能组合多个通道用作高级的定时器功能。定时器时钟选择寄存器m(TPSm)是16位寄存器,选......
  • GYM 105125 C
    题目描述给定\(NM\)个数\(A_1,A_2,\dots,A_{NM}\),你要将这些数分成\(N\)个数组,每个数组\(M\)个数。接着你要将这些数组按字典序排序。对于排序后每个数组求出可能的字典序最小情况。思路我们从字典序的比较上来考虑,并把\(A\)排序。首先考虑当前数组\(i\)的第一位......
  • 51c大模型~合集55
    #新型忆阻器昂贵LLM的救星?Nature新研究提出新型忆阻器,比HaswellCPU高效460倍前些天,OpenAI发布了ο1系列模型,它那「超越博士水平的」强大推理性能预示着其必将在人们的生产生活中大有作为。但它的使用成本也很高,以至于OpenAI不得不限制每位用户的使用量:每位用户每周仅能给o1-......
  • STM32F407单片机编程入门(三)ADC详解及实战含源码
    文章目录一.概要二.STM32F407VET6单片机ADC外设特点三.STM32单片机ADC内部结构图1.ADC相关引脚说明2.ADC通道分类3.触发源4.转换周期5.电压转换计算6.更精确电压转换计算四.规则通道ADC采集信号流向1.单次转换模式2.连续转换模式五.CubeMX配置一个ADC采集例程六.CubeMX......
  • 教育部等十八部门关于加强新时代中小学科学教育工作的意见 20240917_085127
    原文教育部等十八部门关于加强新时代中小学科学教育工作的意见_国务院部门文件_中国政府网https://www.gov.cn/zhengce/zhengceku/202305/content_6883615.htm概述教育部等十八部门联合发布此意见,强调要加强科学教育,推动校内校外融合,规范科技类校外培训。这一政策为少儿编程教......
  • 【Proteus51单片机仿真】PWM直流电机调速
    目录一、主要功能二、硬件资源三、程序编程四、实现现象一、主要功能**        基于AT89C51,L298N驱动两个电机,因为是平台,最后用两个电机驱动,然后第一个按键控制所有电机停止,第二个按键按下,电机顺时针转动,第三个按键按下,电机逆时针转动。然后加入pwm调速,分为......
  • 【Proteus单片机仿真】基于51单片机的循迹小车避障+气体传感器和温度传感器系统
    目录一、主要功能二、硬件资源三、程序编程四、实现现象一、主要功能开机即两个直流电机运转,然后三个气体传感器,如果超过阈值,即蜂鸣器报警;超声波传感器,如果检测到障碍,电机停止;温度传感器,超过阈值,电机停止,蜂鸣器报警,点亮一个灯;循迹模拟,与电机联动;仿真图:编辑二、......