基于51单片机水塔水位控制系统

基于51单片机水塔水位控制

(仿真+程序)

功能介绍

具体功能:

1.用滑动变阻器模拟水位,ADC0809将模拟信号转换为数字信号;

2.LCD1602显示当前水位和水位阈值;

3.当水位超过设定阈值,蜂鸣器+LED声光报警,并且电机转动(模拟排水);

4.三个按键可以设定水位阈值;

​演示视频:

基于51单片机水塔水位控制系统 

添加图片注释,不超过 140 字(可选)

程序

//程序头函数
#include <reg52.h>
#include <intrins.h>
/***公众号:木子单片机****/
//宏定义
#define uint unsigned int 
#define uchar unsigned char
#define Data_ADC0809 P1		//定义P1口为Data_ADC0809
 
//管脚声明
sbit LED_R= P2^2;			  //红色指示灯
sbit LED_G= P2^0;			  //绿色指示灯
sbit FENG = P2^5;			  //蜂鸣器
sbit san=P3^4;				  //继电器
//ADC0809
sbit ST=P3^3;
sbit EOC=P3^6;
sbit OE=P3^2;
//按键
sbit Key1=P2^6;
sbit Key2=P2^7;
sbit Key3=P3^7;

bit bdata flag;				  //定义位变量
uchar set;					  //设置变量

sbit RS=P2^3;
sbit RW=P2^1;
sbit EN=P2^4;
//ADC数值
uchar ADC_value=0;

//报警数值
uchar WARNING=25;		//报警值变量

//延时函数
void Delay1ms( int ms)
{                           
  int i;
  while(ms--)
  {
    for(i = 0; i< 250; i++)
    {
      _nop_();
      _nop_();
      _nop_();
      _nop_();
    }
  }
}

//检查忙函数
bit check()
{                         
  bit busy;
  RS=0;
  RW=1;
  EN=1;
  Delay1ms(2);
  EN=0;
  return busy;
}

//写指令函数
write_com(uchar zhi)
{
  while(check());
  RS=0;
  RW=0;
  EN=0;
  _nop_();
  _nop_();
  P0=zhi;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  EN=1;	
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  EN=0;	 
}

//写数据函数
write_data(uchar shu) 
{
  while(check());
  RS=1;
  RW=0;
  EN=0;
  _nop_();
  _nop_();
  P0=shu;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  EN=1;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  EN=0;
}

//初始化LCD函数
void Init1602()
{
  write_com(0x38);
  Delay1ms(1);
  write_com(0x0c);
  Delay1ms(1); 
  write_com(0x06);
  Delay1ms(1);
  write_com(0x01); 
  Delay1ms(1); 
}

//ADC0809读取信息
uchar ADC0809()
{
	uchar temp=0x00;
	//初始化高阻太
	OE=0;
	//转化初始化
	ST=0;
	//开始转换
	ST=1;
	Delay1ms(1);
	ST=0;
	//外部中断等待AD转换结束
	while(EOC==0)
	//读取转换的AD值
	OE=1;
	temp=Data_ADC0809;
	OE=0;
	return temp;
}

