STM32驱动单总线设备DHT11测量温、湿度

提示:上次更新@STM32F103驱动单总线的DS18B20测量温度(含多点测量)


前言

温度和湿度是环境因素中非常重要的两个参数。它们对于人类的健康和舒适感、生物的生长发育、物体的保存和保护等都起着重要的影响。本文基于STM32驱动单总线设备DHT11来测量环境的温湿度,编程的重点在于DHT11的时序。


一、DHT11的相关特性

1.测量参数

采样周期间隔>=1S.
在这里插入图片描述

2.典型电路

建议连接线长度短于20m时使用5kΩ上拉电阻,大于20m时根据实际情况增加适合的上拉电阻。这里的VDD=3.3V,DATA引脚接单片机的PA5引脚。
在这里插入图片描述

3.串行接口(单线双向)

使用单总线的通讯方式与MCU进行数据的传输,当MCU给DHT11发送起始信号时,DHT11响应后开始采集数据,采集完成后,一次性向MCU发送40位完成的数据,并且数据是 高位先出 的。
数据格式:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和。
其中数据传输正确时的校验和等于“8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据”所得结果的末8位。

二、使用步骤

1.相关的头文件代码

#ifndef __DHT11_H
#define __DHT11_H

#include "stm32f10x.h"
#include "delay.h"

#define DHT11_IO     GPIO_Pin_5
#define DHT11_PORT   GPIOA
#define DHT11_SET_IO(x)  (x) ? GPIO_SetBits(DHT11_PORT, DHT11_IO) : GPIO_ResetBits(DHT11_PORT, DHT11_IO)
#define DHT11_READ_IO     GPIO_ReadInputDataBit(DHT11_PORT, DHT11_IO)

extern u8 dht_data[5];
extern u8 wendu;
extern u8 shidu;

void rst_dht11(void);
u8 check_dht11(void);
u8 read_dht_bit(void);
u8 read_dht_byte(void);
u8 read_dht_data(void);
#endif

2.时序

在这里插入图片描述

2.1 复位和检测响应时序

在这里插入图片描述

//作用:初始化dht11的io为输出
//无返回值
//无输入参数
void init_dht11_out(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能A端口时钟
	GPIO_InitStructure.GPIO_Pin = DHT11_IO;	//GPIOA5
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
 	GPIO_Init(DHT11_PORT, &GPIO_InitStructure);	  //初始化GPIOA5
	
 	GPIO_SetBits(DHT11_PORT, DHT11_IO);	
}

//作用:初始化dht11的io为输入
//无返回值
//无输入参数
void init_dht11_in(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能A端口时钟
	GPIO_InitStructure.GPIO_Pin = DHT11_IO;	//GPIOA5
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 		 //浮空输入
	
 	GPIO_Init(DHT11_PORT, &GPIO_InitStructure);	  //初始化GPIOA5
}


void rst_dht11(void)	//发送起始信号以复位
{
	init_dht11_out();
	DHT11_SET_IO(0);
	delay_ms(20);
	DHT11_SET_IO(1);
	delay_us(30);
}

u8 check_dht11(void)	//检查响应
{
	u8 retry = 0;
	init_dht11_in();
	while(DHT11_READ_IO == 1)	//等待dht低电平响应
	{
		delay_us(1);
		retry ++;
		if(retry >= 200)	return 1;  //等待时间过长
	}
	retry = 0;
	while(DHT11_READ_IO == 0)	//等待拉高电平,准备发送数据
	{
		delay_us(1);
		retry ++;
		if(retry >= 200)	return 1;  //等待时间过长
	}
	retry = 0;
	while(DHT11_READ_IO == 1)	//等待dht低电平响应,等待发0/1的共同电平到来
	{
		delay_us(1);
		retry ++;
		if(retry >= 200)	return 1;  //等待时间过长
	}
	return 0;
}

2.2 读1和读0时序

1.读0时序
在这里插入图片描述
2.读1时序
在这里插入图片描述

读取数据的代码如下,注意,每读完一次1都要等待高电平时序(读1的电平持续时间约为70us),结束才能读取下一位数据。

u8 read_dht_bit(void)	//只读一位0/1
{
	u8 retry = 0; 
	while(DHT11_READ_IO == 0)	//等待发送0/1的低电平结束
	{
		delay_us(1);
		retry ++;
		if(retry >= 200)	break;
	}
	delay_us(40);	//排除0信号,检测1信号
	if(DHT11_READ_IO)	//是1信号就返回1
		return 1;
	else 
		return 0;	//0信号返回0
	return 0;
}

