《電子DIY》之基於STM32驅動溫溼度傳感器DHT11、DHT12

一,DHT11(12)傳感器簡介

DHT11 是一款溼溫度一體化的數字傳感器。該傳感器包括一個電阻式測溼元件和一個 NTC 測溫元件,通過單片機等微處理器簡單的電路連接就能夠實時的採集本地溼度和溫度。DHT11 與單片機之間能採用簡單的單總線進行通信,僅僅需要一個I/O 口。傳感器內部溼度和溫度數據 40Bit 的數據一次性傳給單片機,數據採用校驗和方式進行校驗,有效的保證數據傳輸的準確性。DHT11 功耗很低,5V 電源電壓下,工作平均最大電流 0.5mA。

溼度:
溼度,表示大氣乾燥程度的物理量。在一定的溫度下在一定體積的空氣裏含有的水汽越少,則空氣越乾燥;水汽越多,則空氣越潮溼。空氣的乾溼程度叫做“溼度”。在此意義下,常用絕對溼度、相對溼度、比較溼度、混合比、飽和差以及露點等物理量來表示;若表示在溼蒸汽中水蒸氣的重量佔蒸汽總重量(體積)的百分比,則稱之爲蒸汽的溼度。人體感覺舒適的溼度是:相對溼度低於70%(摘自百度)

工作特性:

 工作電壓範圍:3.5V-5.5V 
 工作電流 :平均 0.5mA 
 溼度測量範圍:2090%RH 
 溫度測量範圍:050℃
 溼度分辨率 :1%RH 8 位
 溫度分辨率 :18 位
 採樣週期 :1S 
 單總線結構
 與 TTL 兼容(5V)

(摘自芯片手冊)

二、引腳定義

在這裏插入圖片描述
在這裏插入圖片描述

三、典型連接電路

DHT11 數字溼溫度傳感器連接方法簡單。第一腳接電源正,第四腳接電源地端。數據端爲第二腳。可直接接主機(單片機)的 I/O 口。爲提高穩定性,通常在數據端和電源正之間接一隻 4.7K左右 的上拉電阻。第三腳爲空腳,此管腳懸空不用。
在這裏插入圖片描述
在這裏插入圖片描述

四、DHT11內部數據結構

DHT11數字溼溫度傳感器採用單總線數據格式。即,單個數據引腳端口完成輸入輸出雙向傳輸。其數據包由5Byte(40Bit)組成。數據分小數部分和整數部分。
一次完整的數據傳輸爲40bit,高位先出

數據格式:

8bit溼度整數數據+8bit溼度小數數據+8bit溫度整數數據+8bit溫度小數數據+8bit校驗和
注:
1,校驗和數據爲前四個字節相加
2,傳感器數據輸出的是未編碼的二進制數據,即數據(溼度、溫度、整數、小數)之間應該分開處理

採集數據後的處理方式舉例:
(設某時刻採集的數據如下:)

 byte4      byte3     byte2      byte1      byte0 
 00101101  00000010  00011100   00000001   01001001  (二進制)
 2DH		02H			1CH			01H		  49H    (十進制)
 45         2           28           1        76
 整數      小數       整數       小數       校驗和
      溼度                 溫度             校驗和

由以上數據就可得到溼度和溫度的值,計算方法:
humi (溼度)= byte4 . byte3=45.2 (%RH) 
temp (溫度)= byte2 . byte1=28.1 () 
(校驗和)= byte4+ byte3+ byte2+ byte1=76(=humi+temp)(校驗正確) 
注意:DHT11一次通訊時間最大3ms,主機連續採樣間隔建議不小於100ms。

五、DHT11採樣時序

DHT11 開始發送數據流程:
在這裏插入圖片描述分析:
主機發送開始信號後,延時等待 20us-40us 後讀取 DHT11 的應答信號,讀取總線爲低電平,說明 DHT11 發送響應信號,DHT11 發送響應信號後,再把總線拉高,準備發送數據,每一 bit 數據都以低電平開始,格式見如果讀取響應信號爲高電平,則 DHT11 沒有響應,請檢查線路是否連接正常。

主機復位信號和 DHT11 響應信號
在這裏插入圖片描述

數字‘0’信號表示方法

在這裏插入圖片描述
數字‘1’信號表示方法
在這裏插入圖片描述

六、DHT11程序源碼

程序源碼:
注:使用串口打印採集的溫溼度數據(1秒採集一次數據)
DHT11 h文件

//Author: Liu Xianfei 0810
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
typedef struct __DHT11_2
{
	u8 temperature[2];  //temperature
	u8 humidity[2];     //humidity
	u16 checksum;       //checksum
}DHT11;
extern DHT11 dht11;
#define DHT11PORT  GPIOA
#define DHT11PIN   GPIO_Pin_11
#define DHT11CLK  RCC_APB2Periph_GPIOA
//IO direction setting
#define DHT11_2_IO_IN()  {GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=8<<12;}
#define DHT11_2_IO_OUT() {GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=3<<12;}
//IO operation function											   
#define	DHT11_2_DQ_OUT PAout(11) 
#define	DHT11_2_DQ_IN  PAin(11)  
//Function declaration
void DHT11_2_Init(void);
u8 DHT11_2_Read_Data(void);    
u8 DHT11_2_Read_Byte(void);
u8 DHT11_2_Read_Bit(void);
u8 DHT11_2_Check(void);
void DHT11_2_Rst(void); 
#endif

DHT11 C文件

#include "DHT11.h"

DHT11 dht11={0,0,0,0,0};

