目錄
一、主要功能
二、硬件資源
三、程序編程
四、實現現象
一、主要功能
1.通過DHT11模塊讀取環境溫度和濕度:
2.將濕度、障礙物距顯示在lcd1602上面,第一行顯示溫度和濕度,格式為:xx°Cyy%,第二行顯示超聲波傳感器測得的距離,格式為:Distance: zzz CM:
3.判斷距離是否超過設定閾值,默認閾值為150cm,當測得距離低于150cm時,蜂鳴器長鳴,LED1(黃燈)閃爍,直至恢復安全距離以上:當濕度大于65%時,蜂鳴器間斷報警(需與剛才報警聲有明顯區別),不對LED1進行操作,如果距離和濕度兩個同時滿足報警條件時,距離報警優先。
4.LDR模塊用于檢測環境光亮度,將光敏電陽模擬信號通過ADC0832轉換為數字信號傳遞給單片機,當亮度低于50時自動打開LED2(紅色)常亮。
5.設置模塊,由三個按鍵組成,用于修改距離閾值,當點擊按鍵1時進入閾值設置模式,進入設置模式后點擊按鍵2增大閾值,點擊按鍵了減小閾值,每次變化幅度為1,lcd顯示實時顯示設置情況,Set Distance:sss CM,當設置完畢再次點擊按鍵1會退出設置模式并保存剛才設定的閩值,lcd恢復原來的顯示內容
二、硬件資源
基于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;typedef?unsigned?char?uint8;typedef?unsigned?int?uint16;typedef?unsigned?long?uint32;
sbit?CS=P1^0;??????
sbit?CLK=P1^1;
sbit?DIO=P1^2;
sbit?Tr=P3^5;//觸發信號sbit?Ec=P3^6;//回響信號sbit?Temp_data=P2^6;?? //DHT11sbit?beep?=?P1^3;
sbit?key1?=?P1^4;
sbit?key2?=?P1^5;
sbit?key3?=?P1^6;
sbit?led?=?P3^7;static?int?jlyz?=?150;
uchar?Recv_Buffer\[4\];
uint?Voltage\[\]={'0','0','0','0'};
bit?bdata?IIC\_ERROR;unsigned?int?distance;unsigned?int?Read\_value(void);//讀值函數static?double?u;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?int?wd,sd;static?int?flag1=0,flag2=0,flag?=?0;static?int?ymflag=0;static?int?flag3=0;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?Delay10us(void);//10us延時函數void?display();void?canshu();void?ajpd();void?Time0_Init()??????????//定時器初始化{TMOD?=?0x21;TH0?=?0x00;TL0?=?0x00;TR0?=?0;//先關閉定時器0}void?Time0_Int()?interrupt?1?//中斷程序{TH0??=?0xfe;?????????????//重新賦值TL0??=?0x33;
}unsigned?int?Read_value(){uint?result;Tr=1;//觸發引腳發出11us的觸發信號(至少10us)Delay10us();Tr=0; while(!Ec);//度過回響信號的低電平TR0=1;//開啟定時器0while(Ec);//度過回響信號高電平TR0=0;//關閉定時器0result=((TH0\*256+TL0)\*0.034)/2; //?距離cm=(時間us?*?速度cm/us)/2return?result?+?2; //+2修正補償 }//延時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\];wd?=?rec\_dat\[3\]*10?+?rec\_dat\[2\];
}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;
}void?beep_warning(){ if(distance?<?jlyz){flag1?=?1;} else{flag1?=?2;} if(sd?>?65){flag2?=?3;} else{flag2?=?4;}flag?=?flag1?*?flag2; if(flag?==?3?||?flag?==?4){beep?=~?beep; Delay(500);} else?if(flag?==?6){beep?=~?beep; Delay(100);} else?if(flag?==?8){beep?=?1;} if(u>=50){led?=?0;} else{led?=?1;}
}void?main() ??//主函數{ Tr=0;???????????????//出發引腳首先拉低LCD_Init();?????????//顯示屏初始化Time0_Init(); ???//定時初始化beep?=?1;led?=?0; while(1){ canshu();??//參數獲取display();??//顯示beep_warning();//報警ajpd();??//按鍵判斷}
}void?ajpd(){ if(key1==0){ Delay(100); if(key1?==?0){ LCD_Init();?????????//顯示屏初始化ymflag++; if(ymflag>1){ymflag?=?0;}}} if(key2==0){ Delay(100); if(key2?==?0){jlyz++;}} if(key3==0){ Delay(100); if(key3?==?0){jlyz--;}}
}void?canshu()?{distance?=?Read_value();//讀值distance+=12; ?dht11();?//溫濕度獲取u=get\_AD\_Res();u?=?(u/177)*50;}void?display(){ if(ymflag?==?0){ ??LCD_ShowNum(2,10,distance,3);?//顯示距離LCD\_ShowNum(1,1,wd,2); ??LCD\_ShowNum(1,7,sd,2);flag3?=?0;} else?if(ymflag?==?1){ LCD_ShowNum(2,1,jlyz,3);?//顯示距離flag3?=?1;} if(flag3?==?0){ LCD_ShowString(2,1,"Distance:");?//顯示字符串DistanceLCD_ShowString(2,14,"CM");?//顯示字符串DistanceLCD_ShowString(1,3,"C");?//顯示字符串DistanceLCD_ShowString(1,9,"%");?//顯示字符串Distanceflag3?=?2;} else?if?(flag3?==?1){ LCD_ShowString(1,1,"SetDistance");?//顯示字符串DistanceLCD_ShowString(2,4,"CM");flag3?=?2;}
}
// void?Delay10us(){TL0=0xF5;TH0=0xFF;TR0=1; while?(TF0==0);TR0=0;TF0=0;
}
四、實現現象
具體動態效果看B站演示視頻:
基于單片機的超聲波、溫濕度、光照檢測分階段報警_嗶哩嗶哩_bilibili
全部資料(源程序、仿真文件、安裝包、演示視頻):
http://?https://pan.baidu.com/s/1nZjWADtV0UnN-OcZPSpc1Q?pwd=rqn5