大棚溫濕度,檢測與控制LCD1602顯示溫度與濕度,溫度大于設定值時開風扇,小于時開電輔熱,使得氣溫保持一定限制,同時利用AD采集濕度,然后進行澆水。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.gif (193.25 KB, 下載次數: 88)
下載附件
2021-11-18 05:30 上傳
單片機源程序如下:
- /*=============================================================*/
- #include <reg52.H> //器件配置文件
- #include <intrins.h>
- #include "lcd.h"
- #define u8 unsigned char
- #define u16 unsigned int
- #define uchar unsigned char
- #define uint unsigned int
- //一般選用500K
- sbit DQ=P2^7; //ds18b20 與單片機連接口
- //將短接片去掉開啟位選功能,否則默認IN0為輸入引腳
- sbit motor=P1^0;//當濕度過低時。給高電平
- sbit ledgreen=P1^1;//當溫度過高時,打開風扇
- sbit ledred=P1^2; //溫度低時,打開輔熱
- unsigned char AD_DATA[2]; //保存IN0通道轉換后的數據
- unsigned char disbuff[7] = { 0,0,0,0,};
- unsigned char Disp[]="0123456789"; //使用字符串保存數字0~9所對應的ASCLL碼
- //unsigned char I_Disp[]="value: "; //初始顯示值
- unsigned char i,tflag;
- unsigned int a,voltage,circuit,electirc,aa,bb,cc,ab;
- unsigned char dd,ee,ff,gg;
- unsigned int tvalue,time,Level,High,t,ppm; // 溫度值
- uint dat=0,shidu;
- void delay_18b20(unsigned int i) // 延時 1 微秒
- {
- while(i--);
- }
- void ds18b20rst() //ds18b20 初始化子函數
- {
- unsigned charx=0;
- DQ = 1; // 信號線 DQ復位
- delay_18b20(4); // 延時
- DQ = 0; //DQ 拉低
- delay_18b20(100); // 精確延時大于 480us
- DQ = 1; // 拉高
- delay_18b20(40);
- }
- void ds18b20wr(unsigned char wdata) /* 寫數據子函數 , 無返回值,含參數 */
- {
- unsigned char i=0;
- for (i=8; i>0; i--)// 要寫完一個字節,故需要重復 8 次以下操作
- {
- DQ = 0; // 數據線拉低
- DQ = wdata&0x01;// 按從低到高的順序發送數據(一次發送一位 )
- delay_18b20(10);
- DQ = 1; // 最后將數據線拉高
- wdata>>=1; // 將 wdata 右移 1 位
- }
- }
- unsigned char ds18b20rd() // 讀數據子函數 , 是有返回值 dat
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--)// 要讀完一個字節,故需要重復 8 次以下操作
- {
- DQ = 0; // 給脈沖信號
- dat>>=1;
- DQ = 1; // 給脈沖信號
- if(DQ)
- dat|=0x80;
- delay_18b20(10);
- }
- return(dat); // 返回 dat
- }
- read_temp() // 讀取溫度值并轉換的子函數,有返回值溫度值 tvalue
- {
- unsigned char a,b;
- ds18b20rst(); // 調用 ds18b20 初始化子函數
- ds18b20wr(0xcc);// 調用寫數據子函數,向 ds18b20 寫命令 0xcc
- //ccH 表示跳過 ROM讀序列號,適用于單機工作,直接向 18b20 發送溫度變換命令
- ds18b20wr(0x44);// 調用寫數據子函數,向 ds18b20 寫命令 0x44
- //44H 表示啟動 ds18b20 溫度轉換 , 結果自行存入 9 字節的 RAM中
- ds18b20rst(); // 調用 ds18b20 初始化子函數
- ds18b20wr(0xcc);// 同上
- ds18b20wr(0xbe);// 調用寫數據子函數,向 ds18b20 寫命令 0xbe
- //beH 表示讀取 RAM中 9 字節的溫度數據
- a=ds18b20rd(); // 調用讀數據子函數,并將所得數據給 a
- b=ds18b20rd(); //
- tvalue=b; // 把 b 的值給 tvalue
- tvalue<<=8; //tvalue 左移 8 位
- tvalue=tvalue|a;//tvalue 與 a 進行按位或
- if(tvalue<0x0fff)//
- tflag=0; // 前五位為 0 時,讀取的溫度為正,標志位為 0,此時只要
- else // 前五位為 1 時,讀取的溫度為負,標志位為 1,此時需要
- { // 將測得數值取反后再加 1,再乘以 0.0625 即可得到實際溫度
- tvalue=~tvalue+1;
- tflag=1; // 此時表示負溫度
- }
- tvalue=tvalue*(0.625);// 溫度值擴大 10 倍,精確到 1 位小數
- return(tvalue); // 返回溫度值
- }
- /***********************************
- 函數名: AD()
- 功能: 啟動AD轉換將值儲存于 AD_DATA[0]
- ***********************************/
- sbit ADCS =P3^5;
- sbit ADCLK =P3^2;
- sbit ADDI =P3^3;
- sbit ADDO =P3^4;
- unsigned int Adc0832(unsigned char channel)
- {
- uchar i=0;
- uchar j;
- uchar ndat=0;
- uchar Vot=0;
- if(channel==0)channel=2;
- if(channel==1)channel=3;
- ADDI=1;
- _nop_();
- _nop_();
- ADCS=0;//拉低CS端
- _nop_();
- _nop_();
- ADCLK=1;//拉高CLK端
- _nop_();
- _nop_();
- ADCLK=0;//拉低CLK端,形成下降沿1
- _nop_();
- _nop_();
- ADCLK=1;//拉高CLK端
- ADDI=channel&0x1;
- _nop_();
- _nop_();
- ADCLK=0;//拉低CLK端,形成下降沿2
- _nop_();
- _nop_();
- ADCLK=1;//拉高CLK端
- ADDI=(channel>>1)&0x1;
- _nop_();
- _nop_();
- ADCLK=0;//拉低CLK端,形成下降沿3
- ADDI=1;//控制命令結束
- _nop_();
- _nop_();
- dat=0;
- for(i=0;i<8;i++)
- {
- dat|=ADDO;//收數據
- ADCLK=1;
- _nop_();
- _nop_();
- ADCLK=0;//形成一次時鐘脈沖
- _nop_();
- _nop_();
- dat<<=1;
- if(i==7)dat|=ADDO;
- }
- for(i=0;i<8;i++)
- {
- j=0;
- j=j|ADDO;//收數據
- ADCLK=1;
- _nop_();
- _nop_();
- ADCLK=0;//形成一次時鐘脈沖
- _nop_();
- _nop_();
- j=j<<7;
- ndat=ndat|j;
- if(i<7)ndat>>=1;
- }
- ADCS=1;//拉低CS端
- ADCLK=0;//拉低CLK端
- ADDO=1;//拉高數據端,回到初始狀態
- dat<<=8;
- dat|=ndat;
- return(dat); //return ad data
- }
- void Conut(void)
- {
- circuit=dat/256;
-
- ppm=circuit;
- aa=ppm/1000;
- bb=ppm%1000/100;
- cc=ppm%100/10;
- ab=ppm%10;
-
- dd=tvalue/1000; // 百位數
- ee=tvalue%1000/100;// 十位數
- ff=tvalue%100/10 ;// 個位數
- gg=tvalue%10; // 小數位
- if(ppm>150) //濕度大于150/256=58.59后電機停轉
- {motor=0;}
- if(ppm<=80) //小于31.25%電機開始啟動
- {motor=1; }
- if(tvalue>400) //溫度大于40度風扇開始啟動
- {ledgreen=1;ledred=0;}
- if(tvalue<=400) //溫度小于40度風扇關閉
- {ledgreen=0;ledred=1;}
- }
- /***********************************
- 函數名: delayms()
- 功能: 延時 ms 毫秒
- ***********************************/
- void delayms(unsigned int ms)
- {
- unsigned char j;
- i=100;
- for(;ms;ms--)
- {
- while(--i)
- {
- j=10;
- while(--j);
- }
- }
- }
- /***********************************
- 函數名: LcdDisplay()
- 功能: 用lcd顯示數組disbuff[]中的值
- ***********************************/
- void LcdDisplay(void)
- {
- LCD1602_write_com(0x80+1+0x40);
- LCD1602_write_word("c=");
- LCD1602_write_com(0x80+3+0x40);
- LCD1602_write_data(0x30+aa);
- LCD1602_write_com(0x80+4+0x40);
- LCD1602_write_data(0x30+bb);
- LCD1602_write_com(0x80+5+0x40);
- LCD1602_write_data(0x30+cc);
- LCD1602_write_com(0x80+6+0x40);
- LCD1602_write_data(0x30+ab);
- LCD1602_write_com(0x80+7+0x40);
- LCD1602_write_word("humid");
-
- LCD1602_write_com(0x80+1);
- LCD1602_write_word("tem=");
- LCD1602_write_com(0x80+5);
- LCD1602_write_data(0x30+dd);
- LCD1602_write_com(0x80+8);
- LCD1602_write_word(".");
- LCD1602_write_com(0x80+6);
- LCD1602_write_data(0x30+ee);
- LCD1602_write_com(0x80+7);
- LCD1602_write_data(0x30+ff);
- LCD1602_write_com(0x80+9);
- LCD1602_write_data(0x30+gg);
-
-
- }
- /***********************************
- 函數名: Analog_IO_Sel()
- 參數說明: m 的值對應ADC0809芯片上模擬輸入的IO
- 功能: 確定模擬輸入位選
- ***********************************/
- //void init()
- //{if(a==0)
- //{
- // EA=1; //開總中斷
- // TMOD=0x02; //設定定時器 T0工作方式
- // TH0=21; //利用T0中斷產生CLK信號
- // TL0=21;
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
51hei圖片20211117203933.png (128.03 KB, 下載次數: 81)
下載附件
2021-11-17 20:38 上傳
所有資料51hei附件下載:
大棚溫濕度控制.rar
(198.02 KB, 下載次數: 327)
2021-11-17 20:40 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|