本篇介紹STM32如何外接溫濕度傳感器實(shí)現(xiàn)當(dāng)前環(huán)境溫濕度的讀取,并顯示到OLED屏幕上。
1 DTH11溫濕度傳感器
DHT11數(shù)字溫濕度傳感器是一款含有已校準(zhǔn)數(shù)字信號輸出的溫濕度復(fù)合傳感器,包括一個電阻式感濕元件和一個NTC測溫元件。

1.1 數(shù)據(jù)讀取協(xié)議
微控制器MCU與 DHT11之間的通訊和同步,采用單總線數(shù)據(jù)格式,一次通訊時間4ms左右。
用戶MCU發(fā)送一次開始信號后,DHT11從低功耗模式轉(zhuǎn)換到高速模式,等待主機(jī)開始信號結(jié)束后,DHT11發(fā)送響應(yīng)信號,送出40bit的數(shù)據(jù),并觸發(fā)一次信號采集,用戶可選擇讀取部分?jǐn)?shù)據(jù)。
從模式下,DHT11接收到開始信號觸發(fā)一次溫濕度采集,如果沒有接收到主機(jī)發(fā)送開始信號,DHT11不會主動進(jìn)行溫濕度采集。采集數(shù)據(jù)后轉(zhuǎn)換到低速模式。
1.1.1 起始信號
總線空閑狀態(tài)為高電平,MCU把總線拉低等待DHT11響應(yīng),MCU把總線拉低必須大于18毫秒,保證DHT11能檢測到起始信號。
DHT11接收到主機(jī)的開始信號后,等待MCU的開始信號結(jié)束,然后發(fā)送80us低電平響應(yīng)信號。
MCU發(fā)送開始信號結(jié)束后,延時等待20-40us后,讀取DHT11的響應(yīng)信號,MCU發(fā)送開始信號后,可以切換到輸入模式,或者輸出高電平均可,總線由上拉電阻拉高。

1.1.2 數(shù)據(jù)數(shù)字信號
總線為低電平,說明DHT11發(fā)送響應(yīng)信號,DHT11發(fā)送響應(yīng)信號后,再把總線拉高80us,準(zhǔn)備發(fā)送數(shù)據(jù),每一bit數(shù)據(jù)都以50us低電平時隙開始,高電平的長短定了數(shù)據(jù)位是0還是1。
數(shù)字0和數(shù)字1的表示,如下面圖示:
數(shù)字0:50us低電平開始后,26-28us的高電平表示0
數(shù)字1:50us低電平開始后,70us的高電平表示1
如果讀取響應(yīng)信號為高電平,則DHT11沒有響應(yīng),需要檢查線路是否連接正常。

當(dāng)最后一bit數(shù)據(jù)傳送完畢后,DHT11拉低總線50us,隨后總線由上拉電阻拉高進(jìn)入空閑狀態(tài)。
1.1.3 溫濕度數(shù)據(jù)格式
一次完整的數(shù)據(jù)傳輸為40bit,高位先出。數(shù)據(jù)分小數(shù)部分和整數(shù)部分,數(shù)據(jù)格式:
8bit濕度整數(shù)數(shù)據(jù)
8bit濕度小數(shù)數(shù)據(jù)
8bit溫度整數(shù)數(shù)據(jù)
8bit溫度小數(shù)數(shù)據(jù)
8bit校驗(yàn)和
數(shù)據(jù)傳送正確時校驗(yàn)和數(shù)據(jù)等于“ 8bit 濕度整數(shù)數(shù)據(jù) +8bit 濕度小數(shù)數(shù)據(jù)+8bit溫度整數(shù)數(shù)據(jù) +8bit 溫度小數(shù)數(shù)據(jù) ”所得結(jié)果的末8位。
1.2 硬件接線
DHT11的數(shù)據(jù)讀取只需要一根線,我使用的是PB8,另外,OLED用來顯示溫濕度的值,使用IIC通信,使用的是PB6和PB7。

