STM32學習之傳感器篇——DHT11溫溼度傳感器

1、DHT11傳感器簡介

DHT11數字溫溼度傳感器是一款含有已校準數字信號輸出的溫溼度複合傳感器,它應用專用的數字模塊採集技術和溫溼度傳感技術,確保產品具有極高的可靠性和卓越的長期穩定性。傳感器包括一個電阻式感溼元件和一個NTC測溫元件,並與一個高性能8位單片機相連接。因此該產品具有品質卓越、超快響應、抗干擾能力強、性價比極高等優點。每個DHT11傳感器都在極爲精確的溼度校驗室中進行校準。校準係數以程序的形式存在OTP內存中,傳感器內部在檢測型號的處理過程中要調用這些校準係數。單線制串行接口,使系統集成變得簡易快捷。超小的體積、極低的功耗,使其成爲該類應用甚至最爲苛刻的應用場合的最佳選擇。產品爲4針單排引腳封裝,連接方便。

 

                                                                 

傳感器特性

供電電壓: 3.3~5.5V DC ;    輸 出: 單總線數字信號 ;    測量範圍: 溼度20-90%RH, 溫度0~50℃ ;   測量精度: 溼度+-5%RH, 溫度+-2℃;   分 辨 率: 溼度1%RH, 溫度1℃;  互 換 性: 可完全互換 ; 長期穩定性: <±1%RH/年;                           

型號 測量範圍 測溼精度 測溫精度 分辨力 封裝
DHT11 20-90%RH 0-50℃ ±5%RH ±2℃ 1 4 針單排直插

電氣特性

參數 條件 min typ max 單位
供電 DC 3 5 5.5 V
供電電流 測量 0.5   2.5 mA
平均 0.2   1 mA
待機 100   150 uA
採樣週期 1    

引腳說明

pin 名稱 註釋
1 VDD 供電 3-5.5VDC
2 DATA 串行數據,單總線
3 NC 空腳,請懸空
4 GND 接地,電源負極

2、編程解讀

2.1、DHT11data數據格式: (高位先出)

 一次傳輸40位數據=8bit溼度整數數據 + 8bit溼度小數數據 + 8bit溫度整數數據 + 8bit溫度小數數據 + 8bit校驗和。數據傳送正確時,校驗和數據等於“8bit溼度整數數據+8位溼度小數數據+8bit溫度整數數據+8bit溫度小數數據”所得結果的末8位。

用戶MCU發送一次開始信號後,DHT11從低功耗轉換到高速模式,等待主機開始信號結束後,DHT11發送響應信號,送出40bit的數據,並觸發一次信號採集,用戶可選擇讀取部分數據,從模式下,DHT11接收到開始信號觸發一次溫溼度採集,如果沒有接收到主機發送開始信號,DHT11不會主動進行溫溼度採集,採集數據後轉換到低速模式。

2.2、時序編程

起步時序

總線空閒狀態爲高電平,主機把總線拉低等待DHT11響應,主機把總線拉低必須大於18毫秒,保證DHT11能檢測到起始信號。DHT11接收到主機的開始信號後,等待主機開始信號結束,然後發送80us低電平響應信號.主機發送開始信號結束後,延時等待20-40us後, 讀取DHT11的響應信號,主機發送開始信號後,可以切換到輸入模式,或者輸出高電平均可, 總線由上拉電阻拉高。

數據接收時序

總線爲低電平,說明DHT11發送響應信號,DHT11發送響應信號後,再把總線拉高80us,準備發送數據,每一bit數據都以50us低電平時隙開始,高電平的長短定了數據位是0還是1.格式見下面圖示.如果讀取響應信號爲高電平,則DHT11沒有響應,請檢查線路是否連接正常.當最後一bit數據傳送完畢後,DHT11拉低總線50us,隨後總線由上拉電阻拉高進入空閒狀態。

數字0信號表示方法

            

數字1信號表示方法

     

 

3、DHT11通信流程及代碼

3.1、簡單通訊流程

第一步初始化IO口 完成起步時序 檢查DHT11是否存在

第二部主機信號線拉高準備接收數據,依次接收40位

3.2主要程序部分

dht11.h部分代碼

#ifndef _dht11_h
#define _dht11_h

#include "system.h"
#include "SysTick.h"




#define DHT11 (GPIO_Pin_4) //PA4
#define GPIO_DHT11 GPIOA
#define DHT11_DQ_IN PAin(4)	  //輸入
#define DHT11_DQ_OUT PAout(4)  //輸出
void DHT11_IO_OUT(void);
void DHT11_IO_IN(void);
u8 DHT11_Init(void);
void DHT11_Rst(void);
u8 DHT11_Check(void);
u8 DHT11_Read_Bit(void);
u8 DHT11_Read_Byte(void);
u8 DHT11_Read_Data(u8 *temp,u8 *humi);

#endif

dht11.c部分代碼

