Master DHT11 Temperature & Humidity Sensor on STM32: Full Code Walkthrough
This tutorial provides a comprehensive, step‑by‑step guide to using the DHT11 temperature and humidity sensor with an STM32F103C8T6 MCU, covering hardware wiring, sensor specifications, timing diagrams, HAL‑based driver implementation, and complete source code for reliable data acquisition.
The article introduces the DHT11 digital temperature and humidity sensor, its features, specifications, and typical applications in embedded projects such as smart home and IoT.
Source code and prerequisites
Links are provided for STM32 development environment setup, flashing methods, and a ready‑made project template for the STM32F103C8T6 MCU.
DHT11 overview
Describes the 3‑pin and 4‑pin packages, internal resistive humidity element and NTC temperature element, and the single‑wire serial interface that delivers 40 bits (humidity integer, humidity decimal, temperature integer, temperature decimal, checksum).
Parameters
Humidity range: 20‑90 %RH
Humidity accuracy: ±5 %RH
Temperature range: 0‑50 °C
Temperature accuracy: ±2 °C
Supply voltage: 3.3 V or 5 V
Hardware connection
Connect VCC to 3.3 V/5 V, DATA to any GPIO (e.g., PA8), and GND to ground. The original wiring table is omitted for brevity.
Working principle and timing
The sensor stays idle high. The host pulls the line low >18 ms, then high for 20‑40 µs to start. DHT11 responds with an 80 µs low pulse followed by an 80 µs high pulse, then transmits 40 bits. Each bit begins with a 50 µs low pulse; a subsequent high pulse of 26‑28 µs represents ‘0’, while 70 µs represents ‘1’.
Implementation on STM32 (HAL)
Microsecond delay is implemented with SysTick. GPIO direction is switched between input and output using HAL functions.
void delay_us(uint32_t nus) {
uint32_t temp;
SysTick->LOAD = nus * g_fac_us; /* load time */
SysTick->VAL = 0x00; /* clear counter */
SysTick->CTRL |= 1 << 0; /* start countdown */
do {
temp = SysTick->CTRL;
} while ((temp & 0x01) && !(temp & (1 << 16)));
SysTick->CTRL &= ~(1 << 0); /* stop */
SysTick->VAL = 0x00; /* clear */
}GPIO configuration functions:
void DHT_GPIO_INPUT(void) {
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = DHT11_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DHT11_IO, &GPIO_InitStructure);
}
void DHT_GPIO_OUTPUT(void) {
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = DHT11_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DHT11_IO, &GPIO_InitStructure);
}Start signal and response handling:
void DHT11_Start() {
DHT_GPIO_OUTPUT();
HAL_GPIO_WritePin(DHT11_IO, DHT11_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(DHT11_IO, DHT11_PIN, GPIO_PIN_RESET);
HAL_Delay(20); // pull low >18 ms
HAL_GPIO_WritePin(DHT11_IO, DHT11_PIN, GPIO_PIN_SET);
DHT_GPIO_INPUT();
while (HAL_GPIO_ReadPin(DHT11_IO, DHT11_PIN)); // wait for DHT11 low
while (!HAL_GPIO_ReadPin(DHT11_IO, DHT11_PIN)); // wait for DHT11 high
while (HAL_GPIO_ReadPin(DHT11_IO, DHT11_PIN)); // wait for DHT11 low again
}Reading a byte:
uint8_t DHT_Read_Byte(void) {
uint8_t i, ReadData = 0, temp;
for (i = 0; i < 8; i++) {
while (!HAL_GPIO_ReadPin(DHT11_IO, DHT11_PIN));
Delay_us(50);
if (HAL_GPIO_ReadPin(DHT11_IO, DHT11_PIN) == 1) {
temp = 1;
while (HAL_GPIO_ReadPin(DHT11_IO, DHT11_PIN));
} else {
temp = 0;
}
ReadData = (ReadData << 1) | temp;
}
return ReadData;
}Full read routine that assembles five bytes, verifies checksum, and prints temperature and humidity. A 2‑second delay is required between reads.
void DHT_Read() {
uint8_t i;
DHT11_Start();
DHT_GPIO_INPUT();
for (i = 0; i < 5; i++) {
Data[i] = DHT_Read_Byte();
}
if ((Data[0] + Data[1] + Data[2] + Data[3]) == Data[4]) {
printf("Humidity: %d.%dRH, ", Data[0], Data[1]);
printf("Temperature: %d.%d°C
", Data[2], Data[3]);
} else {
printf("ERROR DATA
");
}
HAL_Delay(2000);
}Header file snippet shows macro definitions and function prototype.
#ifndef __DHT11_H__
#define __DHT11_H__
#include "stdio.h"
#include "stm32f1xx.h"
#define DHT11_IO GPIOA
#define DHT11_PIN GPIO_PIN_8
void DHT_Read(void);
#endifConclusion
The guide provides a complete, 3000‑word, step‑by‑step example that enables readers to integrate DHT11 into STM32 projects, understand its timing constraints, and obtain reliable temperature and humidity readings.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
