您的位置 首页 主动

单片机的模仿智能灌溉系统

模拟智能灌溉系统:先上原理图这是用proteus画的模拟图,当然还有实物图,不过都被我放在自己的工作室了(话说明明是实验室好不好)目前是…

模仿智能灌溉体系

先上原理图

这是用proteus画的模仿图,当然还有什物图,不过都被我放在自己的作业室了(话说分明是实验室好不好)现在是在外面进一步学习,我就不把什物晒出来了。

程序的好坏在于它的流程图是否好,所以我就把我其时画的流程图拿了出来!

那么该项目究竟是什么呢?

便是当年竞赛的一个预习题,不过渠道不一样搞得我其时比较难堪就拿了个三等奖回来,哎,期望我嵌入式小组的学弟学妹们能够加油,帮我拿个一等奖回来!了了我心中的惋惜吧!

功用简述:

要求“模仿智能灌溉体系”能够完结土壤湿度丈量、土壤湿度和时刻显现、湿度阈值设定及存储等基本功用。经过电位器Rb2输出电压信号,模仿湿度传感器输出信号,再经过AD并重完结湿度丈量功用;经过DS1302芯片供给时刻信息;经过按键完结灌溉体系操控和湿度阈值调整功用,经过LED完结体系作业状况指示功用。体系硬件电路主要由单片机操控电路、显现单元、ADC并重单元、RTC单元、EEPROM存储单元、继电器操控电路及报警输出电路组成,体系框图如图1所示:

1. 体系作业及初始化状况阐明:

1.1、主动作业状况,依据湿度数据主动操控翻开或封闭灌溉设备,以L1点亮指示;

1.2、手动作业状况,经过按键操控翻开或封闭灌溉设备,以L2点亮指示;

1.3、体系上电后处于主动作业状况,体系初始湿度阈值为50%,此刻若湿度低于50%,灌溉设备主动翻开,到达50%后,灌溉设备主动封闭;

1.4、灌溉设备翻开或封闭经过继电器作业状况模仿。

2. 数码管单元:

“模仿智能灌溉体系”经过读取DS1302时钟芯片相关寄存器取得时刻,DS1302芯片时、分、秒寄存器在程序中设定为体系进行初始化设定,时刻为08时30分。

3. 报警输出单元:

体系作业于手动作业状况下时,若其时湿度低于湿度阈值,蜂鸣器宣布提示音,并可经过按键S6封闭提示功用。

4. 功用按键:

4.1、按键S7设定为体系作业状况切换按键;

4.2、手动作业状况下按键S6、S5、S4功用设定如下:

按下S6封闭蜂鸣器提示功用,再次按下S6翻开蜂鸣器提示功用,如此循环;

S5功用设定为翻开灌溉体系;S4功用设定为封闭灌溉体系。

4.3、主动作业状况下按键S6、S5、S4功用设定如下:

S6功用设定为湿度阈值调整按键,按下S6后,进入湿度阈值调整界面(如图3所示),此刻按下S5为湿度阈值加1,按下S4湿度阈值减1,再次按下S6后,体系将新的湿度阈值保存到EEPROM中,并退出湿度阈值设定界面。

5. 实时时钟:

“模仿智能灌溉体系”经过读取DS1302时钟芯片相关寄存器取得时刻,DS1302芯片时、分、秒寄存器在程序中设定为体系进行初始化设定,时刻为08时30分。

6. 湿度检测单元:

以电位器Rb2输出电压信号模仿湿度传感器输出信号,且假定电压信号与湿度成正比例联系H湿度= KVRb2(K为常数),Rb2电压输出为5V时对应湿度为99%。

7. EEPROM存储单元:

体系经过EEPROM存储湿度阈值,主动作业状况下,可经过按键S6、S5、S4设置和保存阈值信息。

下面将是我写的一些代码了,大三上写的代码,或许不是那么好吧!勿见责啊,其时都没有代码标准的思维,写得比较杂乱,我也由于对它不再想修改了,就不改格局了,因此对看本博客的同学们一共歉意了!