2 程序編寫
根據(jù)DHT11的數(shù)據(jù)讀取協(xié)議,編寫對應(yīng)的數(shù)據(jù)讀取函數(shù)。
2.1 DHT11復(fù)位和檢測響應(yīng)函數(shù)
首先是MCU向DHT11發(fā)送的起始信號,拉低20ms,再拉高30us。
u8 DHT11RstAndCheck(void)
{
    u8 timer = 0;
    __set_PRIMASK(1);          //關(guān)總中斷
    DHT11_OUT = 0; 	           //輸出低電平
    delay_ms(20);    	       //拉低至少18ms
    DHT11_OUT = 1; 	           //輸出高電平
    delay_us(30);     	       //拉高20~40us
    while (!DHT11_IN)          //等待總線拉低,DHT11會拉低40~80us作為響應(yīng)信號
    {
        timer++;               //總線拉低時計數(shù)
        delay_us(1);
    }
    if (timer>100 || timer<20) //判斷響應(yīng)時間
    {
        __set_PRIMASK(0);      //開總中斷
        return 0;
    }
	
    timer = 0;
    while (DHT11_IN)           //等待DHT11釋放總線,持續(xù)時間40~80us
    {
        timer++;               //總線拉高時計數(shù)
        delay_us(1);
    }
    __set_PRIMASK(0);          //開總中斷
    if (timer>100 || timer<20) //檢測響應(yīng)信號之后的高電平
    {
        return 0;
    }
	
    return 1;
}
2.2 數(shù)據(jù)讀取
MCU向DHT11發(fā)送起始信號后,就可以接收DHT11的數(shù)據(jù)返回了,一次讀取濕度和溫度即可。
/*讀取一字節(jié)數(shù)據(jù),返回值-讀到的數(shù)據(jù)*/
u8 DHT11ReadByte(void)
{
    u8 i;
    u8 byt = 0;
    __set_PRIMASK(1);      //關(guān)總中斷
    for (i=0; i<8; i++)
    {
        while (DHT11_IN);  //等待低電平,數(shù)據(jù)位前都有50us低電平時隙
		
        while (!DHT11_IN); //等待高電平,開始傳輸數(shù)據(jù)位
		
        delay_us(40);
        byt <<= 1;         //因高位在前,所以左移byt,最低位補(bǔ)0
        if (DHT11_IN)      //將總線電平值讀取到byt最低位中
        {
            byt |= 0x01;
        }
    }
    __set_PRIMASK(0);      //開總中斷
    return byt;
}
/*讀取一次數(shù)據(jù),返回參數(shù):Humi-濕度,Temp-溫度;返回值: 0-成功,1-失敗*/
u8 DHT11ReadData(float *Humi, float *Temp)
{
    s8 sta = 0;
    u8 i;
    u8 buf[5];
    if (DHT11RstAndCheck())         //檢測響應(yīng)信號
    {
        for(i=0;i<5;i++)            //讀取40位數(shù)據(jù)
        {
            buf[i]=DHT11ReadByte(); //讀取1字節(jié)數(shù)據(jù)
        }
        if(buf[0]+buf[1]+buf[2]+buf[3] == buf[4]) //校驗(yàn)成功
        {
            u8 H_inte = buf[0]; //濕度整數(shù)部分?jǐn)?shù)據(jù)
			u8 H_frac = buf[1]; //濕度小數(shù)部分?jǐn)?shù)據(jù)
            u8 T_inte = buf[2]; //溫度整數(shù)部分?jǐn)?shù)據(jù)
			u8 T_frac = buf[3]; //溫度小數(shù)部分?jǐn)?shù)據(jù)
			
			char tmp1[8], tmp2[8];
			sprintf(tmp1, "%d.%d",H_inte,H_frac);
			sscanf(tmp1, "%f", Humi);
			sprintf(tmp2, "%d.%d",T_inte,T_frac);
			sscanf(tmp2, "%f", Temp);
        }
        sta = 0;
    }
    else //響應(yīng)失敗返回-1
    {
        *Humi = 88; //響應(yīng)失敗返回-1
        *Temp = 88; //響應(yīng)失敗返回-1
        sta = 1;
    }
    
    return sta;    
}
2.3 初始化
使用DHT11之前,進(jìn)行引腳的初始化和器件的初始化。
/*DHT11初始化函數(shù)*/
u8 DHT11Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能GPIOC端口時鐘
    GPIO_SetBits(GPIOB,GPIO_Pin_8);                     //設(shè)置PC13輸出高電平,(先設(shè)置引腳電平可以避免IO初始化過程中可能產(chǎn)生的毛刺)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;	        //設(shè)置DHT11數(shù)據(jù)引腳->PC13
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;    //設(shè)置為開漏輸出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //設(shè)置輸出速率為50MHz
    GPIO_Init(GPIOB, &GPIO_InitStructure);	            //初始化GPIOC端口
    return DHT11RstAndCheck();                          //返回DHT11狀態(tài)
}
3 測試
在移植過U8g2庫的hello_world例程上進(jìn)行修改,在屏幕上顯示溫濕度。注意攝氏度單位的小圓圈,不知道怎么直接以符號的形式顯示出來,我這里是單獨(dú)畫了一個小空心圓。
int main(void)
{	
	delay_init();	    //延時函數(shù)初始化	  
	LED_Init();		  	//初始化與LED連接的硬件接口
	IIC_Init();
	 
	u8g2_t u8g2;
	u8g2Init(&u8g2);
	u8g2_SetFontMode(&u8g2, 1);
	u8g2_SetFont(&u8g2, u8g2_font_unifont_t_symbols);
	
	DHT11Init();
	float Temp = 0;
	float Humi = 0;
	char strTemp[32];
	char strHumi[32];
	while(1)
	{
		u8g2_FirstPage(&u8g2);
		do
		{
			//draw(&u8g2);
			DHT11ReadData(&Humi, &Temp);
			sprintf(strTemp, "Temp: %.1f C", Temp);
			sprintf(strHumi, "Humi: %.1f %%", Humi);
			
			u8g2_ClearBuffer(&u8g2);
			u8g2_DrawStr(&u8g2, 0, 30, strTemp);
			u8g2_DrawCircle(&u8g2, 84, 22, 2, U8G2_DRAW_ALL);
		    u8g2_DrawStr(&u8g2, 0, 60, strHumi);
			u8g2_SendBuffer(&u8g2);			
			delay_ms(3000);
		} while (u8g2_NextPage(&u8g2));
    }
}
測試效果如下:

4 總結(jié)
本篇介紹了如何在STM32上外接溫濕度DHT11實(shí)現(xiàn)溫濕度數(shù)據(jù)的讀取,并通過OLED進(jìn)行數(shù)據(jù)顯示。
- 
                                單片機(jī)
                                +關(guān)注
關(guān)注
6072文章
45277瀏覽量
661630 - 
                                嵌入式
                                +關(guān)注
關(guān)注
5178文章
20041瀏覽量
326402 - 
                                STM32
                                +關(guān)注
關(guān)注
2302文章
11108瀏覽量
370262 - 
                                DHT11
                                +關(guān)注
關(guān)注
19文章
277瀏覽量
59148 
發(fā)布評論請先 登錄
基于arduino的dht11溫濕度傳感器的使用
    
DHT11溫濕度傳感器介紹
使用DHT11溫濕度傳感器
DHT11溫濕度傳感器
基于STM32開發(fā)板實(shí)現(xiàn)傳感數(shù)據(jù)采集-DHT11溫濕度采集
使用STM32來讀取DHT11數(shù)字溫濕度傳感器
如何通過NodeMCU和DHT11收集溫濕度
如何使用STM32 HAL庫進(jìn)行開發(fā)并驅(qū)動DHT11溫濕度傳感器呢
DHT11數(shù)字溫濕度傳感器的相關(guān)資料推薦
使用51單片機(jī)應(yīng)用DHT11溫濕度傳感器通過1602顯示的程序免費(fèi)下載
    
使用 NodeMCU 和 DHT11 傳感器通過 MQTT 上傳溫濕度數(shù)據(jù)
    
溫濕度傳感器DHT11的STM32驅(qū)動實(shí)現(xiàn)
    
          
        
        
STM32外接DHT11溫濕度傳感器并通過OLED進(jìn)行數(shù)據(jù)顯示的設(shè)計電路與程序
                
 
    
           
            
            
                
            
評論