void Key()					  //按键函数
{
	if(Key1==0)				  //设置键按下
	{
		while(Key1==0);		  //按键松开
		FENG=0;				  //蜂鸣器响
		set++;				  //设置变量加
		flag=0;				  //关闭报警
		san=1;				  //关闭继电器
		TR0=0;				  //关闭定时器
	}
	if(set==1)				  //设置报警值时
	{
		write_com(0x38);//屏幕初始化
		write_com(0x80+0x40+13);//位置
   		write_com(0x0f);//打开显示 无光标 光标闪烁
   		write_com(0x06);//当读或写一个字符是指针后一一位
		FENG=1;				//关闭蜂鸣器

	}
	else if(set>=2)		//设置完成时
	{
		set=0;			//变量清零
		write_com(0x38);//屏幕初始化 
		write_com(0x80);
		write_com(0x0c);//打开显示 无光标 无光标闪烁
		FENG=1;			//关闭蜂鸣器
		flag=1;			//打开报警
		TR0=1;			//打开定时器
	}
	if(Key2==0&&set!=0)			//设置报警值时加键按下
	{
		while(Key2==0);			//按键松开
		FENG=0;					//打开蜂鸣器
		WARNING++;				//报警值加
		if(WARNING>=255)		//最大加到255
		WARNING=0;				//清零
		write_com(0x80+0x40+11);	   //选中液晶屏上的第二行第十一列
		write_data('0'+WARNING/100);   //开始显示报警值。例如报警值是123,123除以100的商是1,加上‘0’是为了得到液晶中对应1的显示码
		write_data('0'+WARNING%100/10);//123除以100的余数是23,23再除以10得到的商是2
		write_data('0'+WARNING%100%10);//23除以10的余数是3
		write_com(0x80+0x40+13);//位置
		FENG=1;						//关闭蜂鸣器
	}
	if(Key3==0&&set!=0)				//注释同加按键
	{
		while(Key3==0);
		FENG=0;
		WARNING--;
		if(WARNING<=0)
		WARNING=255;
		write_com(0x80+0x40+11);
		write_data('0'+WARNING/100);
		write_data('0'+WARNING/10%10);
		write_data('0'+WARNING%10);
		write_com(0x80+0x40+13);//位置
		FENG=1;
	}
}
//显示AD数值和报警数值
void Display1602(uchar tempADC,uchar tempWaring)
{
  const uchar buf1[]={"Level:"};
  const uchar buf2[]={"Setup:"};
  int i=0x00;
  uchar temp = 0;
  write_com(0x80|0x05); //第一行显示
  while(buf1[i]!=0)
  {
    write_data(buf1[i]);
    i++;
  }	
  temp =  tempADC/100 + '0';
  write_data(temp);
  temp =  tempADC%100/10 + '0';
  write_data(temp);
  temp =  tempADC%10 + '0';
  write_data(temp);
  write_data(' ');
  write_data(' ');


  write_com(0x80|0x45); //第二行显示
  i=0x00;
  while(buf2[i]!=0)
  {
    write_data(buf2[i]);
    i++;
  }
  temp =  tempWaring/100 + '0';
  write_data(temp);
  temp =  tempWaring%100/10 + '0';
  write_data(temp);
  temp =  tempWaring%10 + '0';
  write_data(temp);
}

void init()				//定时器初始化函数
{
	TMOD=0x01;			//定时器工作方式
 	TL0=0xb0;
 	TH0=0x3c;			//赋初值50ms
 	EA=1;				//打开中断总开关
	ET0=1;				//打开定时器0中断允许开关
 	TR0=1;				//打开定时器0定时开关
}

void main()				//主函数
{
	Init1602();						 //初始化液晶函数
	init();							 //初始化定时器
	while(1)						 //进入循环
	{
		ADC_value=ADC0809();				 //读取AD数值
		if(set==0)					 //set为0,说明现在不是设置状态
			Display1602(ADC_value,WARNING);	 //显示AD数值和报警值
		if(ADC_value<WARNING&&set==0)	 //AD数值小于报警值
		{
			flag=0;					 //关闭报警
		}
		else if(ADC_value>WARNING&&set==0)//AD值大于报警值
		{
			flag=1;					 //打开报警
		}
		Key();						 //调用按键函数
	}
}
void  time1_int(void) interrupt 1		  //定时器工作函数
{
	uchar count;						  //定义计时变量
	TL0=0xb0;
 	TH0=0x3c;							  //重新赋初值50ms
  	count++;							  //变量加一次就是50ms
	if(count==10)						  //加到10次就是500ms
	{
		if(flag==0)						  //flag=0时,也就是不开启报警
		{
			LED_G=0;					  //绿灯点亮
			LED_R=1;					  //红灯熄灭
			FENG=1;						  //关闭蜂鸣器
			san=1;						  //关闭继电器
		}
		if(flag==1)						  //flag为1时,也就是打开报警
		{
			LED_G=1;					  //绿灯熄灭
			LED_R=0;					  //红灯点亮
			FENG=0;						  //打开蜂鸣器
			san=0;						  //打开继电器
		}
	}

   	if(count==20)						  //计数20次,就是1s
   	{									  //在1s时,红绿灯都是熄灭状态,蜂鸣器也是关闭状态,装可以达到闪烁的目的
		count=0;						  //变量清零
		if(flag==0)						  //不是报警状态时
		{
			LED_G=1;
			LED_R=1;
			FENG=1;
			san=1;						  //都关闭
		}
		if(flag==1)						  //报警状态时
		{
			LED_G=1;
			LED_R=1;
			FENG=1;
			san=0;						  //继电器一直吸和
		}
	}
} 

硬件设计