(1)主函数main.c#include#include #include#define  PCF8591 0x90    //PCF8591 地址#include<ds1302.h>//else IOunsigned char AD_CHANNEL;unsigned long xdata  LedOut[8];unsigned int  D[32];sbit LS138A=P2^2;  sbit LS138B=P2^3;sbit LS138C=P2^4;sbit L1=P2^5;sbit L2=P2^6;sbit beed=P1^0;sbit RELAY=P1^1;sbit k4=P1^2;sbit k5=P1^3;sbit k6=P1^4;sbit k7=P1^5; //此表为 LED 的字模, 共阴数码管 0-9  - unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; unsigned char delay1[8]={10,10,0,0,0,0,0,0};unsigned char HUO,flag;unsigned char key,mode,th;/**推迟函数**/         void delay(){unsigned char a=100;while(a--); }/************at24c02功用模块***/void At24c02Write(unsigned char addr,unsigned char dat){I2C_Start();I2C_SendByte(0xa0, 1);//发送写器材地址I2C_SendByte(addr, 1);//发送要写入内存地址I2C_SendByte(dat, 0);    //发送数据I2C_Stop();}unsigned char At24c02Read(unsigned char addr){unsigned char num;I2C_Start();I2C_SendByte(0xa0, 1); //发送写器材地址I2C_SendByte(addr, 1); //发送要读取的地址I2C_Start();I2C_SendByte(0xa1, 1); //发送读器材地址num=I2C_ReadByte(); //读取数据I2C_Stop();return num;    }/*******************************************************************ADC发送字节[指令]数据函数               *******************************************************************/bit ISendByte(unsigned char sla,unsigned char c){Start_I2c();              //发动总线SendByte(sla);            //发送器材地址if(ack==0)return(0);SendByte(c);              //发送数据if(ack==0)return(0);Stop_I2c();               //完毕总线return(1);}/*******************************************************************ADC读字节数据函数               *******************************************************************/unsigned char IRcvByte(unsigned char sla){  unsigned char c;Start_I2c();          //发动总线SendByte(sla+1);      //发送器材地址if(ack==0)return(0);c=RcvByte();          //读取数据0Ack_I2c(1);           //发送非就答位Stop_I2c();           //完毕总线return(c);}unsigned char keysan(void){   if(!k7){while(!k7);return 7;}if(!k6){while(!k6);return 6;}if(!k5){while(!k5);return 5;}    if(!k4){while(!k4);return 4;}return 0;}/**初始设置函数**/void seting(){ unsigned char isFirstRun=0;beed=1;L1=0;L2=1;RELAY=1;mode=1;isFirstRun=!At24c02Read(2);//经过EEPROM的2地址出是否有值来判别是否为第一次运转if(isFirstRun)//若第一次运转{At24c02Write(2,1);//往2地址写入信息供今后开机时判别At24c02Write(1,50);//写入默许阈值50}else{HUO=At24c02Read(1);//从EEPROM的1地址处读出阈值}delay1[6]=HUO/10;delay1[7]=HUO%10;InitTIMER0();          //初始化定时器0Set_RTC(); }/****判别函数***/void chouse(unsigned char key){  switch(key)                      {     case 4:if(mode==1){    if(j==1){  HUO--;delay1[6]=HUO/10;delay1[7]=HUO%10;delay();}   }else { RELAY=1;}break;                 case 5:if(mode==1){if(j==1){   HUO++; if(HUO>99)HUO=99;delay1[6]=HUO/10;delay1[7]=HUO%10;delay();}}else  {RELAY=0;}break;case 6:if(mode==1){  if(flag==1)//在设置形式,保存阈值并退出设置形式{At24c02Write(1,HUO);//在EEPROM的1地址处写入阈值flag=0;}else//不在设置形式,将进入设置形式{flag=1;}}else {beed=(beed==1)?0:1;} break;case 7:if(mode==1){mode=0;L1=0;L2=1;}else {mode=1;L1=1;L2=0;} break;default:break;}if(th99) th=99;l_tmpdisplay[6]=th/10;l_tmpdisplay[7]=th%10; }/**主函数***/void main(){  seting();while(1){    key=keysan();chouse(key);} }void InitTIMER0(void){TMOD=0x01;//定时器设置 16位TH0=0xef;//初始化值TL0=0xf0;ET0=1;TR0=1;EA=1;}/******************************************************************//*                   定时器中止函数                               *//******************************************************************/void tim(void) interrupt 1 using 1//中止,用于数码管扫描{static unsigned char i,num;TH0=0xf5;TL0=0xe0;if(flag==1){//在设置形式P0=table[delay1[i]];}else{//P0=table[l_tmpdisplay[i]];    //查表法得到要显现数字的数码段}switch(i)                      {        case 0:LS138A=0; LS138B=0; LS138C=0; break;         case 1:LS138A=1; LS138B=0; LS138C=0; break;                 case 2:LS138A=0; LS138B=1; LS138C=0; break; case 3:LS138A=1; LS138B=1; LS138C=0; break; case 4:LS138A=0; LS138B=0; LS138C=1; break;case 5:LS138A=1; LS138B=0; LS138C=1; break;case 6:LS138A=0; LS138B=1; LS138C=1; break;case 7:LS138A=1; LS138B=1; LS138C=1; break;}i++;if(i==8){i=0;num++;if(10==num)       //隔段时刻读取1302的数据。时刻距离能够调整{ReadRTC_Flag=1; //运用标志位判别num=0;}}}(2)I2C总线函数#include#include #include #define  NOP()   _nop_()   /* 界说空指令 */#define  _Nop()  _nop_()   /*界说空指令*/sbit     SCL=P2^1;       //I2C  时钟 sbit     SDA=P2^0;       //I2C  数据 bit ack;                 /*应对标志位*//*******************************************************************起动总线函数               函数原型: void  Start_I2c();  功用:     发动I2C总线,即发送I2C开端条件.  ********************************************************************/void Start_I2c(){SDA=1;         /*发送开端条件的数据信号*/_Nop();SCL=1;_Nop();        /*开端条件树立时刻大于4.7us,延时*/_Nop();_Nop();_Nop();_Nop();    SDA=0;         /*发送开端信号*/_Nop();        /* 开端条件确定时刻大于4μs*/_Nop();_Nop();_Nop();_Nop();       SCL=0;       /*钳住I2C总线,预备发送或接纳数据 */_Nop();_Nop();}/*******************************************************************完毕总线函数               函数原型: void  Stop_I2c();  功用:     完毕I2C总线,即发送I2C完毕条件.  ********************************************************************/void Stop_I2c(){SDA=0;      /*发送完毕条件的数据信号*/_Nop();       /*发送完毕条件的时钟信号*/SCL=1;      /*完毕条件树立时刻大于4μs*/_Nop();_Nop();_Nop();_Nop();_Nop();SDA=1;      /*发送I2C总线完毕信号*/_Nop();_Nop();_Nop();_Nop();}/*******************************************************************字节数据发送函数               函数原型: void  SendByte(UCHAR c);功用:     将数据c发送出去,能够是地址,也能够是数据,发完后等候应对,并对此状况位进行操作.(不应对或非应对都使ack=0)     发送数据正常,ack=1; ack=0一共被控器无应对或损坏。********************************************************************/void  SendByte(unsigned char  c){unsigned char  BitCnt;for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8位*/{if((c<0; b--){for(a=2; a>0; a--);}}/******************************************************************************** 函 数 名         : I2C_Start()* 函数功用           : 开端信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号发生一个下降沿* 输    入         : 无* 输    出         : 无* 备    注         : 开端之后I2C_SDA和I2C_SCL都为0****************************************************************************/void I2C_Start(){SDA = 1;I2C_Delay10us();SCL = 1;I2C_Delay10us();//树立时刻是I2C_SDA坚持时刻>4.7usSDA = 0;I2C_Delay10us();//坚持时刻是>4usSCL = 0;            I2C_Delay10us();        }/******************************************************************************* 函 数 名           : I2C_Stop()* 函数功用             : 停止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号发生一个上升沿* 输    入           : 无* 输    出              : 无* 备    注           : 完毕之后坚持I2C_SDA和I2C_SCL都为1;一共总线闲暇******************************************************************************/void I2C_Stop(){SDA = 0;I2C_Delay10us();SCL = 1;I2C_Delay10us();//树立时刻大于4.7usSDA = 1;I2C_Delay10us();        }/******************************************************************************** 函 数 名           : I2cSendByte(uchar num)* 函数功用              : 经过I2C发送一个字节。在I2C_SCL时钟信号高电平期间,*                    * 坚持发送信号I2C_SDA坚持安稳* 输    入           : num ,ack* 输    出              : 0或1。发送成功回来1,发送失利回来0* 备    注           : 发送完一个字节I2C_SCL=0, 需求应对则应对设置为1,否则为0******************************************************************************/unsigned char I2C_SendByte(unsigned char dat, unsigned char ack){unsigned char a = 0,b = 0;//最大255,一个机器周期为1us,最大延时255us。for(a=0; a<8; a++)//要发送8位,从最高位开端{SDA = dat >> 7;     //开端信号之后I2C_SCL=0,所以能够直接改动I2C_SDA信号dat = dat << 1;I2C_Delay10us();SCL = 1;I2C_Delay10us();//树立时刻>4.7usSCL = 0;I2C_Delay10us();//时刻大于4us        }SDA = 1;I2C_Delay10us();SCL = 1;while(SDA && (ack == 1))//等候应对,也便是等候从设备把I2C_SDA拉低{b++;if(b > 200)     //假如超越200us没有应对发送失利,或许为非应对,一共接纳完毕{SCL = 0;I2C_Delay10us();return 0;}}SCL = 0;I2C_Delay10us();return 1;        }/******************************************************************************** 函 数 名           : I2cReadByte()* 函数功用             : 运用I2c读取一个字节* 输    入           : 无* 输    出              : dat* 备    注           : 接纳完一个字节I2C_SCL=0*****************************************************************************/unsigned char I2C_ReadByte(){unsigned char     a = 0,dat = 0;SDA = 1;            //开端和发送一个字节之后I2C_SCL都是0I2C_Delay10us();for(a=0; a<8; a++)//接纳8个字节{SCL = 1;I2C_Delay10us();dat <<= 1;dat = SDA;I2C_Delay10us();SCL = 0;I2C_Delay10us();}return dat;        }其H文件:extern bit ack;//起动总线函数extern void Start_I2c();//完毕总线函数  extern void Stop_I2c();//应对子函数extern void Ack_I2c(bit a);//字节数据发送函数extern void  SendByte(unsigned char  c);//有子地址发送多字节数据函数               extern bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no) ;//无子地址发送多字节数据函数   extern bit ISendStrExt(unsigned char sla,unsigned char *s,unsigned char no);//无子地址读字节数据函数               extern unsigned char RcvByte();extern void I2C_Start();extern      void I2C_Stop();extern         unsigned char I2C_SendByte(unsigned char dat, unsigned char ack);extern         unsigned char I2C_ReadByte();(3)DS1302时钟函数:#include //包括头文件,一般状况不需求改动,头文件包括特别功用寄存器的界说#include sbit SCK=P3^6;    //时钟    sbit SDA=P3^4;    //数据    sbit RST = P3^5;// DS1302复位bit ReadRTC_Flag;//界说读DS1302标志unsigned char l_tmpdate[7]={0,30,8,15,5,3,8};//秒分时日月周年08-05-15 12:00:00unsigned char l_tmpdisplay[8];code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年 最低位读写位code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};  //code unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //共阴数码管 0-9  - 平息‘表/******************************************************************//*                   写一个字节                                   *//******************************************************************/void Write_Ds1302_Byte(unsigned  char temp) {unsigned char i;for (i=0;i<8;i++)         //循环8次 写入数据{ SCK=0;SDA=temp&0x01;     //每次传输低字节 temp>>=1;          //右移一位SCK=1;}}   /******************************************************************//*                  写入DS1302                                    *//******************************************************************/void Write_Ds1302( unsigned char address,unsigned char dat )     {RST=0;_nop_();SCK=0;_nop_();RST=1;    _nop_();                    //发动Write_Ds1302_Byte(address);    //发送地址Write_Ds1302_Byte(dat);        //发送数据RST=0;                      //康复}/******************************************************************//*                   读出DS1302数据                               *//******************************************************************/unsigned char Read_Ds1302 ( unsigned char address ){unsigned char i,temp=0x00;RST=0;_nop_();_nop_();SCK=0;_nop_();_nop_();RST=1;_nop_();_nop_();Write_Ds1302_Byte(address);for (i=0;i<8;i++)         //循环8次 读取数据{        if(SDA)temp=0x80;            //每次传输低字节SCK=0;temp>>=1;            //右移一位_nop_();_nop_();_nop_();SCK=1;} RST=0;_nop_();                  //以下为DS1302复位的安稳时刻_nop_();RST=0;SCK=0;_nop_();_nop_();_nop_();_nop_();SCK=1;_nop_();_nop_();SDA=0;_nop_();_nop_();SDA=1;_nop_();_nop_();return (temp);            //回来}/******************************************************************//*                   读时钟数据                                   *//******************************************************************/void Read_RTC(void)            //读取 日历{unsigned char i,*p;p=read_rtc_address;         //地址传递for(i=0;i<7;i++)            //分7次读取 秒分时日月周年{l_tmpdate[i]=Read_Ds1302(*p);p++;}}/******************************************************************//*                  设定时钟数据                                  *//******************************************************************/void Set_RTC(void)            //设定 日历{unsigned char i,*p,tmp;for(i=0;i<7;i++){       //BCD处理tmp=l_tmpdate[i]/10;l_tmpdate[i]=l_tmpdate[i]%10;l_tmpdate[i]=l_tmpdate[i]+tmp*16;}  Write_Ds1302(0x8E,0X00);p=write_rtc_address;    //传地址    for(i=0;i<7;i++)        //7次写入 秒分时日月周年{Write_Ds1302(*p,l_tmpdate[i]);p++;  }Write_Ds1302(0x8E,0x80);}其H文件:extern void Write_Ds1302_byte(unsigned char temp); extern void Write_Ds1302( unsigned char address,unsigned char dat );extern unsigned char Read_Ds1302 ( unsigned char address );extern void Read_RTC(void);//read RTC extern void Set_RTC(void); //set RTC extern void InitTIMER0(void);//inital timer0extern bit ReadRTC_Flag;//界说读DS1302标志extern  unsigned char l_tmpdisplay[8];extern unsigned char l_tmpdate[7];extern     bit ReadRTC_Flag;//界说读DS1302标志

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ziliao/zhudong/263805.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部