毕业设计基于51单片机控制的水塔自动供水系统设计.doc
毕 业 (设 计) 论 文题目: 基于51单片机控制的水塔自动供水系统系部: 电气工程与自动化系 专业: 自动化技术 班级: 电气A0701班 姓名: 李月鹏 指导教师: 陈毅朋、张慧明 山 西 综 合 职 业 技 术 学 院 摘 要微型计算机SCMC,简称单片机,又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。这种计算机的最小系统只用了一片集成电路,可进行简单运算和控制。虽然单片机只有一个芯片,但无论从组成还是从功能上看,它已具备了计算机系统的属性,是一个简单的微型计算机。单片机以其体积小、功能全、价格优等种种优势充斥着整个市场。现在,单片机的使用领域已十分广泛,如智能仪表、实时工控、导航系统、家用电器等。单片机开发出的各种产品遍布于我们日常生活中的每个角落。为了加深对单片机智能型控制器的了解,经过综合分析,本次设计最终选取了由51单片机控制的智能型液位控制器作为研究项目,本文对单片机水塔水位控制系统进行了整体设计,完成了单片机水塔水位控制系统硬件接线图和流程图以及单片机内部控制程序设计,并完成了开发板模拟仿真过程。通过此次设计过程,自己在分析问题、解决问题方面的能力得到了很大程度的提高。关键词: MCS-51单片机 液压传感器 AD转换 水塔水位检控目 录引言31、系统设计方案比较及论证32、系统原理框图43、工作原理44、硬件设计44.1 STC89C52RC单片机简介44.2 锁存器(74HC573)简介54.3 ADC0804简介64.4 单片机与继电器及蜂鸣器的接口电路74.5 井中缺水信号检测电路84.6 压力传感器介绍94.7 LCD1602液晶显示屏接线图及其引脚功能图104.8 开关电源部分105、软件设计125.1 程序流程图125.2 程序流程图解析136、实验仿真结果137、结束语13致谢14附 录15附录1 PCB原理图15附录2 C程序16参考文献26基于51单片机控制的水塔自动供水系统山西综合职业技术学院 李月鹏引言 水塔供水的主要问题是塔内水位应始终保持在一定范围,避免“空塔”、“溢塔”现象发生。目前,控制水塔水位方法较多,其中较为常用的是由单片机控制实现自动运行,使水塔内水位保持恒定,以保证连续正常地供水。实际供水过程中要确保水位在允许的范围内浮动,应采用水压监测来控制水位。首先通过压力传感器实时检测水压,测量水位变化,再变送成电压信号传回单片机,由单片机执行内部控制程序指令,从而控制水泵电动机,保证水位在正常范围内变化。为此,这里给出以STC公司的STC89C52RC单片机为核心器件、以压力传感器为检测原件、通过ADC0804芯片为信号转换原件的水塔水位检测控制系统仿真设计,实现水位的自动检测控制、电机故障检测和报警等功能,通过在51单片机实验开发板上实际仿真,实验结果表明:该系统具有良好的检测和控制功能,实用性很强。1 系统设计方案比较及论证 对于液位进行控制的方式有很多,而应用较多的主要有2种,一种是通过简单的机械控制装置来实现,而另一种是由复杂的控制器来控制。两种方式的实现简介如下: (1)简单的机械式控制方式。其常用形式有浮标式、电极式等,这种控制形式的优点是结构简单,成本低廉。存在问题是精度不高,不能进行数值显示,另外很容易引起误动作,且只能单独控制,与计算机进行通信较难实现。 (2)复杂控制器控制方式。这种控制方式是通过安装在水塔出口管道上的压力传感器来把出口水压变成标准工业电信号的模拟信号,再经过前置放大、AD转换模块变换成数字信号传送到单片机中,而后经单片机运算和给定参量的比较,进行PID运算,得出调节参量;最后经由DA变换给调压、变频调速装置输入给定端,控制其输出电压变化,来调节电机转速,以达到控制水箱液位的目的。 针对上述2种控制方式,以及设计需达到的性能要求,这里选取第二种控制方式,同时考虑到成本问题需要把PID控制去掉。最终形成的方案是,利用单片机为控制核心,设计一个对水塔水位能进行自动监控的工控系统。根据监控对象的特征,要求实时检测水塔的液位高度,并与开始预设定的上、下限值做比较,由单片机控制固态继电器的开断进行液位的调整,最终达到液位的预设定值范围内。检测值若高于上限设定值时,要求报警,同时断开继电器,使水泵停止上水;检测值若低于下限设定值,要求报警,同时开启继电器,控制水泵开始上水。现场在LCD1602液晶屏上实时显示测量值,从而实现对水箱液位的自动监控。 在功能上,本设计还预留了两个调参按键,通过这两个按键可以自由设定水塔内水位的上下限值,以此来实现人工可控功能。2 系统原理框图 图1 系统原理框图3 工作原理基于51单片机实现液位控制的控制器是以STC89C52RC芯片为核心,由键盘、LCD1602液晶显示、ADC0804模数转换、液压传感器、开关电源、蜂鸣报警、电磁继电器等部分组成。工作过程如下:水塔液位发生变化时,引起水塔中液压传感器的输出电压值变化,即把压力变化量转化成电压信号;该信号经过运算放大电路放大后变成幅度为05 V标准信号,送入AD转换器,AD转换器把模拟信号量变成数字信号量,再由单片机进行实时数据采集,并进行处理,根据设定要求控制输出,同时由液晶屏显示液位高度。通过键盘能够自由设置水位上下限值。该系统控制器的最大特点是可直观地显示水位占水塔容积的百分量,并可任意控制水位上下限高度。 4 硬件设计液位控制器的硬件主要包括由单片机、液压传感器(带变送器)、键盘电路、液晶显示电路、AD转换器和输出控制电路等。 4.1 STC89C52单片机简介 单片机采用的是由STC公司生产的双列40脚STC89C52RC芯片。STC公司生产的STC89C52RC单片机,是一款性价比非常高的单片机,普通用户可完全将其当作一般的51单片机来使用,高级用户可使用其扩展功能。 STC公司的单片机内部资源比起来ATMEL公司的单片机要丰富的多,它内部有1280字节的SRAM、8-64K字节的内部程序存储器、2-8K字节的ISP引导码、除P0-P3口外还多出了P4口(PLCC封装)、片内自带8路8位AD(AD系列),片内自带EEPROM、单片机内自带看门狗、双数据指针等。目前STC公司的单片机在国内市场上的占有率与日俱增。其中在这里我们把P0口连接LCD1602液晶显示屏;P1口用于AD转换; P2口用于控制电磁阀、蜂鸣报警和键盘输入;P3口用于读写控制和中断等。下图是STC89C52RC单片机管脚图。 图2 STC89C52RC单片机管脚图4.2 锁存器(74HC573)简介 锁存器,顾名思义,就是把输入端的数据锁存(或送出)到输出端,如下图所示,第11角(锁存端)为高电平的时候,右边D0-D7的输入与左边Q0-Q7的输出是直通的,就是说,输入端是什么电平,输出端就是什么电平,可以把它当作不存在。当第11角为低电平的时候,左右两端就被断开了,无论输入端怎么变化,输出端都不会变化,当第11角由低电平变为高电平的一瞬间,输入端的数据立刻被传送到输出端,并且在11角保持为高电平期间,输出端数据始终的输入端数据相同,如果此时我们再次把第11角设置为低电平,那么以后当输入端无论再怎么变化,输出端都不会变化而是保持刚才第11角在下降沿(由高电平到低电平跳变)之间时输入端的值,这样就达到了锁存数据的目的,这也就是所谓的总线设计思路,一个8位的数据线加一个锁存器后就可以扩接多个元件,当选通哪个元件的片选信号,就送数据给那个元件。 图3 74HC573管脚图4.3 ADC0804简介 ADC0804是8位全MOS中速A/D 转换器,它是逐次逼近式A/D 转换器,片内有三态数据输出锁存器,可以和单片机直接接口。单通道输入,转换时间大约为100us。ADC0804 转换时序是:当CS0 许可进行A/D 转换。WR由低到高时,A/D开始转换。CS与WR同时有效时启动A/D转换,转换结束产生INTR 信号(低电平有效),可供查询或者中断信号。在CS和RD 的控制下可以读取数据结果。在使用时可选择中断、查询和延时等待3种方式编制AD转换程序。本实验没有使用INTR信号,而是采用了延时等待的方式,以便把中断口留给LCD1602液晶显示屏接线使用。AD转换电路在控制器中起主导作用,用它来将液压传感器输出的模拟电压信号转换成单片机能处理的数字量。下图是AD转换部分原理图,在接线时先要经过运算放大器和分压电路把传感器输出的电流信号转换成电压信号,然后输入到AD转换器。由于实际条件较为有限,在此暂时由电位器来代替模拟液压传感器传回的电压信号量。 图4 ADC0804与单片机接线图4.4 单片机与继电器及蜂鸣器的接口电路简介 采用光电耦合器的开关量输出电路如下图所示。+5V电源为单片机电源,+24V电源为开关量输出电源,两个电源是隔离的。当单片机输出端口输出高电平时,经与非门电路,A点为低电平,经光耦器件使驱动晶体管V导通,出口继电器J得电吸合。当输出端输出低电平时,经与非门电路,A点输出高电平,经光耦器件使V截止,J释放。以此来控制水泵执行运行或停止工作。 图5 单片机与继电器接口电路原理图说明:P2.5口接的J,是为了判断接触器是否吸合,从而判知水泵是否得电,以此来检测配合完成单片机内部程序的运行。也就是说程序流程图上的“判断水泵的前一个工作状态”就是通过此处的接触器常开触点J的通断来判断的。 图6 单片机与蜂鸣器接口电路原理图4.5 井中缺水信号检测电路 图7 井中缺水信号检测电路说明:通过井中的两电极是否导通来判断井中是否缺水,当井中水位过低、不足以淹没两检测电极,则P2.0口会检测到一个低电平输入信号,单片机可判知井中缺水,并作出相应的动作指令,如缺水报警、水泵停机等紧急动作。4.6 压力传感器介绍经过市场及网上实际调查发现,目前的液压传感器价格普遍偏高,多为高规格工业用品。为实现低价位高功能,在此我们通过气压传感器改制了一个液压传感器。同样可以满足实际要求。传感器使用SY一9411LD型变送器,它内部含有1个压力传感器和相应的放大电路。该压力传感器是美国SM公司生产的5552型OEM压阻式压力传感器,其有全温度补偿及标定(O70),传感器经过特殊加工处理,用坚固的耐高温塑料外壳封装。其引脚分布如图3所示。1脚为信号输出(一);2脚为信号输出(一);3脚为激励电压;4脚为地;5脚为信号输出(+);6脚为信号输出(+)。 在水塔底部安装1根直径为5 mm的软管,一端安装在水塔底部;另一端与传感器连接。水塔水位高度发生变化时,引起软管内气压变化,然后传感器把气压转换成电压信号,输送到AD转换器。 图8 SY-9411L-D型变送器引脚结构图4.7 LCD1602液晶显示屏接线图及其引脚功能图 图9 LCD1602与单片机的接线图 图10 LCD1602液晶屏的各引脚功能图4.8 开关电源部分随着全球对能源问题的重视,电子产品的耗能问题将愈来愈突出,如何降低其待机功耗,提高供电效率成为一个亟待解决的问题。传统的线性稳压电源虽然电路结构简单、工作可靠,但它存在着效率低(只有40% 50%)、体积大、铜铁消耗量大,工作温度高及调整范围小等缺点。为了提高效率,人们研制出了开关式稳压电源,它的效率可达85% 以上,稳压范围宽,除此之外,还具有稳压精度高、不使用电源变压器等特点,是一种较理想的稳压电源。正因为如此,开关式稳压电源已广泛应用于各种电子设备中,本着节能环保、电能高效利用的原则,本设计选用了开关电源为整个模块供电。下面是对开关电源基本原理的简单介绍。1 开关式稳压电源的基本工作原理 开关式稳压电源接控制方式分为调宽式和调频式两种,在实际的应用中,调宽式使用较多,在目前开发和使用的开关电源集成电路中,绝大多数为脉宽调制型。因此下面就主要介绍调宽式开关稳压电源。调宽式开关稳压电源的基本原理可参见下图。 图11 调宽式开关稳压电源的基本原理对于单极性矩形脉冲来说,其直流平均电压Uo取决于矩形脉冲的宽度,脉冲越宽,其直流平均电压值就越高。直流平均电压。可由公式计算,即Uo=Um×T1/T,式中Um为矩形脉冲最大电压值;T为矩形脉冲周期;T1为矩形脉冲宽度。从上式可以看出,当Um 与T 不变时,直流平均电压Uo 将与脉冲宽度T1 成正比。这样,只要我们设法使脉冲宽度随稳压电源输出电压的增高而变窄,就可以达到稳定电压的目的。2 开关式稳压电源的原理电路 开关式稳压电源的基本电路框图如图二所示。交流电压经整流电路及滤波电路整流滤波后,变成含有一定脉动成份的直流电压,该电压进人高频变换器被转换成所需电压值的方波,最后再将这个方波电压经整流滤波变为所需要的直流电压。 控制电路为一脉冲宽度调制器,它主要由取样器、比较器、振荡器、脉宽调制及基准电压等电路构成。这部分电路目前已集成化,制成了各种开关电源用集成电路。控制电路用来调整高频开关元件的开关时间比例,以达到稳定输出电压的目的。 图12 开关电源基本电路框图 5. 软件设计5.1 程序流程图 图13 程序流程图5.2 程序流程图解析1 正常工作时:(1)假设初始时水塔中无水,经过开始、初始化程序后首先判断是否有按键键入,如果有的话执行按键调试子程序,通过按键可以设定上限位,下限位值。设定完成后再执行AD转换,接下来是判断一下液晶屏上是否有报警指示输出,如果有的话就不执行显示水塔液位这一子程序,直接判断是否首次启动AD转换;否则在液晶屏上显示通过AD转换得来的水塔水位值。下一步再判断AD转换是否是首次启动,是首次启动就直接判断测量值是否小于预设的上限位AD值,如果此时小于上限位,再判断是否小于下限位AD值,如果判得小于下限位则再判断井中是否有水,接着如果判得井中有水就执行上水工作。经过一个延时程序后再执行下一次循环。(2)有所不同的是在执行到判得检测值大于下限位时不执行上述循环,而是再判断之前水泵的工作状态,如果之前水泵是上水状态则转到判断井中是否有水,接着再执行上水工作,否则继续循环保持水泵停机状态。(3)当水塔中的水高出上限位,此时执行断开继电器这一指令,让水泵停机。到此,上水工作完成。继续循环检测,用户用水会使水塔水位低于上限值,这时再执行判断之前水泵是否在上水状态,如果判得之前水泵没在上水状态则继续执行循环判断,如此一来就保证了低于水位下限时水泵开始上水,并一直上水达到上限位为止。再保持水塔水位用到低于下限位时开始打水。2 出现故障时:(1)当井中水位传感器检测到井中缺水时会调用报警子程序,在液晶屏上显示“井中缺水”字样,并响起蜂鸣器,同时断开控制水泵的继电器。再执行一个长延时子程序,等待井中积攒下足够的水后再执行上水工作。(2)当判断AD值始终保持不变次数达到十次时,则需要再判断控制水泵的继电器是否一直吸合,如果满足这两个条件则可判知水泵可能出现故障,这时就需要液晶显示“水泵故障”,同时蜂鸣报警,并立即断开控制水泵的继电器。6 实验仿真结果 根据所设计系统的软件流程图,编写相应的程序在kill软件环境下实现仿真,并且还通过51单片机实验开发板进行了模拟实验。实验结果表明,该系统能够实现水位检测、电机故障检测、处理和报警等功能,具有良好的检测控制功能,可移植性和扩展性强。7 结束语 该系统设计是基于在单片机嵌入式系统基础上而设计的,充分利用单片机强大控制功能,该检测控制系统经过软件仿真实验和单片机实验开发板模拟实验,基本实现了水位模拟检测、电机故障模拟检测、处理和报警等功能。进一步优化了系统软硬件整体功能,可实时实现水塔自动控制,因此,该系统在水塔自动控制领域有着广阔的应用前景。致 谢经过半个多月的匆忙准备,我们组所选的“基于51单片机控制的水塔自动供水系统”终于小有所成。在这期间非常感谢我的导师陈毅鹏老师和张慧明老师,还有所有培育过我的老师们!是他们悉心指导、耐心教诲下才让我逐渐发现知识的“庐山真面目”,并从中体验到了学习研究过程中所带来的巨大乐趣。这些天我还体悟到一个道理:任何一件伟大的事情都是由若干个细节堆砌而成的,要想取得最后的成功,那就必须把握好中间过程的每一个细节。同时在这里我也要感谢我的队友们,是大家的共同努力才赢得了这次小小的胜利,团队的力量是伟大的,三人行必有我师焉。路漫漫其修远兮,吾将上下而求索!在今后的工作学习中我会深深的记住并运用此次获得的经验教训,相信以后的日子里在该行业领域我会有更大的收获。附 录附录1 PCB原理图附录2 C程序#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit adrd=P37; /IO口定义sbit diola=P25;sbit dula=P26;sbit wela=P27; sbit BEEP=P23 ; /蜂鸣器驱动线sbit LCD_RS = P35; sbit LCD_RW = P36;sbit LCD_EN = P34;bit presence,flag;uchar code cdis1 = " PLEASE CHECK "uchar code cdis2 = " DEEP: "uchar code cdis3 = "TH: TL: "unsigned char data deep_data2 = 0x00,0x00;unsigned char data deep_alarm2 = 0x0a,0xff;unsigned char data display5 = 0x00,0x00,0x00,0x00,0x00; /深度值显示unsigned char data display13 = 0x00,0x00,0x00; unsigned char code mytab18 = 0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00;unsigned char code mytab28 = 0x01,0x1b,0x1d,0x19,0x1d,0x1b,0x01,0x00; /小喇叭#define delayNOP(); _nop_();_nop_();_nop_();_nop_();unsigned char deep,deep_comp,timecount,count,compare_th,compare_tl;/数据存放位置void Disp_deep_alarm(uchar addr,uchar num);void Natural_Menu ();void spk(uchar addr);void set_deep_alarm();void deep_compare();void beep();/*/void delay1(int ms) unsigned char y; while(ms-) for(y = 0; y<250; y+) _nop_(); _nop_(); _nop_(); _nop_(); /检查LCD忙状态 /*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据*/*/bit lcd_busy() bit result; LCD_RS = 0; LCD_RW = 1; LCD_EN = 1; delayNOP(); result = (bit)(P0&0x80); LCD_EN = 0; return(result); /*/*写指令数据到LCD */ /*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 /*/void lcd_wcmd(uchar cmd) delay1(10); LCD_RS = 0; LCD_RW = 0; LCD_EN = 0; _nop_(); _nop_(); P0 = cmd; delayNOP(); LCD_EN = 1; delayNOP(); LCD_EN = 0; /*/*写显示数据到LCD /*RS=H,RW=L,E=高脉冲,D0-D7=数据。 /*/void lcd_wdat(uchar dat) delay1(10); LCD_RS = 1; LCD_RW = 0; LCD_EN = 0; P0 = dat; delayNOP(); LCD_EN = 1; delayNOP(); LCD_EN = 0; /*/* LCD初始化设定 /*/void lcd_init() delay1(15); lcd_wcmd(0x01); /清除LCD的显示内容 lcd_wcmd(0x38); /16*2显示,5*7点阵,8位数据 delay1(5); lcd_wcmd(0x38); delay1(5); lcd_wcmd(0x38); delay1(5); lcd_wcmd(0x0c); /显示开,关光标 delay1(5); lcd_wcmd(0x06); /移动光标 delay1(5); lcd_wcmd(0x01); /清除LCD的显示内容 delay1(5);/*/* 设定显示位置 /*/void lcd_pos(uchar pos) lcd_wcmd(pos | 0x80); /数据指针=80+地址变量/*/*us级延时函数 /*/void Delay(unsigned int num) while( -num );/*/* 读取深度 /*/ Read_deep(void) uchar a,sl; TR0=0; /关中断,防止读数错误 wela=1; P0=0; /选通ADCS LCD_RW=0;/AD写入(随便写个什么都行, LCD_RW=1; P0=0xff; /关闭ADCS Delay(10); wela=0; /关闭有AD片选信号锁存器的锁/存端以防止在操作数码管时使AD的片选发生变化 for(a=20;a>0;a-) ; /需要注意的是ADC0804在写和/读之间的时间间隔要足够长否则无法读出数据 for(a=20;a>0;a-); /这里把显示部分放这里的原 wela=1; /重新打开有AD片选信号锁存器 P1=0xff; /读取P1口之前先给其写全1 P0=0; /选通ADCS adrd=0; /AD读使能 sl=P1;/AD数据读取赋给P1口 adrd=1; P0=0xff; /关闭ADCS LCD_RW=0; deep_data0 = sl ; /深度 TR0=1; /开中断/*/* 数据转换与深度显示 /*/ Disp_Temperature() display4=deep_data0&0x0f; display0=(display4*10/16)+0x30; display4=(deep_data0&0xf0)>>4)|(deep_data1&0x0f)<<4); display3=display4/100+0x30; display1=display4%100; display2=display1/10+0x30; display1=display1%10+0x30; if(display3=0x30) /高位为0,不显示 display3=0x20; if(display2=0x30) /次高位为0,不显示 display2=0x20; ; ; lcd_pos(0x07); lcd_wdat(display3); /百位数显示 lcd_wdat(display2); /十位数显示 lcd_wdat(display1); /个位数显示 lcd_wdat('.'); lcd_wdat(display0); /小数位数显示 lcd_wdat('%'); /显示%void beep() unsigned char y; for (y=0;y<100;y+) Delay(70); BEEP=!BEEP; /BEEP取反 ; BEEP=1; /关闭蜂鸣器Delay(25000);/*/* ad0804 正常显示菜单 /*/void Natural_Menu () uchar m; lcd_init(); /初始化LCD lcd_pos(0); /设置显示位置为第一行的第1个 for(m=0;m<16;m+); lcd_wdat(cdis2m); /显示字符 lcd_pos(0x40); /设置显示位置为第二行第1个字 for(m=0;m<16;m+); lcd_wdat(cdis3m); /显示字符 Read_deep(); Disp_deep_alarm(0x43,0); /显示deeph值 Disp_deep_alarm(0x4b,1); /显示deepl值 Disp_Temperature(); /显示实时深度值/*/ 显示报警深度/*/void Disp_deep_alarm(uchar addr,uchar num) /0=TH,1=TL display12=deep_alarmnum/100+0x30; display10=deep_alarmnum%100; display11=display10/10+0x30; display10=display10%10+0x30; lcd_pos(addr); lcd_wdat(display12); /百位数显示 lcd_wdat(display11); /十位数显示 lcd_wdat(display10); /个位数显示 /*/ Time0中断函数/*