DHT11和DHT22使用區別(基於STM32)

JLouis94發表於2020-10-15

介紹

溫溼度模組DHT11和DHT22小專案用得比較多,雖然二者均是1-wire協議,但是細節部分還是有所差異。1-wire協議我就不多介紹了,網上很詳細。這裡著重介紹二者使用的區別。

DHT11
DHT11
DHT22

在這裡插入圖片描述

DHT系列區別

DHT11和DHT22

晶片手冊
提取:hgew

起始訊號

DHT11

在這裡插入圖片描述

在這裡插入圖片描述

DHT22

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

顯然DHT11拉低要>18ms,而DHT22拉低只要>1ms就足夠。

程式碼實現

/*
 * 一次完整的資料傳輸為40bit,高位先出
 * 8bit 溼度整數 + 8bit 溼度小數 + 8bit 溫度整數 + 8bit 溫度小數 + 8bit 校驗和 
 */
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{  
	/*輸出模式*/
	DHT11_Mode_Out_PP();
	/*主機拉低*/
	DHT11_Dout_0;
	
	/*延時18ms*/
	DHT11_DELAY_MS(18); //dht11
	//DHT11_DELAY_MS(2); //dht22
	
	/*匯流排拉高 主機延時30us*/
	DHT11_Dout_1; 

	DHT11_DELAY_US(30);   //延時30us

	/*主機設為輸入 判斷從機響應訊號*/ 
	DHT11_Mode_IPU();

	/*判斷從機是否有低電平響應訊號 如不響應則跳出,響應則向下執行*/   
	if(DHT11_Dout_IN()==Bit_RESET)     
	{
		/*輪詢直到從機發出 的80us 低電平 響應訊號結束*/  
		while(DHT11_Dout_IN()==Bit_RESET);

		/*輪詢直到從機發出的 80us 高電平 標置訊號結束*/
		while(DHT11_Dout_IN()==Bit_SET);

		/*開始接收資料*/   
		DHT11_Data->humi_int= DHT11_ReadByte();

		DHT11_Data->humi_deci= DHT11_ReadByte();

		DHT11_Data->temp_int= DHT11_ReadByte();

		DHT11_Data->temp_deci= DHT11_ReadByte();

		DHT11_Data->check_sum= DHT11_ReadByte();


		/*讀取結束,引腳改為輸出模式*/
		DHT11_Mode_Out_PP();
		/*主機拉高*/
		DHT11_Dout_1;

		/*檢查讀取的資料是否正確*/
		if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
			return SUCCESS;
		else 
			return ERROR;
	}
	
	else
		return ERROR;
	
}

13行 DHT11_DELAY_MS(18); 14行 DHT11_DELAY_MS(2); //DHT11時,延時18ms;DHT22時,延時1ms(建議2ms,經測試1ms有可能讀取失敗)

資料處理

DHT11

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

DHT22

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

程式碼實現

/*
 * 一次完整的資料傳輸為40bit,高位先出
 * 8bit 溼度整數 + 8bit 溼度小數 + 8bit 溫度整數 + 8bit 溫度小數 + 8bit 校驗和 
 */
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{  
	uint32_t humi=0;
	uint32_t temp =0;
	
	/*輸出模式*/
	DHT11_Mode_Out_PP();
	/*主機拉低*/
	DHT11_Dout_0;
	/*延時2ms*/
	DHT11_DELAY_MS(2);

	/*匯流排拉高 主機延時30us*/
	DHT11_Dout_1; 

	DHT11_DELAY_US(30);   //延時30us

	/*主機設為輸入 判斷從機響應訊號*/ 
	DHT11_Mode_IPU();

	/*判斷從機是否有低電平響應訊號 如不響應則跳出,響應則向下執行*/   
	if(DHT11_Dout_IN()==Bit_RESET)     
	{
		/*輪詢直到從機發出 的80us 低電平 響應訊號結束*/  
		while(DHT11_Dout_IN()==Bit_RESET);

		/*輪詢直到從機發出的 80us 高電平 標置訊號結束*/
		while(DHT11_Dout_IN()==Bit_SET);

		/*開始接收資料,需要修改的計算方式跟dht11不同*/   
		DHT11_Data->humi_int= DHT11_ReadByte();

		DHT11_Data->humi_deci= DHT11_ReadByte();

		DHT11_Data->temp_int= DHT11_ReadByte();

		DHT11_Data->temp_deci= DHT11_ReadByte();

		DHT11_Data->check_sum= DHT11_ReadByte();


		/*讀取結束,引腳改為輸出模式*/
		DHT11_Mode_Out_PP();
		/*主機拉高*/
		DHT11_Dout_1;

		/*檢查讀取的資料是否正確*/
		if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)
		{	/*----------------------------------資料處理-----------------------*/
			/*----------------DHT22溫溼度16bit精度,故需要分高低位元組計算,且需要uint32_t變數裝載---------------------*/
			/*-----------------------------溼度和溫度的高八位需要乘以256再加上低八位---------------------------------*/
			humi = DHT11_Data->humi_int *256 + DHT11_Data->humi_deci;
			temp = DHT11_Data->temp_int *256 + DHT11_Data->temp_deci;
			
			
			DHT11_Data->humi_int = (uint8_t)(humi*0.1);
			DHT11_Data->humi_deci = humi%10;
			
			DHT11_Data->temp_int = (uint8_t)(temp*0.1);
			DHT11_Data->humi_deci = temp%10;
			
			return SUCCESS;
		}
		else 
			return ERROR;
	}
	
	else
		return ERROR;
	
}

此處並沒有錯,我的程式通過改變巨集定義即可切換dht11或dht22測量。所以函式名稱沒改回來。

除錯問題

DHT22讀取失敗

1.主機拉低傳送起始訊號延時1ms時會讀取失敗,但延時2ms能完美解決問題。
2.兩次資料讀取時間過短,建議大於2s。

實現程式碼

程式碼地址

相關文章