/*
*	Function name: initialize DHT11
*	Parameter: None
*	Return value: None
*	Author: Liu Xianfei 0810
*/
void DHT11_2_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	
	RCC_APB2PeriphClockCmd(DHT11CLK,ENABLE);//Turn on the clock
	//Initialization pin
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=DHT11PIN;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(DHT11PORT,&GPIO_InitStruct);
 	GPIO_SetBits(DHT11PORT,DHT11PIN);//Pull up pin			    
}

/*
*	Function name: reset DHT11
*	Parameter: None
*	Return value: None
*/
void DHT11_2_Rst(void)	   
{                 
	DHT11_2_IO_OUT(); 	//SET OUTPUT
    DHT11_2_DQ_OUT=0; 	//pull downDQ
    delay_ms(20);    	//Pull down for at least 18ms
    DHT11_2_DQ_OUT=1; 	//DQ=1 
	delay_us(30);     	//Main engine pull-up 20 ~ 40us
}

/*
*	Function name: waiting for DHT11 to respond
*	Parameter: None
*	Return value: 1: DHT11 not detected 0: DHT11 detected
*/
u8 DHT11_2_Check(void) 	   
{   
	u8 retry=0;
	DHT11_2_IO_IN();//SET INPUT	 
    while (DHT11_2_DQ_IN&&retry<100)//DHT11 will pull down 40~80us
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=100)
		return 1;
	else 
		retry=0;
	//When DHT11 is pulled down, it will be pulled up again by 40-80us
    while (!DHT11_2_DQ_IN&&retry<100)
	{
		retry++;
		delay_us(1);
	};
	if(retry>=100)
		return 1;	    
	return 0;
}

/*
*	Function name: read a bit from DHT11
*	Parameter: None
*	Return value: 1 or 0
*/
static u8 DHT11_2_Read_Bit(void) 			 
{
 	u8 retry=0;
	while(DHT11_2_DQ_IN&&retry<100)//Waiting for low level
	{
		retry++;
		delay_us(1);
	}
	retry=0;
	while(!DHT11_2_DQ_IN&&retry<100)//Waiting for high level
	{
		retry++;
		delay_us(1);
	}
	delay_us(40);
	if(DHT11_2_DQ_IN)
		return 1;
	else 
		return 0;		   
}

/*
*	Function name: read a byte from DHT11
*	Parameter: None
*	Return value: data of 1B
*	Author: Liu Xianfei 0810
*/
static u8 DHT11_2_Read_Byte(void)    
{        
    u8 i,dat;
    dat=0;
	for (i=0;i<8;i++) 
	{
   		dat<<=1; 
	    dat|=DHT11_2_Read_Bit();
    }						    
    return dat;
}

/*
*	Function name: read data once from DHT11
*	Parameter: temp: temperature value (range: 0 ~ 50 °) humi: humidity value (range: 20% ~ 90%)
*	Return value: 0, normal; 1, read failed
*/
u8 DHT11_2_Read_Data(void)    
{        
 	u8 buf[5];
	u8 i;
	DHT11_2_Rst();
	if(DHT11_2_Check()==0)
	{
		for(i=0;i<5;i++)//Read 40 bit data
		{
			buf[i]=DHT11_2_Read_Byte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
		{
			//Assignment
			dht11.humidity[0]=buf[0];
			dht11.humidity[1]=buf[1];
			dht11.temperature[0]=buf[2];
			dht11.temperature[1]=buf[3];
			dht11.checksum=buf[4];
		}
	}
	else 
		return 1;
	return 0;	    
}

延時函數 h文件

/*
	Filename: delay function
	Author: Liu Xianfei 0810
	Related note: use the system tick counter to realize the delay function
*/
#ifndef _delay_H
#define _delay_H 			   
#include "sys.h"   	 
void delay_init_liuxianfei0810(void);
void delay_ms(u16 nms);
void delay_us(u32 nus);
#endif

延時函數 c文件

#include "delay.h"

static u8  fac_us=0;	//us delay multiplier
static u16 fac_ms=0;    //ms delay multiplier
	
/*
	Function name: initialization delay function
	Author: Liu Xianfei 0810
	Description:
		Systick clock is fixed to 1/8 of HCLK clock
		Sysclk: system clock
*/
void delay_init_liuxianfei0810(void)
{
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	
	//Select external clock HCLK/8
	fac_us=SystemCoreClock/8000000;							
	//1/8 of the system clock  
	fac_ms=(u16)fac_us*1000;		
	//Represents the number of systick clocks required per ms  
}								    

/*
	Function name: delay NUS function
	Author: Liu Xianfei 0810
	Description:
			nus is the number of us to delay						  MAXnus=2^24(LOAD)/fac_us
			=2^24(LOAD)/(SystemCoreClock/8000000)=2^24(LOAD)/9
*/    								   
void delay_us(u32 nus)
{		
	u32 temp;	    	 
	SysTick->LOAD=nus*fac_us; 					//Time loading	  		 
	SysTick->VAL=0x00;        					//Clear counter
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	//Start countdown	  
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));		//Waiting time arrives  
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//Turn off counter
	SysTick->VAL =0X00;      					//Clear counter	 
}

/*
	Function name: delay NMS function
	Author: Liu Xianfei 0810
	Description: Delay nms
		Note the range of nms
		Systick -> load is a 24 bit register, so the maximum delay is:
				nms<=0xffffff*8*1000/SYSCLK
				Sysclk in Hz, nms in nms
				For 72MHz clock, nms <= 1864
*/
void delay_ms(u16 nms)
{	 		  	  
	u32 temp;		   
	SysTick->LOAD=(u32)nms*fac_ms;				
	//Time loading (systick ->LOAD is 24bit)
	SysTick->VAL =0x00;						
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));		
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	
	SysTick->VAL =0X00;       						    
} 

七、效果圖

在這裏插入圖片描述

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