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

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

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

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

2 程序編寫
根據DHT11的數據讀取協議,編寫對應的數據讀取函數。
2.1 DHT11復位和檢測響應函數
首先是MCU向DHT11發送的起始信號,拉低20ms,再拉高30us。
u8 DHT11RstAndCheck(void)
{
u8 timer = 0;
__set_PRIMASK(1); //關總中斷
DHT11_OUT = 0; //輸出低電平
delay_ms(20); //拉低至少18ms
DHT11_OUT = 1; //輸出高電平
delay_us(30); //拉高20~40us
while (!DHT11_IN) //等待總線拉低,DHT11會拉低40~80us作為響應信號
{
timer++; //總線拉低時計數
delay_us(1);
}
if (timer>100 || timer<20) //判斷響應時間
{
__set_PRIMASK(0); //開總中斷
return 0;
}
timer = 0;
while (DHT11_IN) //等待DHT11釋放總線,持續時間40~80us
{
timer++; //總線拉高時計數
delay_us(1);
}
__set_PRIMASK(0); //開總中斷
if (timer>100 || timer<20) //檢測響應信號之后的高電平
{
return 0;
}
return 1;
}
2.2 數據讀取
MCU向DHT11發送起始信號后,就可以接收DHT11的數據返回了,一次讀取濕度和溫度即可。
/*讀取一字節數據,返回值-讀到的數據*/
u8 DHT11ReadByte(void)
{
u8 i;
u8 byt = 0;
__set_PRIMASK(1); //關總中斷
for (i=0; i<8; i++)
{
while (DHT11_IN); //等待低電平,數據位前都有50us低電平時隙
while (!DHT11_IN); //等待高電平,開始傳輸數據位
delay_us(40);
byt <<= 1; //因高位在前,所以左移byt,最低位補0
if (DHT11_IN) //將總線電平值讀取到byt最低位中
{
byt |= 0x01;
}
}
__set_PRIMASK(0); //開總中斷
return byt;
}
/*讀取一次數據,返回參數:Humi-濕度,Temp-溫度;返回值: 0-成功,1-失敗*/
u8 DHT11ReadData(float *Humi, float *Temp)
{
s8 sta = 0;
u8 i;
u8 buf[5];
if (DHT11RstAndCheck()) //檢測響應信號
{
for(i=0;i<5;i++) //讀取40位數據
{
buf[i]=DHT11ReadByte(); //讀取1字節數據
}
if(buf[0]+buf[1]+buf[2]+buf[3] == buf[4]) //校驗成功
{
u8 H_inte = buf[0]; //濕度整數部分數據
u8 H_frac = buf[1]; //濕度小數部分數據
u8 T_inte = buf[2]; //溫度整數部分數據
u8 T_frac = buf[3]; //溫度小數部分數據
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 //響應失敗返回-1
{
*Humi = 88; //響應失敗返回-1
*Temp = 88; //響應失敗返回-1
sta = 1;
}
return sta;
}
2.3 初始化
使用DHT11之前,進行引腳的初始化和器件的初始化。
/*DHT11初始化函數*/
u8 DHT11Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能GPIOC端口時鐘
GPIO_SetBits(GPIOB,GPIO_Pin_8); //設置PC13輸出高電平,(先設置引腳電平可以避免IO初始化過程中可能產生的毛刺)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //設置DHT11數據引腳->PC13
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //設置為開漏輸出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //設置輸出速率為50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOC端口
return DHT11RstAndCheck(); //返回DHT11狀態
}
3 測試
在移植過U8g2庫的hello_world例程上進行修改,在屏幕上顯示溫濕度。注意攝氏度單位的小圓圈,不知道怎么直接以符號的形式顯示出來,我這里是單獨畫了一個小空心圓。
int main(void)
{
delay_init(); //延時函數初始化
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 總結
本篇介紹了如何在STM32上外接溫濕度DHT11實現溫濕度數據的讀取,并通過OLED進行數據顯示。
-
單片機
+關注
關注
6076文章
45494瀏覽量
670262 -
嵌入式
+關注
關注
5198文章
20442瀏覽量
333978 -
STM32
+關注
關注
2309文章
11162瀏覽量
373406 -
DHT11
+關注
關注
19文章
277瀏覽量
59702
發布評論請先 登錄
基于arduino的dht11溫濕度傳感器的使用
DHT11溫濕度傳感器
使用51單片機應用DHT11溫濕度傳感器通過1602顯示的程序免費下載
使用 NodeMCU 和 DHT11 傳感器通過 MQTT 上傳溫濕度數據
STM32外接DHT11溫濕度傳感器并通過OLED進行數據顯示的設計電路與程序
評論