포스트

DTH11_온습도센서 드라이버 만들기

DTH11_온습도센서 드라이버 만들기

DTH11

온습도 센서


📌 동작원리 (Datasheet기반)

DHT11 datasheet 링크

1. 기본 구조

data 라인 하나로 MCU와 DHT11간 통신

2. 전압

3.5V ~ 5V DC 공급 필요

3. 통신 방식

Single Wire 양방향 Serial 통신

한 전송에 40bit

  • 8bit : 습도 정수부
  • 8bit : 습도 소수부
  • 8bit : 온도 정수부
  • 8bit : 온도 소수부
  • 8bit : 체크섬
1
2
3
4
5
6
7
typedef struct{
    uint8_t humidity_int;
    uint8_t humidity_dec;
    uint8_t temperature_int;
    uint8_t temperature_dec;
    uint8_t checksum;
}DHT11_Data;    //40bit

4. 통신전 사전설정

  1. Low 전압 최소 18ms 공급
  2. High 전압 공급 후 20 ~ 40us 대기

5. 센서값 받기

dht11에서 LOW -> HIGH -> LOW 값을 보내오는 것을 대기

dht11로부터 수신 시작


1바이트씩 보냄 바이트당 송신 전 LOW신호를 보내옴
dht11에서 0을 보낼 때 : HIGH 신호 26 ~ 28 us 보내옴
dht11에서 1을 보낼 때 : HIGH 신호 70 us 보내옴


📌 코드

코드 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
void delay_us(uint32_t us) {
    Ifx_TickTime ticks = IfxStm_getTicksFromMicroseconds(BSP_DEFAULT_TIMER, us);
    waitTime(ticks);
}

uint8_t DHT11_ReadByte(void) {
    uint8_t result = 0;
    for (int i = 0; i < 8; i++) {
        while (IfxPort_getPinState(DHT11_PORT.port, DHT11_PORT.pinIndex) == 0); // LOW면 대기
        delay_us(30);  // 26~28us면 '0', 70us면 '1'

        if (IfxPort_getPinState(DHT11_PORT.port, DHT11_PORT.pinIndex)) {    //70us이상일 때 High기록
            result |= (1 << (7 - i));   //MSB부터 write
        }

        while (IfxPort_getPinState(DHT11_PORT.port, DHT11_PORT.pinIndex) == 1); // HIGH면 대기
    }
    return result;
}

int DHT11_process(DHT11_Data *data) {
    uint8_t buffer[5] = {0};

    // MCU → DHT11: Start Signal
    IfxPort_setPinModeOutput(DHT11_PORT.port, DHT11_PORT.pinIndex, IfxPort_OutputMode_pushPull, IfxPort_OutputIdx_general);
    IfxPort_setPinLow(DHT11_PORT.port, DHT11_PORT.pinIndex);
    delay_us(18000);  // 최소 18ms 동안 LOW 유지
    IfxPort_setPinHigh(DHT11_PORT.port, DHT11_PORT.pinIndex);
    delay_us(40);  // 20~40us 동안 HIGH 유지

    // MCU ← DHT11: 응답 대기
    IfxPort_setPinModeInput(DHT11_PORT.port, DHT11_PORT.pinIndex, IfxPort_Mode_inputPullUp);

    //DHT11에서 Low -> High -> Low 보내옴
    uint32_t timeout = TIMEOUT;
    while (IfxPort_getPinState(DHT11_PORT.port, DHT11_PORT.pinIndex) == 1) {
        if (--timeout == 0) return -1;  // 응답 없음
    }
    timeout = TIMEOUT;
    while (IfxPort_getPinState(DHT11_PORT.port, DHT11_PORT.pinIndex) == 0) {
        if (--timeout == 0) return -1;
    }
    timeout = TIMEOUT;
    while (IfxPort_getPinState(DHT11_PORT.port, DHT11_PORT.pinIndex) == 1) {
        if (--timeout == 0) return -1;
    }

    // 데이터 수신 (40비트 = 5바이트)
    for (int i = 0; i < 5; i++) {
        buffer[i] = DHT11_ReadByte();
    }

    // 체크섬 검증
    if (buffer[4] != (buffer[0] + buffer[1] + buffer[2] + buffer[3])) {
        return -2;  // 체크섬 오류
    }

    // 데이터 저장
    data->humidity_int = buffer[0];
    data->humidity_dec = buffer[1];
    data->temperature_int = buffer[2];
    data->temperature_dec = buffer[3];
    data->checksum = buffer[4];

    return 0;
}