u8 read_dht_byte(void)	//读取DHT的1个字节数据
{
	u8 data = 0, i;
	for(i = 0; i < 8; i ++)
	{
		if(read_dht_bit())
		{
			data |= (1 << (7 - i));	//高位先出,就将读到的数据按序移到相应位置
			while(DHT11_READ_IO == 1); //	等待读1的高电平结束
		}
	}
	return data;
}

3. DHT11温、湿度的读取操作

主机(MCU)发送复位信号后,DHT11进入温、湿度采集模式,并行MCU发送响应信号,温湿度采集完成后一次性完整地向MCU发送40bit的数据。在温、湿度等数据读取时采用数组来存放相关的数据,并进行数据的校验和检验,如果校验和正确,就显示一次数据。具体的函数代码如下:

//作用:读取温、湿度函数,温度和湿度的数值分别传输给wendu、shidu
//返回值:复位无响应返回1,校验和错误返回2,正常返回0.
//无输入参数
u8 read_dht_data(void)	//读取5个字节的数据,包含温、湿度和校验位
{
	u8 reack = 1, i;
	rst_dht11();	//主机给起始信号
	reack = check_dht11();	//检查dht的响应
	if(reack == 0)	//有响应
	{
		for(i = 0; i < 5; i ++)
		dht_data[i] = read_dht_byte(); 
	}
	else //无响应返回1
		return 1;
	
	if(dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3] == dht_data[4])	//和校验
	{
		wendu = dht_data[2];
		shidu = dht_data[0];
	}
	else 	//校验和不通过返回2
		return 2;
	return 0;
}

实物效果及总结

单总线的设备通常要根据时序图将复位、读取响应、读取一位数据、读取一个字节、最终读取数据。有些设备(比如上次更新的DS18B20检测温度)还需要写字节操作,并根据指令发送十六进制的指令进行使用。在写时序时一定要严格按照时序图的延时时间编写程序,通常使用while()判断电平来确定电平时序的却换,为了稳妥些(防止MCU卡死在时序函数的while死循环中),应该规定一定超时时间退出时序的死循环。
在这里插入图片描述

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先需要连接STM32DHT11传感器,DHT11的数据线连接到STM32的GPIO口。接下来可以使用STM32的库函数来读取DHT11传感器数据。 以下是一个基本的示例代码: ```c #include "stm32f10x.h" #define DHT11_PORT GPIOA #define DHT11_PIN GPIO_Pin_0 void delay_us(uint32_t us) { SysTick->LOAD = 9 * us; SysTick->CTRL = 0x01; while (!(SysTick->CTRL & 0x10000)); SysTick->CTRL = 0x00; } void DHT11_start(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = DHT11_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11_PORT, &GPIO_InitStructure); GPIO_ResetBits(DHT11_PORT, DHT11_PIN); delay_us(18000); GPIO_SetBits(DHT11_PORT, DHT11_PIN); delay_us(40); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(DHT11_PORT, &GPIO_InitStructure); } uint8_t DHT11_read_bit(void) { uint8_t retry = 0; while (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == RESET) { retry++; if (retry > 100) return 0; delay_us(1); } retry = 0; while (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == SET) { retry++; if (retry > 100) return 0; delay_us(1); } if (retry > 50) return 1; else return 0; } uint8_t DHT11_read_byte(void) { uint8_t i, j, byte = 0; for (i = 0; i < 8; i++) { j = DHT11_read_bit(); byte <<= 1; byte |= j; } return byte; } void DHT11_read_data(uint8_t *temp, uint8_t *humi) { uint8_t i; uint8_t data[5]; DHT11_start(); if (DHT11_read_bit() == 0) { *humi = 100; *temp = 100; return; } for (i = 0; i < 5; i++) data[i] = DHT11_read_byte(); if ((data[0] + data[1] + data[2] + data[3]) == data[4]) { *humi = data[0]; *temp = data[2]; } else { *humi = 0; *temp = 0; } } int main(void) { uint8_t temp, humi; while (1) { DHT11_read_data(&temp, &humi); printf("Temperature: %d°C, Humidity: %d%%\n", temp, humi); delay_ms(2000); } } ``` 此代码通过DHT11传感器读取度和湿度,然后将其打印到串口终端上。需要注意的是,由于DHT11传感器的数据传输是比较慢的,因此需要适当的延时来等待数据传输完成。另外,由于本例是在STM32F103C8T6开发板上编写的,因此需要根据自己使用的STM32型号,调整GPIO口的配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值