Fundamentals 13 min read

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.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Master DHT11 Temperature & Humidity Sensor on STM32: Full Code Walkthrough

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);
#endif

Conclusion

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.

C++HALSensorSTM32DHT11
Liangxu Linux
Written by

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.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.