使用元器件:

单片机:AT89C52;

(注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)

添加图片注释,不超过 140 字(可选)

设计资料

01仿真图

本设计使用proteus7.8和proteus8.9两个版本设计!具体如图!

添加图片注释,不超过 140 字(可选)

02程序

本设计使用软件keil4和keil5版本编程设计!具体如图!

添加图片注释,不超过 140 字(可选)

03设计资料

         资料获取请关注同名公众号,全部资料包括仿真源文件 、程序(含注释)等。具体内容如下,全网最全! !

资料获取请观看前面演示视频!

点赞分享一起学习成长。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/689942.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统之部署Blog-Index导航页

Linux系统之部署Blog-Index导航页 一、Blog-Index介绍1.1 Blog-Index简介1.2 Blog-Index特点1.3 Blog-Index使用场景 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍2.3 Yarn介绍 三、检查本地环境3.1 检查本地操作系统版本3.2 检查系统内核版本3.3 检查系统是否安装yarn 四…

C语言scanf( ) 函数、fprintf( ) 函数与 scanf( ) 函数和printf( ) 函数有什么不同?

一、问题 fscanf( ) 函数、fprintf( ) 函数与 printf( ) 函数、scanf( ) 函数的作⽤相似&#xff0c;都是格式化读写函 数&#xff0c;那么这两个读写函数有什么不同呢&#xff1f; 二、解答 两者的区别就在于前⾯的字符“f”&#xff0c;即 fscanfQ函数和 fprintfD函数的读写…

2005-2022年各省居民人均消费支出数据(无缺失)

2005-2022年各省居民人均消费支出数据&#xff08;无缺失&#xff09; 1、时间&#xff1a;2005-2022年 2、来源&#xff1a;国家统计局、统计年鉴 3、指标&#xff1a;全体居民人均消费支出 4、范围&#xff1a;31省 5、缺失情况&#xff1a;无缺失 6、指标解释 居民人…

【经验分享】搭建跨境电商那个独立站必备的功能模块以及实现

搭建跨境电商独立站时&#xff0c;需要确保网站具备一系列关键的功能板块&#xff0c;以提供用户友好的购物体验并确保业务的顺利进行。以下是这些功能板块的详细归纳&#xff1a; 注册登录与身份验证&#xff1a; 用户注册与登录&#xff1a;允许用户创建账户&#xff0c;通过…

排查互联网敏感信息,对信息泄露说“不”

前言 01 近几年&#xff0c;随着我国对网络安全的重视&#xff0c;贴近实战的攻防演练活动越发丰富&#xff0c;各单位的网络安全建设也逐步从“事后补救”升级为“事前防控”。在演练中&#xff0c;进攻方会在指定时间内对防守方发动网络攻击&#xff0c;检测出防守方存在的…

这才是计科之 Onix XV6 源码分析(3、Unix-like系统的进程调度模块)

这才是计科之 Onix & XV6 源码分析&#xff08;3、Unix-like系统的进程调度模块&#xff09; 前言 前面已经分析了XV6的启动流程以及内存管理&#xff0c;接下来&#xff0c;我们探究进程调度的实现。与其说进程调度&#xff0c;我觉得可以顺应内存的虚拟化的叫法&#x…

Python报错:IndentationError: unexpected indent问题的解决办法及原因

解决Python报错&#xff1a;IndentationError: unexpected indent问题的解决办法及原因 Python是一种注重可读性的编程语言&#xff0c;它使用缩进来定义代码块。如果你遇到了IndentationError: unexpected indent的错误&#xff0c;这意味着Python解释器在代码中遇到了意外的缩…

HTML,CSS,JavaScript实例——3D骰子,跨纬度蠕虫,动态登录表单。

文章目录 一、3D筛子1.HTML2.CSS 二、跨纬度蠕虫1.HTML2.CSS3.JS 三、动态登录表单1.HTML2.CSS 一、3D筛子 1.HTML <!--ring div starts here--> <div class"ring"><i style"--clr:#00ff0a;"></i><i style"--clr:#ff0057…

如何拼接全景图?PTGui Pro macOS安装包

PTGui Pro是一款功能强大的全景图像拼接软件&#xff0c;特别适合专业摄影师和设计师使用。它能够将多张照片拼接成高质量的全景图&#xff0c;支持普通、圆柱和球形等多种全景模式。软件提供了自动图像拼接和手动模式&#xff0c;用户可根据需求灵活选择。同时&#xff0c;PTG…

