基于STC89C52RC的模拟智能灌溉系统Word文档下载推荐.docx
《基于STC89C52RC的模拟智能灌溉系统Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《基于STC89C52RC的模拟智能灌溉系统Word文档下载推荐.docx(26页珍藏版)》请在冰豆网上搜索。
核心控制模块由STC89C52RC芯片、排阻、复位和晶振电路组成;
按键输入单元由4个独立按键组成;
水泵驱动单元由继电器和绿色指示灯组成,显示单元由数码管显示模块完成,湿度数据采集和转换由单电源低功耗的8位CMOS数据采集器件PCF8591完成。
图2-1系统总电路图
2.2单片机控制电路
STC89C52RC是STC公司出产的一种低功耗、高性能CMOS8位微控制器,具8K在系统可编程Flash存储器。
STC89C52使用经典的MCS-51内核,但做了很多的改进使得芯片具有传统51单片机不具备的功能。
在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
单片机是一个完整电路系统的核心控制部分,控制着整个系统是否能成功运行并达到设定的目标。
单片机的最小系统由晶振电路和复位电路组成,如图2-2。
(1)复位电路
在系统开始运行的时候,都需要对系统进行一个初始化,而在单片机的最小系统中,复位电路就是为了把电路系统初始化而存在的,复位电路的原理就是在将单片机的电阻和电容接在单片机的复位引脚RST上,实现一个上电复位,只有当复位电平持续两个机器周期以上时复位才有效。
具体的数值可以由RC电路计算出来。
(2)晶振电路(时钟电路)
只要是一个完整的单片机系统,就一定会有晶振,晶振是通过一种能把机械能和电能进行相互转化的晶体在共振的状态下进行工作,从而提供稳定而精确的单频振荡。
晶振在整个单片机系统里的作用是不可或缺的,它与单片机的内部电路相结合,产生一个单片机所需要的时钟频率,晶振提供的时钟频率越高,单片机的运行速度就会越快,单片对整个系统所执行的一切指令都是建立在晶振提供的这个时钟频率之上的。
图2-2单片机最小系统
2.3按键输入单元
本设计的按键输入单元是由4个规格为6*6*5的四脚按键构成的如图2-3所示。
图2-3按键输入
按键功能如下:
(1)、按键S7设定为系统工作状态切换按键;
(2)、手动工作状态下按键S6、S5、S4功能设定如下:
按下S6关闭蜂鸣器提醒功能,再次按下S6打开蜂鸣器提醒功能,如此循环;
S5功能设定为打开灌溉系统;
S4功能设定为关闭灌溉系统。
(3)、自动工作状态下按键S6、S5、S4功能设定如下:
S6功能设定为湿度阈值调整按键,按下S6后,进入湿度阈值调整界面(如图2-4所示),此时按下S5为湿度阈值加1,按下S4湿度阈值减1,再次按下S6后,系统将新的湿度阈值保存到EEPROM中,并退出湿度阈值设定界面。
图2-4湿度阀值设定界面
2.4湿度检测单元
PCF8591是一个单片集成、单独供电、低功耗、8-bitCMOS数据获取器件。
如图2-5所示。
PCF8591具有4个模拟输入、1个模拟输出和1个串行I²
C总线接口。
PCF8591的3个地址引脚A0,A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。
在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。
图2-5PCF8591
以电位器Rb2输出电压信号模拟湿度传感器输出信号,且假定电压信号与湿度成正比例关系H湿度=KVRb2(K为常数),Rb2电压输出为5V时对应湿度为99%。
模拟检测单元如图2-6所示。
图2-6模拟湿度检测单元
2.5RTC(实时时钟)单元
DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.0V~5.5V。
采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
DS1302内部有一个31×
8的用于临时性存放数据的RAM寄存器。
DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力。
“模拟智能灌溉系统”通过读取DS1302时钟芯片相关寄存器获得时间,DS1302芯片时、分、秒寄存器在程序中设定为系统进行初始化设定,时间为08时30分。
单元原理图如图2-6所示。
图2-6RTC单元
2.6数码管显示单元
数码管的显示可以分为两种:
静态显示和动态显示。
静态显示的段选位和位选位均单独连接,因此占用的I/O接口多,无法扩展多个数码管。
而数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划的同名端连在一起,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是那个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,通过分时轮流控制各个数码管的COM端,就使各个数码管轮流受控显示,这就是动态驱动。
数码显示管分为共阳数码管和共阴数码管两种。
本设计采用共阴极数码显示管做显示电路。
由于采用的是共阴的数码显示管,所以只要数码管的各引脚为高电平,那么其对应的二极管就会发光。
电源供电电压为5V,当上拉电阻选用220Ω电阻时灌电流为22mA。
不会损坏单片机的I/O口,同时也可以为数码显示管起到限制电流的保护作用。
如图2-7所示。
图2-7数码显示单元
时间及湿度数据显示格式如图2-8所示:
图2-8数据显示格式
2.7EEPROM存储单元
AT24C02支持I2C,总线数据传送协议I2C,总线协议规定任何将数据传送到总线的器件作为发送器。
任何从总线接收数据的器件为接收器。
数据传送是由产生串行时钟和所有起始停止信号的主器件控制的。
主器件和从器件都可以作为发送器或接收器,但由主器件控制传送数据(发送或接收)的模式,由于A0、A1和A2可以组成000~111八种情况,即通过器件地址输入端A0、A1和A2可以实现将最多8个AT24C02器件连接到总线上,通过进行不同的配置进行选择器件。
在本次设计中系统通过EEPROM存储湿度阈值,自动工作状态下,可通过按键S6、S5、S4设置和保存阈值信息。
原理如图2-9所示。
图2-9EEPROM存储单元
2.8水泵增湿模拟单元
水泵增湿模拟单元与单片机的p2.5连接,当传感器检测的湿度值低于设定值50%时,单片机给三极管一个高电平,电路处于导通状态,相当于接通一个开关,使水泵进行灌溉(继电器工作,绿色指示灯亮),在灌溉的过程中,当传感器检测到的湿度值高于设定值50%时,单片机又给三极管一个低电平,这时三极管截止,相当于一只断开的开关,使水泵停止灌溉(继电器停止工作,绿色指示灯灭),将程序录入单片机后,通过单片机对三极管的控制便能控制水泵是否进行灌溉。
图2-10是水泵模块的系统原理图。
图2-10水泵增湿模拟单元
2.9报警输出单元
系统工作于手动工作状态下时,若当前湿度低于湿度阈值,蜂鸣器发出提示音,并可通过按键S6关闭提醒功能。
如图2-11所示。
图2-11报警输出单元
3系统软件设计
3.1程序流程图
首先依照系统所要实现的功能和实现这个功能的原理,设计一个主程序流程图,智能灌溉控制系统工作流程图如图3-1所示。
然后按照这个流程图在KeilμVision3软件中进行程序的开发(设计与编译)。
接通电源后开始,进行单片机数据初始化、显示单元初始化、传感器采集数据并显示到显示单元上,接着判断手动模式按钮S7是否按下,若按下,则进入手动模式,程序循环扫描设定按键是否被按下,当按键按下时,进入设定模式,设定温湿度值下限,若没有按下按键则继续采集温湿度值。
接着返回到测量程序,若处于灌溉状态,根据湿度,阀值给出提醒,由用户决定如何控制。
若手动模式按钮S7没有按下,则进入自动模式,程序循环扫描设定按键是否被按下,当按键按下时,进入设定模式,设定温湿度值下限,若没有按下按键则继续采集温湿度值。
接着返回到测量程序,若处于灌溉状态,则当检测到的湿度值高于设定值50%时停止灌溉,若处于非灌溉状态,则判断检测到的湿度值是否小于设定值的50%,若小于,则启动水泵灌溉,若不小于,则继续采集温湿度,如此循环进行下去。
图3-1程序流程图
3.2程序源代码
/******************************************************************************************************************main.c******************************************************************************************************************/
#include<
reg52.h>
deputy.h>
sbitwr=P3^6;
sbits7=P3^0;
sbits6=P3^1;
sbits5=P3^2;
sbits4=P3^3;
ucharcodetab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
ucharyi,er,san,si,wu,liu,qi,ba;
ucharss7,ss6,jia,jian,kai;
ucharfazhi=50;
voidkeyscan();
voidallinit();
voiddisplay1(ucharyi,ucharer);
voiddisplay2(ucharsan,ucharsi);
voiddisplay3(ucharwu,ucharliu);
voiddisplay4(ucharqi,ucharba);
voidmain()
{
ucharshidu;
allinit();
dsinit();
fazhi=IIRead(0x10);
while
(1)
{
keyscan();
shidu=ADRead(0x03);
dsget();
if(ss7==1)
{
P2=0X80;
P0=0XFD;
qi=shidu/10;
ba=shidu%10;
yi=shijian[2]/10;
er=shijian[2]%10;
san=10;
si=shijian[1]/10;
wu=shijian[1]%10;
liu=11;
if((shidu<
fazhi)&
&
(ss6==1))
{
if(kai==1)
{
P2=0XA0;
P0=0X10;
}
else
P0=0X00;
}
elseif((shidu<
(ss6==0))
P0=0X50;
P0=0X40;
elseif(shidu>
fazhi)
}
elseif(ss7==0)
P0=0XFE;
if(ss6==1)
if(jia==1)
{
fazhi=fazhi+1;
jia=0;
if(jian==1)
{
fazhi=fazhi-1;
jian=0;
yi=10;
er=10;
san=11;
si=11;
wu=11;
qi=fazhi/10;
ba=fazhi%10;
else
qi=shidu/10;
yi=shijian[2]/10;
if(shidu<
P2=0XA0;
display1(yi,er);
display2(san,si);
display3(wu,liu);
display4(qi,ba);
}
}
voidkeyscan()
if(s7==0)
delay(5);
if(s7==0)
if(ss7==0)ss7=1;
elsess7=0;
while(!
s7);
elseif(s6==0)
if(s6==0)
if(ss6==0)
ss6=1;
ss6=0;
IIwrite(fazhi);
s6);
elseif(s5==0)
if(s5==0)
kai=0;
jia=1;
s5);
elseif(s4==0)
if(s4==0)
kai=1;
jian=1;
s4);
voiddisplay1(ucharyi,ucharer)
P2=0XC0;
P0=0X01;
P2=0XFF;
P0=tab[yi];
delay(5);
P0=0X02;
P0=tab[er];
voiddisplay2(ucharsan,ucharsi)
P0=0X04;
P0=tab[san];
P0=0X08;
P0=tab[si];
voiddisplay3(ucharwu,ucharliu)
P0=0X10;
P0=tab[wu];
P0=0X20;
P0=tab[liu];
voiddisplay4(ucharqi,ucharba)
P0=0X40;
P0=tab[qi];
P0=0X80;
P0=tab[ba];
voidallinit()
P2=0X80;
P0=0XFE;
P0=0XFF;
P2=0XA0;
P0=0X00;
/***************************************Deputy.c**************************************************************************************************************/
intrins.h>
ucharcodestr[]={0,30,8,18,2,4,16};
shijian[7];
voiddelay(ucharz)//延迟一毫秒
uchari,j;
for(i=z;
i>
0;
i--)
for(j=110;
j>
j--);
/*********************************AD转换驱动程序******************************************/
//总线启动条件
voidIIC_Start(void)
SDA=1;
SCL=1;
somenop;
SDA=0;
SCL=0;
//总线停止条件
voidIIC_Stop(void)
//应答位控制
voidIIC_Ack(unsignedcharackbit)
if(ackbit)
{
SDA=0;
else
SDA=1;
//等待应答
bitIIC_WaitAck(void)
if(SDA)
SCL=0;
IIC_Stop();
return0;
return1;
//通过I2C总线发送数据
voidIIC_SendByte(unsignedcharbyt)
unsignedchari;
for(i=0;
i<
8;
i++)
if(byt&
0x80)
{
SDA=1;
else
SDA=0;
somenop;
SCL=1;
byt<
<
=1;
//从I2C总线上接收数据
unsignedcharIIC_RecByte(void)
unsignedcharda;
da<
if(SDA)
da|=0x01;
returnda;
ucharADRead(ucharadd)
uchardate;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_SendByte(0x91);
date=IIC_RecByte();
IIC_Stop();
date=0.39*date;
returndate;
voidIIwrite(uchardate)
IIC_SendByte(0xa0);
IIC_SendByte(0X10);
IIC_SendByte(date);
ucharIIRead(ucharadd)
IIC_SendByte(0xa1);
/*******************************时间驱动程序******************************************/
voidWrite_Ds1302_Byte(unsignedchardat)
unsigne