guowenxue
2021-08-29 77ddd4a0943e2f9935bec2e00fffacec370cc1aa
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
 * dht11.c
 *
 *  Created on: Aug 8, 2021
 *      Author: Think
 */
 
#include "tim.h"
#include "gpio.h"
#include "main.h"
 
typedef struct w1_gpio_s
{
    GPIO_TypeDef        *group;
    uint16_t             pin;
} w1_gpio_t;
 
static w1_gpio_t   W1Dat =  /* IO pin connected to PA5 */
{
        .group = GPIOA,
        .pin   = GPIO_PIN_5,
};
 
#define W1DQ_Input()           \
{    \
        GPIO_InitTypeDef GPIO_InitStruct = {0}; \
        GPIO_InitStruct.Pin = W1Dat.pin; \
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \
        GPIO_InitStruct.Pull = GPIO_PULLUP; \
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; \
        HAL_GPIO_Init(W1Dat.group, &GPIO_InitStruct); \
}
 
#define W1DQ_Output()           \
{    \
        GPIO_InitTypeDef GPIO_InitStruct = {0}; \
        GPIO_InitStruct.Pin = W1Dat.pin; \
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \
        GPIO_InitStruct.Pull = GPIO_NOPULL; \
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; \
        HAL_GPIO_Init(W1Dat.group, &GPIO_InitStruct); \
}
 
#define W1DQ_Write(x)    HAL_GPIO_WritePin(W1Dat.group, W1Dat.pin, \
                        (x==1)?GPIO_PIN_SET:GPIO_PIN_RESET)
 
#define W1DQ_Read()     HAL_GPIO_ReadPin(W1Dat.group,  W1Dat.pin)
 
 
/* 主机发送起始信号 */
static void DHT11_StartSignal(void)
{
    W1DQ_Output();
 
    /* 主机拉低 >= 18ms */
    W1DQ_Write(0);
    HAL_Delay(20);
 
    /* 主机拉高 >= 20~40us */
    W1DQ_Write(1);
    delay_us(30);
 
    W1DQ_Input();
}
 
uint8_t DHT11_RespondSignal(void)
{
    uint8_t retry = 0;
 
    /* 总线变为低电平说明从设备发送了响应信号: 80us */
    while( W1DQ_Read() && retry <100)
    {
            retry++;
            delay_us(1);
    }
 
    /* 超时没有收到响应信号 */
    if(retry >= 100)
            return 1;
 
    /* 从设备再把总线拉高表示从设备要发送数据了: 80us */
    retry =    0;
    while( !W1DQ_Read() && retry <100)
    {
            retry++;
            delay_us(1);
    }
 
    /* 超时没有收到数据开始信号 */
    if(retry >= 100)
            return 1;
 
    return 0;
}
 
uint8_t DHT11_ReadBit(void)   //读取一个位
{
    uint8_t retry = 0;
 
    /* 从设备回复的每个位数据以低电平标置开始: 50us */
    while( W1DQ_Read() && retry<100 )
    {
            retry++;
            delay_us(1);
    }
 
    /* 数据位都用高电平表示, 但高电平的长短决定了数据是 1 or 0 */
    retry = 0;
    while( !W1DQ_Read() && retry<100 )
    {
            retry++;
            delay_us(1);
    }
 
    /* 判断数据位是 1(70us) or 0(26~28us)*/
    delay_us(40);
    if( W1DQ_Read() )
            return 1;
    else
            return 0;
}
 
uint8_t DHT11_ReadByte(void)    //读取一个字节返回值位采集值
{
    uint8_t     i,dat;
 
    dat = 0;
    for(i=0; i<8; i++)
    {
          dat <<= 1;
          dat |= DHT11_ReadBit();     //每读取到一个位放到最后一位
    }
 
    return dat;
}
 
int DHT11_SampleData(float *temperature, float *humidity)
{
    uint8_t         humi_H8bit;
    uint8_t         humi_L8bit;
    uint8_t         temp_H8bit;
    uint8_t         temp_L8bit;
    uint8_t         check_sum;
 
    if( !temperature || !humidity )
            return -1;
 
    /* 主机发起起始信号并等到从设备的响应信号 */
    DHT11_StartSignal();
    if( 0 != DHT11_RespondSignal() )
            return -2;
 
    humi_H8bit = DHT11_ReadByte();
    humi_L8bit = DHT11_ReadByte();
    temp_H8bit = DHT11_ReadByte();
    temp_L8bit = DHT11_ReadByte();
    check_sum = DHT11_ReadByte();
 
    if( (humi_H8bit+humi_L8bit+temp_H8bit+temp_L8bit) != check_sum )
         return -3;
 
    *humidity = (humi_H8bit*100 + humi_L8bit) / 100.00;
    *temperature = (temp_H8bit*100 + temp_L8bit) / 100.00;
 
    return 0;
}