一.簡介
DHT11作爲一款低價、入門級的溫溼度傳感器,常用於我們的單片機設計實例中;它應用專用的數字模塊採集技術和溫溼度傳感技術,確保產品具有極高的可靠性與卓越的長期穩定性。傳感器包括一個電阻式感溼元件和一個NTC測溫元件,並與一個高性能8位單片機相連接。
DHT11爲 4 針單排引腳封裝,如下圖,採用單線制串行接口,只需加適當的上拉電阻,信號傳輸距離可達20米以上,使其成爲各類應用甚至最爲苛刻的應用場合的最佳選擇。
二.傳感器參數
1.DHT11電氣參數如下:
2.引腳定義
3.典型電路
DHT11的供電電壓爲 3-5.5V,電源引腳(VDD,GND)之間可增加一個100nF 的電容,用以去耦濾波。DATA引腳並聯一個5K以上的上拉電阻,增強信號的抗干擾額能力。傳感器上電後,要等待 1s 以越過不穩定狀態在此期間無需發送任何指令。
三.傳感器控制時序
1.數據格式
DATA 用於微處理器與 DHT11之間的通訊和同步,採用單總線數據格式,一次通訊時間4ms左右,數據分小數部分和整數部分,具體格式在下面說明,當前小數部分用於以後擴展,現讀出爲零,操作流程如下:
一次完整的數據傳輸爲40bit,高位先出。
數據格式:
8bit溼度整數數據+8bit溼度小數數據+8bi溫度整數數據+8bit溫度小數數據+8bit校驗和
8位校驗和:
"8bit溼度整數數據+8bit溼度小數數據+8bi溫度整數數據+8bit溫度小數數據"相加所得結果的末8位。
2.控制時序
要實現對DHT11傳感器的控制和數據的讀取,需先學會分析DHT11的控制時序。時序主要分爲三部分:
-
觸發DHT11採集數據;
-
讀取數字0;
-
讀取數字1;
(1)觸發DHT11採集數據
總線空閒狀態爲高電平,單片機把總線拉低等待DHT11響應,單片機把總線拉低必須大於18ms,保證DHT11能檢測到起始信號。
當DHT11接收到單片機的開始信號後,等待單片機開始信號結束,然後發送80us低電平響應信號。
單片機發送開始信號結束後,延時等待20-40us後,切換爲輸入狀態,等待DHT11的80us低電平信號結束,然後判斷DHT11是否是否發出 80us 的高電平;如果是,即可開始採集數據。
(2)數字0信號時序
當DHT11輸出數字0時, 單片機讀取到的信號爲50 us的低電平,之後爲26-28 us的高電平。
(3)數字1信號時序
當DHT11輸出數字0時, 單片機讀取到的信號爲50 us的低電平,之後爲70 us的高電平。
由此可知DHT11輸出數字0和數字1的區別在於高電平的時間,由此單片機可在讀取到高電平後,延時30us後,識別此時總線的電平,高電平爲數字1,低電平爲數字0;
(4)總時序圖
用戶MCU發送一次開始信號後,DHT11從低功耗模式轉換到高速模式,等待主機開始信號結束後,DHT11發送響應信號,送出40bit的數據,並觸發一次信號採集,用戶可選擇讀取部分數據。
從模式下,DHT11接收到開始信號觸發一次溫溼度採集,如果沒有接收到主機發送開始信號,DHT11不會主動進行溫溼度採集。當一次完整的採集數據後,DHT11會轉換到低速模式。
四.控制程序
1.單字節採集
void COM(void)
{
U8 i;
for(i=0;i<8;i++)
{
U8FLAG=2;
while((!P2_0)&&U8FLAG++);
Delay_10us();
Delay_10us();
Delay_10us();
U8temp=0;
if(P2_0)U8temp=1;
U8FLAG=2;
while((P2_0)&&U8FLAG++);
//超時則跳出for循環
if(U8FLAG==1)break;
//判斷數據位是0還是1
// 如果高電平高過預定0高電平值則數據位爲 1
U8comdata<<=1;
U8comdata|=U8temp; //0
}
}
2.完整一次數據採集
void RH(void)
{
//主機拉低18ms
P2_0=0;
Delay(180);
P2_0=1;
//總線由上拉電阻拉高 主機延時20us
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
//主機設爲輸入 判斷從機響應信號
P2_0=1;
//判斷從機是否有低電平響應信號 如不響應則跳出,響應則向下運行
if(!P2_0) //T !
{
U8FLAG=2;
//判斷從機是否發出 80us 的低電平響應信號是否結束
while((!P2_0)&&U8FLAG++);
U8FLAG=2;
//判斷從機是否發出 80us 的高電平,如發出則進入數據接收狀態
while((P2_0)&&U8FLAG++);
//數據接收狀態
COM();
U8RH_data_H_temp=U8comdata;
COM();
U8RH_data_L_temp=U8comdata;
COM();
U8T_data_H_temp=U8comdata;
COM();
U8T_data_L_temp=U8comdata;
COM();
U8checkdata_temp=U8comdata;
P2_0=1;
//數據校驗
U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);
if(U8temp==U8checkdata_temp)
{
U8RH_data_H=U8RH_data_H_temp;
U8RH_data_L=U8RH_data_L_temp;
U8T_data_H=U8T_data_H_temp;
U8T_data_L=U8T_data_L_temp;
U8checkdata=U8checkdata_temp;
}
}/
}
3.獲取DHT11數據
void GetTemp(void)
{
//------------------------
//調用溫溼度讀取子程序
RH();
//串口顯示程序
//--------------------------
Send_string("Humidity:");
str[0]=U8RH_data_H/10+0x30;
str[1]=U8RH_data_H%10+0x30;
str[2]='.';
str[3]=U8RH_data_L/10+0x30;
str[4]=U8RH_data_L%10+0x30;
str[5]='\0';
Send_string(str);
Send_string("%\r\n");
Send_string("Temperature:");
str[0]=U8T_data_H/10+0x30;
str[1]=U8T_data_H%10+0x30;
str[2]='.';
str[3]=U8T_data_L/10+0x30;
str[4]=U8T_data_L%10+0x30;
str[5]='\0';
Send_string(str);
Send_string("℃\r\n");
}