DHT11 Single-Wire Communication Protocol: Data Format and Implementation

Data Packet Structure

The DHT11 sensor uses a single-wire communication protocol. Each data transmission consists of a 5-byte packet organized as follows:

  • Byte 0: Integer part of humidity
  • Byte 1: Fractional part of humidity
  • Byte 2: Integer part of temperature
  • Byte 3: Fractional part of temperature
  • Byte 4: Checksum byte

The sensor transmits data most significant bit first.

The humidity and temperature values are calculated as:

Humidity = buf[0] (integer)
Temperature = buf[2] (integer)
Checksum = buf[0] + buf[1] + buf[2] + buf[3]

Communication Timing Sequence

The complete communication cycle requires approximately 3ms.

Step 1: Master Start Signal

The MCU pulls the data line LOW for atleast 18ms, then releases it HIGH for 20-40μs.

Step 2: DHT11 Acknowledgment

The sensor responds by pulling the data line LOW for 40-50μs.

Step 3: DHT11 Ready Signal

After acknowledgment, the sensor pulls the data line HIGH for 40-50μs before transmitting data.

Data Bit Encoding

The sensor encodes each bit using pulse width modulation:

Bit Vallue Low Duration High Duration
0 12-14μs 26-28μs
1 12-14μs 116-118μs

The initial low pulse signals the start of each bit transmission. The subsequent high pulse duration determines whether the bit is 0 or 1.

Implementation

DHT11.h

#ifndef __DHT11_H__
#define __DHT11_H__

#include "sys.h"

#define DHT11_PIN GPIO_Pin_11
#define DHT11_PORT GPIOG

#define DHT11_OUT_HIGH() GPIO_SetBits(DHT11_PORT, DHT11_PIN)
#define DHT11_OUT_LOW() GPIO_ResetBits(DHT11_PORT, DHT11_PIN)
#define DHT11_READ() GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN)

void DHT11_Init(void);
u8 DHT11_Read_Data(u8 *temp, u8 *humi);

#endif

DHT11.c

#include "dht11.h"
#include "delay.h"

// Configure GPIO as output mode
static void DHT11_GPIO_OUT(void) {
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);
    GPIO_InitStruct.GPIO_Pin = DHT11_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DHT11_PORT, &GPIO_InitStruct);
}

// Configure GPIO as input mode
static void DHT11_GPIO_IN(void) {
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = DHT11_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(DHT11_PORT, &GPIO_InitStruct);
}

// Send reset pulse to DHT11
static void DHT11_Reset(void) {
    DHT11_GPIO_OUT();
    DHT11_OUT_LOW();
    delay_ms(20);
    DHT11_OUT_HIGH();
    delay_us(30);
}

// Check sensor acknowledgment
// Return 0: acknowledgment received
// Return 1: no response
static u8 DHT11_Check(void) {
    u8 timeout = 0;
    DHT11_GPIO_IN();
    
    while (DHT11_READ() && timeout < 100) {
        timeout++;
        delay_us(1);
    }
    if (timeout >= 100) return 1;
    
    timeout = 0;
    while (!DHT11_READ() && timeout < 100) {
        timeout++;
        delay_us(1);
    }
    if (timeout >= 100) return 1;
    
    return 0;
}

// Read single bit from DHT11
static u8 DHT11_Read_Bit(void) {
    u8 timeout = 0;
    
    while (DHT11_READ() && timeout < 100) {
        timeout++;
        delay_us(1);
    }
    
    timeout = 0;
    while (!DHT11_READ() && timeout < 100) {
        timeout++;
        delay_us(1);
    }
    
    delay_us(40);
    return DHT11_READ() ? 1 : 0;
}

// Read single byte from DHT11
static u8 DHT11_Read_Byte(void) {
    u8 i;
    u8 byte = 0;
    
    for (i = 0; i < 8; i++) {
        byte <<= 1;
        byte |= DHT11_Read_Bit();
    }
    return byte;
}

// Initialize DHT11 sensor
void DHT11_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);
    GPIO_InitStruct.GPIO_Pin = DHT11_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DHT11_PORT, &GPIO_InitStruct);
    GPIO_SetBits(DHT11_PORT, DHT11_PIN);
    DHT11_Reset();
}

// Read temperature and humidity from DHT11
// Return 0: success
// Return 1: failure
u8 DHT11_Read_Data(u8 *temp, u8 *humi) {
    u8 buffer[5];
    u8 i;
    
    DHT11_Reset();
    if (DHT11_Check() == 0) {
        for (i = 0; i < 5; i++) {
            buffer[i] = DHT11_Read_Byte();
        }
        if ((buffer[0] + buffer[1] + buffer[2] + buffer[3]) == buffer[4]) {
            *humi = buffer[0];
            *temp = buffer[2];
            return 0;
        }
    }
    return 1;
}

main.c

#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "lcd.h"
#include "dht11.h"

int main(void) {
    u8 counter = 0;
    u8 temperature = 0;
    u8 humidity = 0;
    
    delay_init();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    uart_init(115200);
    LED_Init();
    LCD_Init();
    
    POINT_COLOR = RED;
    
    while (DHT11_Read_Data(&temperature, &humidity)) {
        LCD_ShowString(30, 130, 200, 16, 16, "DHT11 Error");
        delay_ms(200);
        LCD_Fill(30, 130, 239, 146, WHITE);
        delay_ms(200);
    }
    
    LCD_ShowString(30, 130, 200, 16, 16, "DHT11 OK");
    POINT_COLOR = BLUE;
    LCD_ShowString(30, 150, 200, 16, 16, "Temp:   C");
    LCD_ShowString(30, 170, 200, 16, 16, "Humi:   %");
    delay_ms(200);
    
    while (1) {
        if (counter % 10 == 0) {
            DHT11_Read_Data(&temperature, &humidity);
            LCD_ShowNum(30 + 40, 150, temperature, 2, 16);
            LCD_ShowNum(30 + 40, 170, humidity, 2, 16);
        }
        delay_ms(10);
        counter++;
        if (counter == 20) {
            counter = 0;
            LED0 = !LED0;
        }
    }
}

Key Implementation Notes

  1. GPIO Configuration: The data pin must be switched between output mode (for sending reset signal) and input mode (for receiving data).

  2. Timing Critical: The delay between acknowledgment detection and bit reading (40μs) is crucial for sampling the data at the correct moment.

  3. Checksum Verification: Always verify the checksum byte before using the temperature and humidity values.

  4. Polling Interval: Allow at least 2 seconds between readings to ensure the sensor has sufficient time to complete its measurement cycle.

Tags: DHT11 single-wire embedded c programming sensor interface

Posted on Sun, 16 Aug 2026 16:49:52 +0000 by MadDogSh