大屏可视化建设方案(word)

1.系统概述 1.1.需求分析 1.2.重难点分析 1.3.重难点解决措施 2.系统架构设计 2.1.系统架构图 2.2.关键技术 2.3.接口及要求 3.系统功能设计 3.1.功能清单列表 3.2.数据源管理 3.3.数据集管理 3.4.视图管理 3.5.仪表盘管理 3.6.移动端设计 3.1.系统权限设计 3.…

平稳交付 20+ 医院,卓健科技基于 OpenCloudOS 的落地实践

导语&#xff1a;随着数字化转型于各个行业领域当中持续地深入推进&#xff0c;充当底层支撑的操作系统正发挥着愈发关键且重要的作用。卓健科技把 OpenCloudOS 当作首要的交付系统&#xff0c;达成了项目交付速度的提升、安全可靠性的增强、运维成本的降低。本文将会阐述卓健科…

源码解析:从零解读SAM(Segment Anything Model)大模型!

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学。 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 合集&#x…

Postman 打开错误的解决方法

错误如下&#xff1a; PostMan的文件都是放在用户文件下&#xff0c;所以在Local和Roaming文件夹下查看&#xff0c;并删除所有PostMan相关文件夹。 我电脑上的路径在 C:\Users\Administrator\AppData\Local 和 C:\Users\Administrator\AppData\Roaming【Administrator为系…

南山代理记账,为您提供专业、高效的服务和全方位的支持

随着商业活动的不断深化和扩展&#xff0c;企业的会计工作越来越重要&#xff0c;而作为一家专业的代理记账公司&#xff0c;“南山代理记账”始终致力于为客户提供专业、高效的服务&#xff0c;帮助他们在经营过程中更好地管理和运用资金。 南山代理记账公司的服务范围广泛&am…

docker pull image 报错 dial tcp 31.13.88.169:443: i/o timeout

一、错误重现 error pulling image configuration: download failed after attempts6: dial tcp 31.13.88.169:443: i/o timeout 在执行docker build构建镜像&#xff0c;拉取镜像时报错 或者直接docker pull镜像时报错 实质都是拉取镜像源超时报错&#xff0c;那么就是镜像源…

通过调用栈快速探究 Compose 中 touch 事件的处理原理

前言 Compose 视图的处理方式和 Android 传统 View 有很大差别&#xff0c;针对 touch 事件的处理自然也截然不同。 如何在 Compose 中处理 touch 事件&#xff0c;官方已有非常详尽的说明&#xff0c;可以参考&#xff1a;https://developer.android.google.cn/jetpack/comp…

为什么PPT录制没有声音 电脑ppt录屏没有声音怎么办

一、为什么PPT录制没有声音 1.软件问题 我们下载软件的时候可能遇到软件损坏的问题&#xff0c;导致录制没有声音&#xff0c;但其他功能还是可以使用的。我建议使用PPT的隐藏功能&#xff0c;下载插件&#xff0c;在PPT界面的加载项选项卡中就能使用。我推荐一款可以解决录屏…

JavaScript入门宝典:核心知识全攻略(下)

文章目录 前言一、获取标签元素二、操作标签元素属性1. 属性的操作2. innerHTML 三、数组及操作方法1. 数组的定义2. 数组的操作 四、循环语句五、字符串拼接六、定时器1. 定时器的使用3. 清除定时器 七、ajax1. ajax的介绍2. ajax的使用 前言 JavaScript是前端开发不可或缺的技…

RHEL - 订阅、注册系统和 Yum Repository(新版界面)

《OpenShift / RHEL / DevSecOps 汇总目录》 演示环境说明 本文需要有 redhat.com 账号以及包含 RHEL 的有效订阅。 演示环境使用了通过 minimal 方式安装的 RHEL 7.6 环境&#xff0c;RHEL 可以访问互联网。 红帽网站 access.redhat.com 针对新用户提供了新版界面&#xff0…

云原生架构:构建高可用、可伸缩的互联网应用

随着互联网技术的不断发展&#xff0c;云原生架构已经成为构建高可用、可伸缩的互联网应用的最佳实践之一。云原生架构是一种以云计算为基础的应用架构&#xff0c;旨在充分利用云平台的优势&#xff0c;实现应用的高可用性、灵活性和可扩展性。本文将介绍云原生架构的关键概念…