24.1 实验内容
通过本实验主要学习以下内容:
- DHT11操作原理
- 单总线GPIO模拟操作原理
24.2 实验原理
HT11是一款已校准数字信号输出的温湿度一体化数字传感器。该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点信号,传输距离可达20米以上。
其具体参数如下:
- 工作电压:3.3V-5.5V
- 工作电流:0.5mA
- 控制方式:单总线
- 输出方式:数字量
- 湿度精度:±5%
- 温度精度:±2℃
- 湿度量程:5%~95%
- 温度量程:-20℃~+60℃
DHT11引脚定义和封装如下图所示
DHT11采用单总线的方式进行数据传输,下面对其通信时序以及传输数据构成进行介绍。
DHT11通信时序可分为:建立连接、数据接收两部分。
建立连接部分时序如下图所示,共包括:主机动作和从机响应两部分。主机动作:DHT11温湿度传感器上电后,数据线处于空闲状态(配置数据线空闲状态为高电平)。主机发送建立连接动作,动作内容为:拉低数据线再拉高数据线(数据线拉低时间>18ms、拉高时间在20-40us之间)然后释放总线。从机响应:从机接收到主句发送的建立连接动作后,先拉低数据线,再拉高数据线,表示连接建立成功(拉低数据线40-50us,拉高数据线40-50us)。
在连接成功建立后,从机发送数据,主机进行数据的接收。数据接收:每一bit数据都以50us低电平开始,通过判断低电平后的高电平时间来决定接收数据的种类。接收高电平时间为26us-28us表示0,接收高电平为70us表示1。当最后一bit数据传送完毕后,从机拉低数据线50us,随后从机释放总线,总线进入空闲状态(高电平)。
主机一次接收40bit数据,共5字节,每个字节的含义如下图所示。从高到低依次为:湿度整数h(0)、湿度小数h(1)、温度整数h(2)、温度小数h(3)、校验和h(4)。检验和等于前四字节数据之和。在一次数据接收完成后,验证h(4)是否等于h(1)+h(2)+h(3)+h(4)。若等式成立则表示数据成功接收,然后进行数据更新,否则不进行数据更新。
DHT11数据格式举例如下。
24.3 硬件设计
DHT11硬件电路图如下所示。DHT11为单信号线通信,因而仅使用了一个IO进行数据通信,且该IO使用了RC进行滤波并采用4.7K进行上拉,保证了数据通信的稳定性,电源地通过100nf电容滤波。
24.4 代码解析
24.4.1 DHT11初始化
DHT11初始化函数实现如下,主要包括DHT11数据通信引脚的初始化以及DHT11 reset和check操作。
C
uint8_t dht11_init(void)
{
driver_gpio_general_init(&DHT11_DA);
/* DHT11_DQ引脚模式设置,开漏输出,上拉, 这样就不用再设置IO方向了, 开漏输出的时候(=1), 也可以读取外部信号的高低电平 */
dht11_reset();
return dht11_check();
}
在该函数中,将DHT11数据引脚配置为开漏模式,使用上可以不用切换引脚模式以及方向,使用比较方便。
dht11_reset()为复位DHT11操作函数,其实现如下,如原理中介绍,首先拉低数据引脚20ms,之后拉高30us,实现对DHT11的复位操作。
C
static void dht11_reset(void)
{
DHT11_DA_OUT(0); /* 拉低DQ */
delay_ms(20); /* 拉低至少18ms */
DHT11_DA_OUT(1); /* DQ=1 */
delay_us(30); /* 主机拉高10~35us */
}
dht11_check()为check DHT11是否正常连接以及工作,其实现如下,其主要通过判断DHT11是否能够响应主机的复位请求操作来判断DHT11是否连接以及工作正常,如果工作正常,该函数返回值为0,否则返回1.
C
uint8_t dht11_check(void)
{
uint8_t retry = 0;
uint8_t rval = 0;
while (DHT11_DA_IN && retry < 100) /* DHT11会拉低83us */
{
retry++;
delay_us(1);
}
if (retry >= 100)
{
rval = 1;
}
else
{
retry = 0;
while (!DHT11_DA_IN && retry < 100) /* DHT11拉低后会再次拉高87us */
{
retry++;
delay_us(1);
}
if (retry >= 100) rval = 1;
}
return rval;
}
24.4.2 DHT11温湿度读取
DHT11温湿度读取函数如下,通过该函数将会连续读取5个字节数据,前两个为湿度数据,之后两个为温度数据,最后一个数据为校验和。读取正确且校验完成后相关湿度数据将会放在对应的形参指定的变量内,该函数将会返回0.
C
uint8_t dht11_read_data(uint8_t *temp, uint8_t *humi)
{
uint8_t buf[5];
uint8_t i;
dht11_reset();
if (dht11_check() == 0)
{
for (i = 0; i < 5; i++) /* 读取40位数据 */
{
buf[i] = dht11_read_byte();
}
if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
{
*humi = buf[0];
*temp = buf[2];
}
}
else
{
return 1;
}
return 0;
}
24.4.3 主函数
DHT11温湿度检测实验主函数如下所示,首先对systick延迟函数进行初始化,之后对DHT11初始化,最后在主循环中没间隔1s读取一次温湿度数据。
C
int main(void)
{
uint8_t temperature;
uint8_t humidity;
delay_init();
while (dht11_init()) /* DHT11初始化 */
{
}
while (1)
{
dht11_read_data(&temperature, &humidity); /* 读取温湿度值 */
delay_ms(1000);
}
}
24.5 实验结果
将DHT11温湿度读取实验烧录到红枫派开发板中,并连接串口,运行程序会,将会每秒钟打印一次温湿度数据。向着DHT11吹口热气,将会观察到打印的温湿度数值都将会增加。
由聚沃科技原创,来源于【红枫派开发板】第二十四讲 DHT11温湿度传感器检测实验 - 苏州聚沃电子科技有限公司 (gd32bbs.com)