DHT11温湿度传感器初识
目錄
一、產品概述
1、接線方式
2、特點
3、數據傳送邏輯
二、發送時序檢測模塊是否存在
1、C51單片機(主機)時序分析
2、編寫代碼檢測模塊是否存在
3、讀取DHT11數據的時序分析
三、溫濕度通過串口傳到PC顯示
四、溫濕度檢測小系統——使數據顯示在LCD1602液晶板上
一、產品概述
DHT11溫濕度傳感器是一款含有已校準數字信號輸出的溫濕度復合傳感器,應用領域:暖通空調、汽車、消費品、氣象站、溫度調節器、除濕器、家電、醫療、自動控制等
1、接線方式
VCC:接供電的正極
GND:接地
DAT:接數據
2、特點
相對濕度和溫度的測量
全部校準、數字輸出
長期穩定性
超長的信號傳輸距離:20米
4引腳安裝:可以買封裝好的
完全互換:直接出結果,不用轉化
3、數據傳送邏輯
只有一根數據線DATA,上官一號發送序列指令給DHT11模塊,模塊一次完整的數據傳輸為40bit高位先出
40bit的數據格式
8bit濕度整數數據+8bit濕度小數數據+8bit溫度整數數據+8bit溫度小數數據+8bit校驗合
二、發送時序檢測模塊是否存在
時序邏輯分析
對于主機來說:發送時序的開始在a點,結束在d點
1、C51單片機(主機)時序分析
a:dht=1;
b:dht=0;
b、c之間延時30ms;
c:dht=1;
開始讀DHT模塊有無信號,在40-100μs之間讀,比如在60μs的時候讀,如果在60μs的時候是低電平,說明模塊存在
那怎么看模塊是否有回應呢,請看上圖中的de段,C51單片機發送完時序信號是處于高電平的狀態,當DHT這邊有信號過來時,會把信號從高電平狀態拉到低電平狀態,所以當de=0時,說明DHT模塊有數據顯示了
那對于單片機來說怎么獲取到這個低電平狀態呢,那就得去讀取de段的數據了,讀上面的引腳是否為低電平
從c點到e點共有兩種情況:
第一種:cd之間的延時最短時間是20μs,de之間的延時時間是80μs,那么從c點到e點,所需要的延時時間就是20-100μs
第二種:cd之間的延時最長時間是40μs,de之間的延時時間是80μs,那么從c點到e點,所需要的延時時間就是40-120μs
綜上述情況, 我們要讀取它們重合的時間,才能把以上兩點都包括在內,重合的時間是40-100μs
2、編寫代碼檢測模塊是否存在
#include "reg52.h" #include "intrins.h"sbit dht = P3^3; sbit ledOne = P3^7;void Delay1000ms() //@11.0592MHz {unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i); }void Delay30ms() //@11.0592MHz {unsigned char i, j;i = 54;j = 199;do{while (--j);} while (--i); }void Delay60us() //@11.0592MHz {unsigned char i;i = 25;while (--i); }void check_DHT(){//a:dht=1;dht = 1;//b:dht=0;dht = 0;//b、c之間延時30ms;Delay30ms();//c:dht=1;dht = 1;//開始讀DHT模塊有無信號,在40-100μs之間讀,比如在60μs的時候讀,如果在60μs的時候是低電平,說明模塊存在Delay60us();if(dht == 0){ledOne = 0; //亮燈,說明DHT模塊存在} }void main() {ledOne = 1; //滅燈Delay1000ms(); //上電后穩定DHT11的供電Delay1000ms();check_DHT(); //看模塊是否存在while(1); //一直循環,不讓main退出 }執行結果:
當單片機接溫濕度傳感器的時候,單片機的P3^7小燈就會亮,單片機不接溫濕度傳感器的時候,小燈就不亮
3、讀取DHT11數據的時序分析
a:dht=1;
b:dht=0;
b、c之間延時30ms;
c:dht=1;
由于c點到d點之間有個20-40μs的延時時間,所以不太好找d點的位置,那么怎么找d點的位置呢
采用卡點的方法:
卡d點:while(dht);這時dht=1,當dht=1時,說明一直是高電平信號,當dht不等于1時,條件不滿足時,說明信號從高電平下降到低電平了,也就是說找到d點了
卡e點:while(!dht); 這時dht=0,一直處于低電平狀態,當dht不等于0時,條件不滿足,說明信號從低電平上升到高電平了,也就是找到e點了
卡f點:while(dht);這時dht=1,當dht=1時,說明一直是高電平信號,當dht不等于1時,條件不滿足時,說明信號從高電平下降到低電平了,也就是說找到f點了
卡g點:while(!dht); 這時dht=0,一直處于低電平狀態,當dht不等于0時,條件不滿足,說明信號從低電平上升到高電平了,也就是找到g點了
DHT11傳輸的有效數據都是高電平,只是持續的時間不一樣
表示0時,高電平持續的時間是26-28μs
表示1時,高電平持續的時間是70μs
怎么讀取DHT11傳送的數據
從g點以后延時一段時間去讀數據,比如延時50μs后,如果讀到的信號是低電平,說明是數據是0,讀到是信號是高電平,說明數據是1,然后讀40bit,也是就是讀40次,40次分5輪來讀,每輪讀8次(8bit=1個char)8次形成一個數據
數字0信號表示方法
?數字1信號表示方法
三、溫濕度通過串口傳到PC顯示
1、環境準備:C51單片機連接DHT11溫濕度傳感器;VCC-5V、GND-GND、DAT-接/發數據引腳
2、編寫代碼
#include "reg52.h" #include "intrins.h"sbit dht = P3^3; sbit ledOne = P3^7; sfr AUXR = 0x8E; char datas[5];void UartInit(void) //9600bps@11.0592MHz {AUXR = 0x01; //降低時鐘對外界的輻射SCON = 0x40; //串行口寄存器工作模式選擇方式1,RNE=0,為串行禁止接收狀態TMOD &= 0x0F; //定時器1工作方式位8位自動重裝TMOD |= 0x20;TH1 = 0xFD; TL1 = 0xFD; //9600波特率的初值TR1 = 1; //啟動定時器}void sendByte(char data_msg){ //發送字節SBUF = data_msg;while(!TI); //智能延時,靠硬件延時TI = 0; }void sendString(char* str){ //發送字符串while(*str != '\0'){sendByte(*str);str++;} }void Delay1000ms() //@11.0592MHz {unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i); }void Delay30ms() //@11.0592MHz {unsigned char i, j;i = 54;j = 199;do{while (--j);} while (--i); }void DHT11_Start(){dht = 1;dht = 0;Delay30ms();dht = 1;while(dht); //卡d點while(!dht); //卡e點while(dht); //卡f點}void Delay40us() //@11.0592MHz {unsigned char i;_nop_();i = 15;while (--i); }void Read_Data_From_DHT(){int i;int j;char tmp; //用來進行移位,用來獲得最低位char flag; //標志位DHT11_Start();for(i=0;i<5;i++){for(j=0;j<8;j++){while(!dht); //卡g點Delay40us(); //延時40usif(dht == 1){flag = 1;while(dht);}else{ flag = 0;}tmp = tmp << 1;tmp |= flag;}datas[i] = tmp;} }void main() {ledOne = 1; //滅燈UartInit(); //初始化一個串口Delay1000ms(); //上電后穩定DHT11的供電Delay1000ms();while(1){Delay1000ms();Read_Data_From_DHT(); //獲取DHT數據sendString("H:"); //發送字符串sendByte(datas[0]/10 + 0x30); //發送第1個bit字節,獲取濕度的整數位sendByte(datas[0]%10 + 0x30);sendByte('.');sendByte(datas[1]/10 + 0x30); //發送第2個bit字節,獲取濕度的小數位sendByte(datas[1]%10 + 0x30);sendString("\r\n"); //自動換行sendString("T:");sendByte(datas[2]/10 + 0x30); //發送第3個bit字節,獲取溫度的整數位sendByte(datas[2]%10 + 0x30);sendByte('.');sendByte(datas[3]/10 + 0x30); //發送第4個bit字節,獲取溫度的小數位sendByte(datas[3]%10 + 0x30);sendString("\r\n"); //自動換行} }3、執行結果:
四、溫濕度檢測小系統——使數據顯示在LCD1602液晶板上
1、環境準備:C51單片機連接DHT11溫濕度傳感器和LCD1602液晶板
下面的鏈接里有C51單片機和LCD1602液晶板的連接方式
初識LCD1602及編程實現字符顯示_Love小羽的博客-CSDN博客
2、編寫代碼
#include "reg52.h" #include "intrins.h" #define databuffer P0 //定義8位數據線,P0端口組sbit dht = P3^3; sbit ledOne = P3^7; sfr AUXR = 0x8E; sbit RS = P1^0; sbit RW = P1^1; sbit EN = P1^4; sbit fengshan = P1^6; //繼電器引腳char datas[5]; char temp[8]; //定義一個溫度類型 char huma[8]; //定義一個濕度類型void check_busy(){char tmp = 0x80;databuffer = 0x80;while(tmp & 0x80){RS = 0;RW = 1;EN = 0;_nop_();EN = 1;_nop_();_nop_();tmp = databuffer; //讀取數據_nop_();EN = 0;_nop_();} }void Write_Cmd_Func(char cmd){check_busy();RS = 0; //指令寄存器,接收地址RW = 0;EN = 0;_nop_();databuffer = cmd; //發送指令_nop_();EN = 1;_nop_();_nop_();EN = 0;_nop_(); }void Write_Data_Func(char dataShow){check_busy();RS = 1; //數據寄存器,接收內容RW = 0;EN = 0;_nop_();databuffer = dataShow; //發送數據_nop_();EN = 1;_nop_();_nop_();EN = 0;_nop_(); }void Delay15ms() //@11.0592MHz {unsigned char i, j;i = 27;j = 226;do{while (--j);} while (--i); }void Delay5ms() //@11.0592MHz {unsigned char i, j;i = 9;j = 244;do{while (--j);} while (--i); }void UartInit(void) //9600bps@11.0592MHz {AUXR = 0x01; //降低時鐘對外界的輻射SCON = 0x40; //串行口寄存器工作模式選擇方式1,RNE=0,為串行禁止接收狀態TMOD &= 0x0F; //定時器1工作方式位8位自動重裝TMOD |= 0x20;TH1 = 0xFD; TL1 = 0xFD; //9600波特率的初值TR1 = 1; //啟動定時器}void sendByte(char data_msg){ //發送字節SBUF = data_msg;while(!TI); //智能延時,靠硬件延時TI = 0; }void sendString(char* str){ //發送字符串while(*str != '\0'){sendByte(*str);str++;} }void Delay1000ms() //@11.0592MHz {unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i); }void Delay30ms() //@11.0592MHz {unsigned char i, j;i = 54;j = 199;do{while (--j);} while (--i); }void DHT11_Start(){dht = 1;dht = 0;Delay30ms();dht = 1;while(dht); //卡d點while(!dht); //卡e點while(dht); //卡f點}void Delay40us() //@11.0592MHz {unsigned char i;_nop_();i = 15;while (--i); }void Read_Data_From_DHT(){int i;int j;char tmp; //用來進行移位,用來獲得最低位char flag; //標志位DHT11_Start();for(i=0;i<5;i++){for(j=0;j<8;j++){while(!dht); //卡g點Delay40us(); //延時40usif(dht == 1){flag = 1;while(dht);}else{ flag = 0;}tmp = tmp << 1;tmp |= flag;}datas[i] = tmp;} }void LCD1602_INIT(){//(1)延時 15ms Delay15ms(); //(2)寫指令 38H(不檢測忙信號) Write_Cmd_Func(0x38); //(3)延時 5ms Delay5ms(); //(4)以后每次寫指令,讀/寫數據操作均需要檢測忙信號 check_busy(); //(5)寫指令 38H:顯示模式設置 Write_Cmd_Func(0x38); //(6)寫指令 08H:顯示關閉 Write_Cmd_Func(0x08); //(7)寫指令 01H:顯示清屏 Write_Cmd_Func(0x01); //(8)寫指令 06H:顯示光標移動設置 Write_Cmd_Func(0x06); //(9)寫指令 0CH:顯示開及光標設置Write_Cmd_Func(0x0c); }void LCD1602_showLine(char row,char col,char *string){switch(row){case 1:Write_Cmd_Func(0x80+col); //選擇要顯示的地址while(*string){Write_Data_Func(*string); //發送要顯示內容string++;}break;case 2:Write_Cmd_Func(0x80+0x40+col);while(*string){Write_Data_Func(*string);string++;}break;} }void Build_Datas(){huma[0] = 'H'; //溫度huma[1] = datas[0]/10 + 0x30;huma[2] = datas[0]%10 + 0x30;huma[3] = '.';huma[4] = datas[1]/10 + 0x30;huma[5] = datas[1]%10 + 0x30;huma[6] = '%';huma[7] = '\0';temp[0] = 'T'; //濕度temp[1] = datas[2]/10 + 0x30;temp[2] = datas[2]%10 + 0x30;temp[3] = '.';temp[4] = datas[3]/10 + 0x30;temp[5] = datas[3]%10 + 0x30;temp[6] = 'C';temp[7] = '\0';}void main() {Delay1000ms();UartInit(); //初始化一個串口LCD1602_INIT(); //初始化LCD1602液晶顯示Delay1000ms(); //上電后穩定DHT11的供電Delay1000ms();ledOne = 0; while(1){Delay1000ms();Read_Data_From_DHT(); //獲取DHT數據if(datas[2] > 29 ){fengshan = 0;}Build_Datas();sendString(huma); //發送濕度字符串sendString("\r\n");sendString(temp); //發送溫度字符串sendString("\r\n");LCD1602_showLine(1,3,temp); //第一行顯示濕度LCD1602_showLine(2,3,huma); //第二行顯示溫度} }執行結果:
總結
以上是生活随笔為你收集整理的DHT11温湿度传感器初识的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: emc存储java打开后报错,EMC存储
- 下一篇: XCP总结