一.傳感器介紹
1.基本介紹
DHT11數字溫濕度傳感器是一款含有已校准數字信號輸出的溫濕度符合傳感器,它應用專用的數字模塊采集技術和溫濕度傳感技術,確保產品具有極高的可靠性和卓越的長期穩定性。
應用平台:
2.管腳說明
管腳 | 作用 |
Vcc | 模塊供電正極(供電電壓范圍:3-5.5V) |
gnd | 模塊數據傳輸管腳 |
GND | 模塊供電負極 |
3.data數據接口串行數據傳輸
一次完整的數據傳輸需要40bit數據,高位先出
傳輸具體過程如下:8bit濕度整數數據+8bit濕度小數數據 +8bi溫度整數數據+8bit溫度小數數據 +8bit校驗和
用戶MCU發送一次開始信號后,DHT11從低功耗模式轉換到高速模式,等待主 機開始信號結束后,DHT11發送響應信號,送出40bit的數據,並觸發一次信號采集, 用戶可選擇讀取部分數據.
二.數據傳輸時序圖、
1.模塊存在檢測時序圖
流程如下
單片機方面:單片機首先會給模塊高電平,然后會將電平拉低,同時延時至少18ms,接着將電平拉高,同時延遲最多40us,可設定30us。
模塊方面:模塊會將管腳的電平拉低,並延遲80us,如果單片機檢測在80us時間內,管腳一直屬於低電平,那么就可以判斷模塊存在。
可以寫出如下代碼:判斷模塊是否存在
sbit LED = P2^0; sbit DATA = P1^0; void Delay25ms() //@11.0592MHz { unsigned char i, j; i = 45; j = 208; do { while (--j); } while (--i); } void Delay70us() //@11.0592MHz { unsigned char i; _nop_(); i = 29; while (--i); void check_DHT11() { DATA = 1; //將電平拉高 DATA = 0; //將電平拉低 Delay25ms(); //低電平延遲25ms(至少18ms) DATA = 1; //延時過后將電平拉高 Delay70us(); //延遲大約70us,用來判斷是否處於低電平 if(DATA ==0) { LED = 0; //如果一直處於低電平,則模塊存在,指示燈點亮 } }
2.數據讀取時序圖
(1)數據0時序圖
(2)數據1時序圖
編程思路:由數據組成可以知道,該組數據由5組構成,每組有8位,因此我們可以建立兩個變量,一個是輪數,讀取5輪,一個是每輪讀取的位數,讀取8位。通過時序圖可以得知,當data數據變成高電平時,開始進行數據讀取,這時可以進行延時大約50us來判斷讀取的數據,(因為0信號高電平最多28us,而1信號最多70us,因此延遲50us來進行判斷),如果經過50us依舊是高電平,則讀取數據就是1,由於70us不好把握,因此需要進行“卡電平”,卡出電平降低的點,否則就是0,可以新建一個變量,將讀取到的數據進行臨時存放,為了保存一組完整的數據,需要新建一個char型變量,用於存儲一組變量,這時可以將這個char型變量進行左移,然后將讀取過來的“0”、“1”數據和char的地位進行按位與運算,直到將整個char型變量替換完畢,將替換完成的變量存儲在數組中,直到整個數組全被存儲,這時數據讀取完畢。
sbit DATA = P1^0; char save_data[5]; //畫出數據存儲區域 void Delay50us() { unsigned char i; _nop_(); i = 20; while (--i); } int i; //定義讀取的輪數 int j; //定義讀取的位數 int tep; //定義一組的臨時存儲區(8位) int flag; //定義讀取的0、1數據 for(i = 0;i < 5;i ++) { for(j = 0;j < 8;j++) { while(!DATA); //如果data數據管腳編程高電平,則開始數據傳輸 Delay50us(); //延遲50us,然后判斷data的電平狀態 if(DATA == 1) { flag = 1; while(DATA); } else { flag = 0; } tep = tep<<1; tep |= flag; } save_data[i] = tep; }
三.全代碼實現
#include <REGX52.H> #include <intrins.h> sbit LED = P2^0; sbit DATA = P1^0; char save_data[5]; //畫出數據存儲區域 void Delay25ms() //@11.0592MHz { unsigned char i, j; i = 45; j = 208; do { while (--j); } while (--i); } void Delay70us() //@11.0592MHz { unsigned char i; _nop_(); i = 29; while (--i); } void Delay50us() //@11.0592MHz { unsigned char i; _nop_(); i = 20; while (--i); } /*串口初始化*/ void UartInit(void) //9600bps@11.0592MHz { SCON = 0x40; //8位數據,可變波特率 TMOD &= 0x0F; //清除定時器1模式位 TMOD |= 0x20; //設定定時器1為8位自動重裝方式 TL1 = 0xFD; //設定定時初值 TH1 = 0xFD; //設定定時器重裝值 ET1 = 0; //禁止定時器1中斷 TR1 = 1; //啟動定時器1 } void send_byte(char msg_data) { SBUF = msg_data; //將形式參數msg_data傳送到SBUF中 } /*判斷溫度檢測模塊是否存在*/ void check_DHT11() { DATA = 1; DATA = 0; Delay25ms(); DATA = 1; Delay70us(); if(DATA ==0) { LED = 0; } } /*讀取溫度檢測模塊發送的數據*/ void send_DHT_data() { int i;//輪數 int k;//每輪的位數 char flag; char tmp; check_DHT11(); for(i=0;i<5;i++) { for(k=0;k<8;k++) { while(!DATA);//等待模塊在低電平結尾處 Delay50us();//延遲50微秒之后,讀取DATA數據,如果依舊是高電平代表1,否則就是低電平,表示0 if(DATA == 1) { flag = 1; while(DATA); //如果是高電平信號,那么就需要卡電平,因為高電平信號會持續將近70微秒 } else { flag = 0; } /*通過將DATA的每一位數據把tmp的從低位一直替換到高位,直到替換完畢。*/ tmp = tmp << 1; tmp |= flag; } save_data[i] = tmp; } }