目錄
一、主要功能
二、硬件資源
三、程序編程
四、實現現象
一、主要功能
基于51單片機,采用DHT11濕度傳感器檢測濕度,DS18B20溫度傳感器檢測溫度,
采用滑動變阻器連接數模轉換器模擬二氧化碳和氧氣濃度檢測,各項數值通過lcd1602顯示屏顯示,
如果各項參數超過閾值,則蜂鳴器報警;若溫濕度超過閾值,則同時啟動電機轉動模擬風扇進行
降溫或者除濕。
二、硬件資源
基于KEIL5編寫C++代碼,PROTEUS8.15進行仿真,全部資源在頁尾,提供安裝包。
編輯
三、程序編程
#include <REGX52.H>#include<intrins.h>#include<stdio.h>#include "Delay.h"#include "LCD1602.h"#define uchar unsigned char#define uint unsigned inttypedef unsigned char u8;typedef unsigned int u16;static uint temp;static float ftemp = 0.0f;//溫度轉變sbit CS=P1^0; //adc0832引腳sbit CLK=P1^1;
sbit DIO=P1^2;
sbit CS1=P1^3; //adc0832引腳sbit CLK1=P1^4;
sbit DIO1=P1^5;
sbit beep=P3^4;
sbit Temp_data=P2^6; //DHT11sbit DS=P2^4; //DS18B20溫度傳感器sbit ssmotor = P3^0;
sbit csmotor = P3^1;unsigned char rec\_dat\_lcd0\[6\];unsigned char rec\_dat\_lcd1\[6\];unsigned char rec\_dat\_lcd2\[6\];unsigned char rec\_dat\_lcd3\[6\];unsigned int rec\_dat\[4\];static uchar u,U,R ,u1,U1,R1; //定義變量static uchar wd,sd;static int wdyz=37,sdyz=80,coyz=90,pmyz=120;void DHT11\_delay\_us(unsigned char n);void DHT11\_delay\_ms(unsigned int z);void DHT11\_start();unsigned char DHT11\_rec\_byte();void DHT11\_receive();void beep\_warning();void cshq();void xxpxs();void tmpchange();uint tmp();void beep_warning();void ajpd();void dsreset(void) //發出命令{uint i;DS=0; i=103; //將總線拉低480us~960uswhile(i>0)i--;DS=1; //然后拉高總線,若DS18B20做出反應會將在15us~60us后將總線拉低i=4; //15us~60us等待while(i>0)i--; //while(DS);}bit tmpreadbit(void) //讀取數據{uint i;bit dat;DS=0;i++; //i++ for delayDS=1;i++;i++;dat=DS;i=8;while(i>0)i--; return (dat);
}uchar tmpread(void) //讀取數據{uchar i,j,dat;dat=0; for(i=1;i<=8;i++){j=tmpreadbit();dat=(j<<7)|(dat>>1); //讀出的數據最低位在最前面,這樣剛好一個字節在DAT里} return(dat);
}void tmpwritebyte(uchar dat) //傳輸數據給DS18B20{uint i;uchar j;bit testb; for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1; if(testb) //write 1{DS=0;i++;i++;DS=1;i=8;while(i>0)i--;} else{DS=0; //write 0i=8;while(i>0)i--;DS=1;i++;i++;}}
}void tmpchange(void) //DS18B20開始工作{ dsreset(); Delay(1); tmpwritebyte(0xcc); tmpwritebyte(0x44);
}
uint tmp() //獲得溫度{ float tt;uchar a,b; dsreset(); Delay(1); tmpwritebyte(0xcc); tmpwritebyte(0xbe);a=tmpread();//低八位b=tmpread();//高八位temp=b;temp<<=8; //two byte compose a int variabletemp=temp|a;tt=temp*0.0625; //算出來的是測到的溫度,數值可到小數點后兩位temp=tt*10+0.5; //為了顯示溫度后的小數點后一位并作出四舍五入,因為取值運算不能取小數點后的數return temp;
}//延時msvoid DHT11\_delay\_ms(unsigned int z){ unsigned int i,j; for(i=z; i>0; i--) for(j=110; j>0; j--);
}//延時us --2*n+5usvoid DHT11\_delay\_us(unsigned char n){ while(--n);
}//DHT11起始信號void DHT11_start(){Temp\_data=1; DHT11\_delay_us(10);Temp\_data=0; DHT11\_delay_ms(50);//這個延時不能過短,18ms以上,實際在仿真當中要想讀到數據延時要在延時參數要在40以上才能出數據Temp\_data=1; DHT11\_delay\_us(30);//這個延時不能過短}//接收一個字節unsigned char DHT11\_rec_byte(){ unsigned char i,dat=0; for(i=0; i<8; i++){ while(!Temp\_data); DHT11\_delay_us(8);dat <<=1; if(Temp_data==1){dat +=1;} while(Temp_data);} return dat;
}//接收溫濕度數據void DHT11\_receive(){ unsigned int R\_H,R\_L,T\_H,T\_L; unsigned char RH,RL,TH,TL,revise; DHT11\_start();Temp\_data=1; if(Temp\_data==0){ while(Temp_data==0); //等待拉高DHT11\_delay\_us(40); //拉高后延時80usR\_H=DHT11\_rec_byte(); //接收濕度高八位R\_L=DHT11\_rec_byte(); //接收濕度低八位T\_H=DHT11\_rec_byte(); //接收溫度高八位T\_L=DHT11\_rec_byte(); //接收溫度低八位revise=DHT11\_rec\_byte(); //接收校正位DHT11\_delay\_us(25); //結束if((R\_H+R\_L+T\_H+T\_L)==revise) //校正{RH=R_H;RL=R_L;TH=T_H;TL=T_L;} /*數據處理,方便顯示*/rec_dat\[0\]=RH;rec_dat\[1\]=RL;rec_dat\[2\]=TH;rec_dat\[3\]=TL;}}void dht11(){ DHT11\_delay\_ms(150); DHT11\_receive(); sprintf(rec\_dat\_lcd0,"%d",rec\_dat\[0\]); sprintf(rec\_dat\_lcd1,"%d",rec\_dat\[1\]); sprintf(rec\_dat\_lcd2,"%d",rec\_dat\[2\]); sprintf(rec\_dat\_lcd3,"%d",rec\_dat\[3\]); DHT11\_delay_ms(100); sd = rec\_dat\[1\]*10 + rec\_dat\[0\];}uchar get\_AD\_Res() //ADC0832啟動讀取函數{uchar i, data1=0, data2=0;CS=0;CLK=0;DIO=1;\_nop\_();CLK=1;\_nop\_();CLK=0;DIO=1;\_nop\_(); CLK=1;\_nop\_();CLK=0;DIO=0;\_nop\_();CLK=1;\_nop\_();CLK=0;DIO=1;\_nop\_(); for(i=0; i<8; i++){CLK=1;\_nop\_();CLK=0;\_nop\_();data1=(data1<<1)|(uchar)DIO; } for(i=0; i<8; i++){data2=data2|(uchar)DIO<<i;CLK=1;\_nop\_();CLK=0;\_nop\_();}CS=1; return(data1 == data2)?data1:0;
}uchar get\_AD\_Res1() //ADC0832啟動讀取函數{uchar i, data1=0, data2=0;CS1=0;CLK1=0;DIO1=1;\_nop\_();CLK1=1;\_nop\_();CLK1=0;DIO1=1;\_nop\_(); CLK1=1;\_nop\_();CLK1=0;DIO1=0;\_nop\_();CLK1=1;\_nop\_();CLK1=0;DIO1=1;\_nop\_(); for(i=0; i<8; i++){CLK1=1;\_nop\_();CLK1=0;\_nop\_();data1=(data1<<1)|(uchar)DIO1; } for(i=0; i<8; i++){data2=data2|(uchar)DIO1<<i;CLK1=1;\_nop\_();CLK1=0;\_nop\_();}CS1=1; return(data1 == data2)?data1:0;
}void beep_warning()//蜂鳴器警報并且電機轉動{ if(ftemp>wdyz){beep = 1;ssmotor = 0;} else{ssmotor = 1;} if(sd>sdyz){beep = 1;csmotor = 0;} else{csmotor = 1;} if(R>coyz) //氧氣{beep = 1;} if(R1>pmyz)//二氧化碳{beep = 1;} if(ftemp<=wdyz && sd<=sdyz && R<=coyz && R1<=pmyz ) {beep = 0;}
}void main() //主函數{ LCD_Init(); //顯示屏初始化ssmotor = 1;csmotor = 1;beep = 0; do{ tmpchange(); //讓18b20開始轉換溫度temp = tmp(); //讀取溫度ftemp = temp/10.0f; //轉換溫度cshq(); //參數獲取dht11(); //溫濕度獲取xxpxs(); //顯示屏顯示beep_warning(); //狀態判斷} while(1);
}void xxpxs() //顯示屏顯示{// LCD\_ShowString(1,1,"O2:"); // LCD\_ShowNum(1,4,R,3); //COLCD_ShowString(1,9,"CO2:"); LCD_ShowNum(1,13,R1,3);//PM2.5//濕度LCD_ShowString(2,1,"wd:"); LCD_ShowNum(2,4,ftemp,3); //溫度LCD_ShowString(2,9,"sd:"); LCD_ShowNum(2,12,sd,3);}void cshq() //參數獲取{u=get\_AD\_Res();U=(250*u)/128; //此處將數字信號轉化為模擬信號,要根據上拉電阻阻值來確定R=200*U/250; //O2u1=get\_AD\_Res1();U1=(250*u1)/128; //此處將數字信號轉化為模擬信號,要根據上拉電阻阻值來確定R1=200*U1/250; //CO2}
四、實現現象
具體動態效果看B站演示視頻:
基于單片機的書庫環境監測_嗶哩嗶哩_bilibili
全部資料(源程序、仿真文件、安裝包、原理圖、演示視頻):