浦東新區(qū)建設(shè)交通委網(wǎng)站鄭州seo線下培訓(xùn)
DHT11是一款可以測(cè)量溫度數(shù)據(jù)和濕度數(shù)據(jù)的傳感器
產(chǎn)品特點(diǎn)
暖通空調(diào)、除濕器、農(nóng)業(yè)、冷鏈倉(cāng)儲(chǔ)、測(cè)試及檢測(cè)設(shè)備、消費(fèi)品、汽車、自動(dòng)控制、數(shù)據(jù)記錄器、氣
象站、家電、濕度調(diào)節(jié)器、醫(yī)療、其他相關(guān)濕度檢測(cè)控制
外形尺寸
第3管腳:NC 是沒(méi)有用的
典型電路
通信方式
DHT11 器件采用簡(jiǎn)化的單總線通信。單總線即只有一根數(shù)據(jù)線,系統(tǒng)中的數(shù)據(jù)交換、控制均由單總線
完成。
設(shè)備(主機(jī)或從機(jī))通過(guò)一個(gè)漏枀開(kāi)路或三態(tài)端口連至該數(shù)據(jù)線,以允許設(shè)備在不發(fā)送數(shù)據(jù)時(shí)能夠
釋放總線,而讓其它設(shè)備使用總線;單總線通常要求外接一個(gè)約 4.7kΩ 的上拉電阻,這樣,當(dāng)總線閑置時(shí),
其狀態(tài)為高電平。由于它們是主從結(jié)極,只有主機(jī)呼叫從機(jī)時(shí),從機(jī)才能應(yīng)答,因此主機(jī)訪問(wèn)器件都必須
嚴(yán)格遵循單總線序列,如果出現(xiàn)序列混亂,器件將不響應(yīng)主機(jī)。
單總線傳送數(shù)據(jù)位定義
DATA 用于微處理器與 DHT11 之間的通訊和同步,采用單總線數(shù)據(jù)格式,一次傳送 40 位數(shù)據(jù),高位先
出。
數(shù)據(jù)格式
8bit 濕度整數(shù)數(shù)據(jù) + 8bit 濕度小數(shù)數(shù)據(jù) + 8bit 溫度整數(shù)數(shù)據(jù) + 8bit 溫度小數(shù)數(shù)據(jù) + 8bit 校驗(yàn)位。
“8bit 濕度整數(shù)數(shù)據(jù) + 8bit 濕度小數(shù)數(shù)據(jù) + 8bit 溫度整數(shù)數(shù)據(jù) + 8bit 溫度小數(shù)數(shù)據(jù)”8bit 校驗(yàn)位等于
所得結(jié)果的末 8 位
自己寫(xiě)的代碼一會(huì)做這個(gè)校驗(yàn)但是很少會(huì)關(guān)注這個(gè)負(fù)數(shù),其實(shí)負(fù)數(shù)的判斷也非常簡(jiǎn)單只需要判斷一下溫度的最高位是否為1就行,是1就代表是負(fù)數(shù)。
使用注意事項(xiàng)
- DHT11 上電后需要等待 1S,并且數(shù)據(jù)總線要保持高電平 ?
- 主機(jī)從 DHT11讀取的溫濕度數(shù)據(jù)總是前一次的測(cè)量值,如果測(cè)量間隔時(shí)間較長(zhǎng)(超過(guò) 4S),請(qǐng)連續(xù) 讀取兩次值,然后以第二次讀取的值為實(shí)時(shí)溫濕度值
- 當(dāng)主機(jī)要對(duì)數(shù)據(jù)總線操作操作(拉高/拉低)時(shí),應(yīng)配置為輸出模式;DHT11 對(duì)數(shù)據(jù)總線操作(拉高 /拉低)時(shí),主機(jī)應(yīng)配置為輸入模式
單片機(jī)用延遲函數(shù)時(shí),誤差不能太大,否則無(wú)法準(zhǔn)確讀取溫濕度的值 通訊協(xié)議的實(shí)現(xiàn)函數(shù)多次用到超時(shí)檢測(cè),這是為了避免程序運(yùn)行時(shí) DHT11 出現(xiàn)錯(cuò)誤而卡在 while 中
通信過(guò)程
參考代碼
#include "dht11.h"
#include "delay.h"/*
修改DHT11數(shù)據(jù)線的模式:推挽輸出/浮空輸入
*/
void DHT111_ChangeMode(DHT11_MODE Mode)
{GPIO_InitTypeDef DHT11_InitStruct;if(Mode == MODE_OUT){DHT11_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽模式設(shè)置}else{DHT11_InitStruct.GPIO_Mode = GPIO_Mode_IPU; //上拉輸入模式}DHT11_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; DHT11_InitStruct.GPIO_Pin = DHT11_DATA_PIN; //DHT11_DATA數(shù)據(jù)線GPIO_Init(DHT11_PORT, &DHT11_InitStruct);
}//初始化DHT11的IO口 DQ 同時(shí)檢測(cè)DHT11的存在
//返回1:不存在
//返回0:存在
uint8_t DHT11_Init(void)
{ RCC_APB2PeriphClockCmd(DHT11_CLK,ENABLE); //打開(kāi)對(duì)應(yīng)的使能GPIO_InitTypeDef DHT11_InitStruct;DHT11_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出DHT11_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;DHT11_InitStruct.GPIO_Pin = DHT11_DATA_PIN; GPIO_Init(DHT11_PORT,&DHT11_InitStruct); GPIO_SetBits(DHT11_PORT,DHT11_DATA_PIN); //空閑 輸出高 DHT11_Rset(); //復(fù)位DHT11return DHT11_Check(); //等待DHT11的回應(yīng)
} //復(fù)位DHT11 -- 起始信號(hào)
void DHT11_Rset(void)
{ DHT11_IO_OUT(); //SET OUTPUTDHT11_DQ_OUT(0); //拉低DQDelay_nms(20); //拉低至少18msDHT11_DQ_OUT(1); //DQ=1 Delay_nus(30); //主機(jī)拉高20~35us 等待從機(jī)響應(yīng)
}//等待DHT11的回應(yīng)
//返回1:未檢測(cè)到DHT11存在
//返回0:存在
uint8_t DHT11_Check(void)
{ uint8_t retry = ERR;DHT11_IO_IN(); //SET INPUT while(DHT11_DQ_IN()&&(retry<100))//DHT11會(huì)拉低40~50us{retry++;Delay_nus(1);} if(retry>=100)return ERR;//超時(shí)未等到信號(hào)變低就證明沒(méi)有回復(fù)else retry=0; //未超時(shí)則證明DHT11有信號(hào)回復(fù)while (!DHT11_DQ_IN()&&(retry<100))//DHT11拉低后會(huì)再次拉高 40~80us(即是等待高電平){retry++;Delay_nus(1);}if(retry>=100)return ERR;//超時(shí)未等到信號(hào)變低就證明沒(méi)有回復(fù) return OK;
}//從DHT11讀取一個(gè)位
//返回值:1/0
uint8_t DHT11_Read_Bit(void)
{uint8_t retry = 0;while(DHT11_DQ_IN()&&(retry<100))//等待變?yōu)榈碗娖?/span>{retry++;Delay_nus(1);}retry = 0;while(!DHT11_DQ_IN()&&retry<100)//等待變高電平{retry++;Delay_nus(1);}Delay_nus(40); //等待40usif(DHT11_DQ_IN())return 1;else return 0;
}//從DHT11讀取一個(gè)字節(jié)
//返回值:讀到的數(shù)據(jù)
uint8_t DHT11_Read_Byte(void)
{ uint8_t i,data;data=0;for(i=0;i<8;i++) {data<<=1; data|=DHT11_Read_Bit();} return data;
}
//從DHT11讀取一次數(shù)據(jù)
//temp:溫度值(范圍:0~50°)
//humi:濕度值(范圍:20%~90%)
//返回值:0,正常;1,讀取失敗
uint8_t DHT11_Read_Data(float *Temp,float *Humi)
{ DHT11_t DHT11 ={0};DHT11_Rset(); //先復(fù)位溫濕度傳感器if(DHT11_Check()==OK){DHT11.Humi_H = DHT11_Read_Byte();DHT11.Humi_L = DHT11_Read_Byte();DHT11.Temp_H = DHT11_Read_Byte();DHT11.Temp_L = DHT11_Read_Byte();DHT11.Check = DHT11_Read_Byte();if(DHT11.Check==(DHT11.Humi_H+DHT11.Humi_L+DHT11.Temp_H+DHT11.Temp_L)){ /*1111 1111*/*Temp=DHT11.Temp_H+(0.1*(int8_t)(DHT11.Temp_L));*Humi=DHT11.Humi_H+(0.1*(int8_t)(DHT11.Humi_L));}}else return 1;return 0;
}
#ifndef __DHT11_H_
#define __DHT11_H_#include "stm32f10x.h"//DHT11接口的宏定義
//方便修改和移植
//修改對(duì)應(yīng)端口和引腳
#define DHT11_CLK RCC_APB2Periph_GPIOB
#define DHT11_PORT GPIOB
#define DHT11_DATA_PIN GPIO_Pin_3 #define OK 0
#define ERR 1/*用枚舉自己定義了兩個(gè)模式模式1:輸入模式模式2:輸出模式
*/
typedef enum
{MODE_IN = 0,MODE_OUT = 1,
}DHT11_MODE;/*
自定義的結(jié)構(gòu)體
*/
typedef struct
{uint8_t Temp_H;uint8_t Temp_L;uint8_t Humi_H;uint8_t Humi_L;uint8_t Check;
}DHT11_t;//IO方向設(shè)置
#define DHT11_IO_IN() DHT111_ChangeMode(MODE_IN)
#define DHT11_IO_OUT() DHT111_ChangeMode(MODE_OUT)IO操作函數(shù)
#define DHT11_DQ_OUT(X) X?(GPIO_SetBits(DHT11_PORT,DHT11_DATA_PIN)):(GPIO_ResetBits(DHT11_PORT,DHT11_DATA_PIN))
#define DHT11_DQ_IN() GPIO_ReadInputDataBit(DHT11_PORT,DHT11_DATA_PIN)uint8_t DHT11_Init(void); //初始化DHT11
void DHT11_Rset(void); //復(fù)位DHT11
void DHT111_Change_Mode(DHT11_MODE Mode); //切換模式
uint8_t DHT11_Read_Byte(void); //讀出一個(gè)字節(jié)
uint8_t DHT11_Read_Bit(void); //讀出一個(gè)位
uint8_t DHT11_Check(void); //檢測(cè)是否存在DHT11
uint8_t DHT11_Read_Data(float *Temp,float *Humi); //讀取溫濕度#endif