花卉自动浇水系统仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
我的毕业设计,自动浇水系统的仿真程序,是基于单片机的
单片机源码如下:
- #include <reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit Key_Min=P3^5;
- sbit Key_Add=P3^6;
- sbit Key_Set=P3^7;
- sbit Key_Mode=P1^0;
- sbit Key_Low=P1^2;
- sbit Key_High=P1^3;
- sbit led1=P3^2; //绿灯,浇水状态,与继电器同步
- sbit led2=P3^3; //黄灯,水位上限
- sbit led3=P3^4; //红灯,水位下限
- //------------继电器引脚-------------------
- sbit JD=P2^1;
- sbit sw=P1^6;
- sbit BEEP=P2^0;
- uchar HumTab=0; //温度浇水时上下限切换的标志,记录是上一个状态,0是缺少,1是盛水。
- sbit rs=P2^5; //命令/数据选择
- sbit rw=P2^6; //读写口
- sbit e=P2^7; //锁存控制
- sbit DQ = P1^5;
- bit DS18B20_IS_OK = 1; //DS18B20 正常标志
- uchar Temp_Value[]={0x00,0x00}; //读到的温度值
- #define NOP() _nop_() /* 定义空指令 */
- #define _Nop() _nop_() /*定义空指令*/
- uchar ThresholdL=20; //湿度阀值下限,低于这个值就开始浇水;
- uchar ThresholdH=50; //湿度阀值上限,浇水超过这个值就停止浇水
- uchar code df_Table[]={ 0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9 };
- uchar Display_Digit[]={0,0,0,0};
- uchar CurrentT = 0;
- float time=0.0;
- long distance=0.0;
- int num=0,num1=0;
- //**************************************************************************************************
- //延时函数
- //**************************************************************************************************
- void delay(uint time) //int型数据为16位,所以最大值为65535
- {
- uint i,j; //定义变量i,j,用于循环语句
- for(i=0;i<time;i++) //for循环,循环50*time次
- for(j=0;j<100;j++); //for循环,循环50次
- }
- void Delay1(uint x) //延时 2
- {
- while(x--);
- }
- //**************************************************************************************************
- //向LCD写一命令
- //**************************************************************************************************
- void wcode(uchar t)
- {
- rs=0; // 写的是命令
- rw=0; // 写状态
- e=1; //使能
- P0=t; //写入命令
- delay(20); //等待写入,如果时间太短,会导致液晶无法显示
- e=0; //数据的锁定
- }
- //**************************************************************************************************
- //向LCD写一数据
- //**************************************************************************************************
- void wdata(uchar t)
- {
- rs=1; // 写的是数据
- rw=0; // 写状态
- e=1; //使能
- P0=t; //写入数据
- delay(20); //等待写入,如果时间太短,会导致液晶无法显示
- e=0; //数据的锁定
- }
- //**************************************************************************************************
- //LCD显示第一行
- //**************************************************************************************************
- void xian1(uchar *dis)
- {
- uchar i;
- wcode(0x80); //设置第一行显示地址
- for(i=0;i<16;i++) //循环16次,写完1行
- {
- wdata(dis[ i]); //写入该行数据[ i]
- }
- }
- //**************************************************************************************************
- //LCD显示第二行
- //**************************************************************************************************
- void xian2(uchar *str)
- {
- uchar i;
- wcode(0xc0); //设置第二行显示地址
- for(i=0;i<16;i++) //循环16次,写完1行
- {
- wdata(str[ i]); //写入该行数据[ i]
- }
- }
- //**************************************************************************************************
- //LCD 初始化
- //**************************************************************************************************
- void InitLCD()
- {
- wcode(0x01); //清屏
- wcode(0x06); //输入方式控制,增量光标不移位
- wcode(0x0c); //显示开关控制
- wcode(0x38); //功能设定:设置16x2显示,5x7显示,8位数据接口
- }
- /*********************************************************/
- // 液晶光标定位函数
- /*********************************************************/
- void LcdGotoXY(uchar line,uchar column)
- {
- if(line==1) // 第一行
- wcode(0x80+column-1);
- if(line==2) // 第二行
- wcode(0xC0+column-1);
- }
- /*********************************************************/
- // 液晶输出数字
- /*********************************************************/
- void LcdPrintNum(uchar num)
- {
- wdata(num/10%10+0x30);
- wdata(num%10+0x30);
- }
- void delay100us(void) //误差 0us
- {
- unsigned char a,b;
- for(b=19;b>0;b--)
- for(a=1;a>0;a--);
- }
- uchar Init_DS18B20() //初始化(或者说复位) DS18B20
- {
- uchar status;
- DQ = 1;
- Delay1(8);
- DQ = 0;
- Delay1(90);
- DQ = 1;
- Delay1(8);
- status=DQ;Delay1(100);
- DQ = 1;
- return status;
- }
- uchar ReadOneByte() //从 DS18B20 读一字节数据
- {
- uchar i,dat=0;
- DQ = 1;
- _nop_();
- for(i=0;i<8;i++)
- {
- DQ = 0;
- dat >>= 1;
- DQ = 1;
- _nop_();
- _nop_();
- if(DQ)
- dat |= 0X80;
- Delay1(30);
- DQ = 1;
- }
- return dat;
- }
- void WriteOneByte(uchar dat) //从 DS18B20 写一字节数据
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- DQ = 0;
- DQ = dat& 0x01;
- Delay1(5);
- DQ = 1;
- dat >>= 1;
- }
- }
- void Read_Temperature() //从 DS18B20 读取温度值
- {
- if(Init_DS18B20()==1) //DS18B20 故障
- DS18B20_IS_OK=0;
- else
- {
- WriteOneByte(0xcc); //跳过序列号命令
- WriteOneByte(0x44); //启动温度转换命令
- Init_DS18B20(); //复位 DS18B20 ( 每一次读写之前都要对 DS18B20 进行复位操作)
- WriteOneByte(0xcc); //跳过序列号命令
- WriteOneByte(0xbe); //读取温度寄存器
- Temp_Value[0] = ReadOneByte(); //读取温度低 8 位(先读低字节,再读高字节,)
- Temp_Value[1] = ReadOneByte();//读取温度高 8 位 (每次只能读一个字节)
- DS18B20_IS_OK=1; //DS18B20 正常
- }
- }
- void Display_Temperature() //在 1602LCD 上显示当前温度
- {
-
- uchar t = 150, ng = 0; //延时值与负数标志
- if((Temp_Value[1]&0xf8)==0xf8) //高字节高 5 位如果全为 1,则为负数,为负数时取反
- { //加 1,并设置负数标志为 1
- Temp_Value[1] = ~Temp_Value[1];
- Temp_Value[0] = ~Temp_Value[0]+1;
- if(Temp_Value[0]==0x00) //若低字节进位,则高字节加 1
- Temp_Value[1]++;
- ng = 1; //设置负数标志为 1
- }
- Display_Digit[0] = df_Table[Temp_Value[0]&0x0f]; //查表得到温度小数部分
- //获取温度整数部分(低字节低 4 位清零,高 4 位右移 4 位) +(高字节高 5 位清零,
- //低三位左移 4 位)
- CurrentT = ((Temp_Value[0]&0xf0)>>4) | ((Temp_Value[1]&0x07)<<4);
- //将温度整数部分分解为 3 位待显示数字
- Display_Digit[3] = CurrentT/100;
- Display_Digit[2] = CurrentT%100/10;
- Display_Digit[1] = CurrentT%10;
- //刷新 LCD 缓冲 //加字符 0 是为了将待数字转化为字符显示
- LcdGotoXY(2,3);
- wdata(Display_Digit[2]+'0');
- wdata(Display_Digit[1]+'0');
- wdata('.');
- wdata(Display_Digit[0]+'0');
- }
- void delay10ms(void) //误差 -0.000000000001us
- {
- unsigned char a,b,c;
- for(c=7;c>0;c--)
- for(b=168;b>0;b--)
- for(a=22;a>0;a--);
- }
- void WateringIntelligence() //智能控制模式
- {
- //--------------设置湿度上下限函数----
- {
- JD=1;
- wcode(0x0f); // 显示光标,并闪烁
- //delay10ms();
- while(Key_Set==0); // 等待按键释放
- //delay10ms();
- wcode(0x01); // 清屏
- xian1("Humidity Set "); // 显示 "Humidity Set" (第一行)
- xian2(" - %RH "); // 显示“ - %RH ” (第二行)
- LcdGotoXY(2,5);
- LcdPrintNum(HumiLowTemp);
- LcdGotoXY(2,8);
- LcdPrintNum(HumiHigTemp);
- LcdGotoXY(2,6);
- /*****湿度下限值设置******************************************
- ------------------------------------------------------------*/
- while(Key_Set!=0)
- {
- if(Key_Min==0) // 湿度下限值 减
- {
- HumiLowTemp--;
- if(HumiLowTemp<0)
- HumiLowTemp=0;
- LcdGotoXY(2,5); // 显示湿度下限值
- LcdPrintNum(HumiLowTemp);
- LcdGotoXY(2,6);
- delay(500);
- }
- if(Key_Add==0) // 湿度下限值 加
- {
- HumiLowTemp++;
- if(HumiLowTemp==100)
- HumiLowTemp=99;
- LcdGotoXY(2,5); // 显示湿度下限值
- LcdPrintNum(HumiLowTemp);
- LcdGotoXY(2,6);
- delay(500);
- }
- }
- //delay10ms();
- while(Key_Set==0); // 等待按键释放
- //delay10ms();
- LcdGotoXY(2,9);
- while(Key_Set!=0) // 如果按键1按下,那么跳到下一级设置,否则是湿度上限值的大小设置
- {
- if(Key_Min==0) // 湿度上限值 减
- {
- HumiHigTemp--;
- if(HumiHigTemp<0)
- HumiHigTemp=0;
- LcdGotoXY(2,8); // 显示湿度上限值
- LcdPrintNum(HumiHigTemp);
- LcdGotoXY(2,9);
- delay(500);
- }
- if(Key_Add==0) // 湿度上限值 加
- {
- HumiHigTemp++;
- if(HumiHigTemp==100)
- HumiHigTemp=99;
- LcdGotoXY(2,8); // 显示度上限值
- LcdPrintNum(HumiHigTemp);
- LcdGotoXY(2,9);
- delay(500);
- }
- }
- //delay10ms();
- while(Key_Set==0); // 等待按键释放
- //delay10ms();
- wcode(0x0c);
-
- ThresholdL=HumiLowTemp; // 更新湿度下限报警值
- ThresholdH=HumiHigTemp; // 更新湿度上限报警
-
- InitLCD(); //初始化1602
- xian1("Watering System "); //显示第一行
- xian2("T: C H: %RH "); //显示第二行
- LcdGotoXY(2,5);
- wdata(0xdf);
-
- }
- if(sw==0) //当前温度低于阈值下限,浇水
- {
- JD=0;
- led1=0;
- HumTab=0;
- LcdGotoXY(2,10);
- LcdPrintNum(19);
-
- }
- else //当前温度高于阈值上限,停止浇水
- {
- JD=1;
- led1=1;
- HumTab=1;
- LcdGotoXY(2,10);
- LcdPrintNum(53);
- }
- }
- //水位检测函数
- void CheckWaterLevel()
- {
- if(Key_Low==1&&Key_High==1)//高低水位都没水
- {
- led3=0; //下水位,快没水了
- led2=1;
- BEEP=0; //蜂鸣器报警
- }
- else if(Key_Low==0&&Key_High==0)//低水位有水,高水位有水,水满了
- {
- led3=1;
- led2=0;
- BEEP=0;
- }
- else
- {
- led3=1;
- led2=1;
- BEEP=1;
- }
- }
- void main()
- {
- InitLCD(); //初始化1602
- xian1("Watering System ");
- xian2("T: C H: %RH "); //显示第二行
- LcdGotoXY(2,5);
- wdata(0xdf);
- while(1) //进入死循环,防止看门狗复位
- {
- //key1deal();
- Read_Temperature();
- Display_Temperature();
- CheckWaterLevel();
- WateringIntelligence();
- delay(1000);
- }
- }
复制代码
全部资料51hei下载地址:
花卉自动浇水.rar
(76.03 KB, 下载次数: 156)
|