#include "stm32f10x.h"                  // Device header
#include "dht11.h"
/*******************************************************************************
* 函 數 名         : DHT11_Init()
* 函數功能		     : DHT11初始化 
* 引    腳         : PA4
* 輸    出         : 返回0:初始化成功,1:失敗
*******************************************************************************/
u8 DHT11_Init()
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

	GPIO_InitStructure.GPIO_Pin=DHT11;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIO_DHT11,&GPIO_InitStructure);
	GPIO_SetBits(GPIO_DHT11,DHT11);	   //拉高

	DHT11_Rst();	  
	return DHT11_Check();	
}
/*******************************************************************************
* 函 數 名         : DHT11_Rst(),DHT11_Check() 
* 函數功能		     : 復位DHT11,檢測DHT11
* 引    腳         : PA4
* 輸    出         ://返回1:未檢測到DHT11的存在,返回0:存在
*******************************************************************************/
void DHT11_Rst()	   
{                 
		DHT11_IO_OUT(); 		//配置io口爲輸出模式
    DHT11_DQ_OUT=0; 		//拉低DQ
    delay_ms(20);    		//拉低至少18ms
    DHT11_DQ_OUT=1; 		//DQ=1 
		delay_us(30);     	//主機拉高20~40us
}
u8 DHT11_Check() 	   
{   
	u8 retry=0;
	DHT11_IO_IN();//配置io口爲輸入模式 
    while (DHT11_DQ_IN&&retry<100)//高電平循環,低電平跳出
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=100)return 1;
	else retry=0;
    while (!DHT11_DQ_IN&&retry<100)//DHT11拉低後會再次拉高40~50us
	{
		retry++;
		delay_us(1);
	};
	if(retry>=100)return 1;	    
	return 0;
}


/*******************************************************************************
* 函 數 名         : DHT11_Read_Bit(void) 
* 函數功能		     : 從DHT11讀取一個位
* 引    腳         : PA4
* 輸    出         :返回值:1/0
*******************************************************************************/
u8 DHT11_Read_Bit(void) 			 
{
 	u8 retry=0;
	while(DHT11_DQ_IN&&retry<100)//等待變爲低電平 12-14us 開始
	{
		retry++;
		delay_us(1);
	}
	retry=0;
	while(!DHT11_DQ_IN&&retry<100)//等待變高電平	 26-28us表示0,116-118us表示1
	{
		retry++;
		delay_us(1);
	}
	delay_us(40);//等待40us
	if(DHT11_DQ_IN)return 1;
	else return 0;		   
}
/*******************************************************************************
* 函 數 名         : DHT11_Read_Byte(void)
* 函數功能		     : 從DHT11讀取一個字節
* 引    腳         : PA4
* 輸    出         :返回值:讀到的數據
*******************************************************************************/
u8 DHT11_Read_Byte(void)    
{        
    u8 i,dat;
    dat=0;
	for (i=0;i<8;i++) 
	{
   		dat<<=1; 
	    dat|=DHT11_Read_Bit();
    }						    
    return dat;
}
/*******************************************************************************
* 函 數 名         : DHT11_Read_Data(u8 *temp,u8 *humi) 
* 函數功能		     : 從DHT11讀取一次數據
* 引    腳         : PA4
* 輸    出         :返回值:0,正常;1,讀取失敗
*******************************************************************************/
u8 DHT11_Read_Data(u8 *temp,u8 *humi)    
{        
 	u8 buf[5];
	u8 i;
	DHT11_Rst();
	if(DHT11_Check()==0)
	{
		for(i=0;i<5;i++)//讀取40位數據
		{
			buf[i]=DHT11_Read_Byte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
		{
			*humi=buf[0];
			*temp=buf[2];
		}
		
	}
		else 
		return 1;
		return 0;	    
}
//DHT11輸出模式配置
void DHT11_IO_OUT()	
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin=DHT11;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;	 //推輓輸出
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIO_DHT11,&GPIO_InitStructure);	
}

//DHT11輸入模式配置
void DHT11_IO_IN()	
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin=DHT11;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;	 //上拉輸入模式
	GPIO_Init(GPIO_DHT11,&GPIO_InitStructure);	
}

mian.c代碼

#include <stm32f10x.h>
#include <SysTick.h>
#include "system.h"
#include "usart1.h"
#include "dht11.h"


int main()
{
u8 temperature;         
u8 humidity; 
u8 rx_buf[5];
SysTick_Init(72);   //系統時鐘初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中斷優先級分組 分2組
USART1_Init(9600);                    //串口初始化PA9,PA10
DHT11_Init();                         //DHT11初始化      引腳PA4PA6-MISO PA7-MOSI 
	while(1)
	{
		DHT11_Read_Data(&temperature,&humidity);				 

		rx_buf[0]=temperature;
		rx_buf[1]=humidity;
        printf("temp=%d,humi=%d",rx_buf[0],rx_buf[1]);		  
				delay_ms(20);
	}
}

總結一下DHT11總體來說挺簡單的 只要清楚理解它的時序,就可以快速上手這款傳感器

DHT11.C和DHT11.H文件可在下邊下載


 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章