DHT11(温湿度检测)

 1. 介绍

DHT11是一款含有已校准数字信号输出的温湿度复合传感器,采用了自主研发的集成式数字温湿度元件,应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。DHT11传感器内包含一个温湿度测量元件和一个高性能MCU

更多详细介绍见《DHT11 中文资料 ------ C语言例程》

2. 传感器原理

(1) 原理图
DQ ------ PG9


单总线上必须有一个上拉电阻(R26)以实现单总线闲置时,其处于高电平状态


(2) 由参考资料《DHT11中文资料 ----- C语言例程》可知

数据格式:

一次完整的数据传输为40bit,高位先发

数据格式:8bit 湿度整数数据 + 8bit 湿度小数数据
         + 8bit 温度整数数据 + 8bit 温度小数数据
         + 8bit 校验和

数据传输正确时校验和数据等于 “8bit 湿度整数数据 + 8bit 湿度小数数据
                           + 8bit 温度整数数据 + 8bit 温度小数数据” 所得结果的未8位

工作时序:

a. 数字0信号表示方法


b. 数字1信号表示方法

(3) DHT11温湿度获取流程

GPIO:通信规则

1. 起始信号
	    STM32 通过 DHT11_DATA_GPIO 输出高 ---> 低电平 持续时间>18ms

2. 等待响应
        STM32 先将引脚电平拉高 DHT11_DATA_GPIO 切换输入模式,
延时20-40us 读取引脚上的电平状态,
        如果引脚电平为低电平则DHT11响应

3. 响应信号
	    DHT11收到启动信号,发送80us的低电平响应信号

4. 准备输出
        DHT11会将 DHT11_DATA_GPIO 拉高 80us的时间

5. 温湿度数据发送 40bit  高位先发
	    湿度整数最开始的8bit
	    0:50us低电平 26-28us高电平
	    1:50us低电平 70us高电平

6. 结束输出
    当最后 1bit 数据抄送完毕后,DHT11 拉低总线50us,随后总线由上拉电阻拉高进入空闲状态

3. 实验要求

a. 对温度湿度的测量

b. 通过串口将温度、湿度输出

c. 设置温度的阈值,通过按键进行设置 

        ===> 按 按键1 温度阈值 +1,按 按键2 温度阈值 -1  ===> 中断控制

d. 当温度超过了阈值,LED灯常亮,蜂鸣器报警

e. 按键控制串口输出当前的信息

        ===> 按一次 按键3 打印当前温度的阈值和当前温湿度  ===> 中断控制

4. 程序设计

DHT11.h

#ifndef __DHT11_H__
#define __DHT11_H__

#include "stm32f4xx.h"
#include "systick.h"

// DHT11需要配置的时钟外设
#define DHT11_DATA_RCC_AHB1Periph  RCC_AHB1Periph_GPIOG
// 使能时钟
#define DHT11_DATA_Clock()   RCC_AHB1PeriphClockCmd(DHT11_DATA_RCC_AHB1Periph, ENABLE)

// DQ ===> PG9
#define DHT11_DATA_GPIO   GPIOG
#define DHT11_DATA_Pin    GPIO_Pin_9

// DHT11_DATA_IDLE 设置空闲状态(IDLE) ===> 高电平
#define DHT11_DATA_IDLE()    GPIO_SetBits(DHT11_DATA_GPIO, DHT11_DATA_Pin)

// 往总线输出高电平
#define DHT11_DATA_SET()	 DHT11_DATA_IDLE()
// 往总线输出低电平
#define DHT11_DATA_RESET()   GPIO_ResetBits(DHT11_DATA_GPIO, DHT11_DATA_Pin)

// 读取总线上的电平状态 
#define DHT11_DATA_STATE()  GPIO_ReadInputDataBit(DHT11_DATA_GPIO, DHT11_DATA_Pin)

// data线设置为输出
void DHT11_DATA_Mode_OUT(void);

// data线设置为输入
void DHT11_DATA_Mode_IN(void);

// 发送开始信号
void DHT11_Start(void);

// 每次8bit接收数据,通过返回值返回,高位先发
uint8_t DHT11_Get8Bit(void);

/*
	获取温度和湿度
		@humi:湿度   
		@temp:温度
		@返回值:成功返回0,失败返回-1
*/
int DHT11_GetData(uint8_t *humi, uint8_t *temp);

#endif

DHT11.c

#include "DHT11.h"

// data线设置为输出模式
void DHT11_DATA_Mode_OUT(void) {

	// 初始化配置GPIO(完成GPIO的4个配置寄存器的赋值)
	
	// a. 定义GPIO初始化信息结构体
	GPIO_InitTypeDef g;

	// b. 根据配置需要,对结构体成员赋值
	g.GPIO_Pin = DHT11_DATA_Pin; // 几号引脚
	g.GPIO_Mode = GPIO_Mode_OUT; // 输出模式
	g.GPIO_Speed = GPIO_Speed_2MHz; // 2MHz
	g.GPIO_OType = GPIO_OType_PP; // 输出类型
	g.GPIO_PuPd = GPIO_PuPd_NOPULL; // 无上拉也无下拉
	
	// c. 根据结构体信息,完成GPIO配置
	GPIO_Init(DHT11_DATA_GPIO, &g);
}

// data线设置为输入模式
void DHT11_DATA_Mode_IN(void) {
	
	// 初始化配置GPIO(完成GPIO的4个配置寄存器的赋值)
	
	// a. 定义GPIO初始化信息结构体
	GPIO_InitTypeDef g;
	
	// b. 根据配置需要,对结构体成员赋值
	g.GPIO_Pin = DHT11_DATA_Pin; // 几号引脚
	g.GPIO_Mode = GPIO_Mode_IN; // 输入模式
	g.GPIO_PuPd = GPIO_PuPd_NOPULL; // 无上拉也无下拉
	
	// c. 根据结构体信息,完成GPIO配置
	GPIO_Init(DHT11_DATA_GPIO ,&g);
}

/*
GPIO:通信规则
	1.起始信号
		STM32 通过 DHT11_DATA_GPIO  输出高->低电平 持续时间>18ms
	2.等待响应
		STM32 先将引脚电平拉高 DHT11_DATA_GPIO 切换输入模式,
延时20-40us 读取引脚上的电平状态,
			如果引脚电平为低电平则DHT11响应
	3.响应信号
		DHT11收到启动信号,发送80us的低电平响应信号
	4.准备输出
		DHT11会将 DHT11_DATA_GPIO  拉高 80us的时间
	5.温湿度数据发送 40bit  高位先发
		湿度整数最开始的8bit
		0:50us低电平 26-28us高电平
		1:50us低电平 70us高电平
	6.结束输出 
		当最后 1bit 数据抄送完毕后,DHT11 拉低总线50us,随后总线由上拉电阻拉高进入空闲状态
*/
// 发送开始信号
void DHT11_Start(void) {

	// data线设置为输出
	DHT11_DATA_Mode_OUT();
	// 将数据线设置为空闲状态
	DHT11_DATA_IDLE();

	delay_ms(1);
	
	// 发送开始信号
	DHT11_DATA_RESET();
	delay_ms(19);
}

// 每次8bit接收数据,通过返回值返回,高位先发
uint8_t DHT11_Get8Bit(void) {

	uint8_t x = 0;

	// 高位先发
	for (int i = 7; i >= 0; i--) {

		// 跳过最开始的50us
		while (DHT11_DATA_STATE() == RESET);

		delay_us(30);
		
		// 30us之后 DATA引脚还是高电平,意味着这个bit是1
		if (DHT11_DATA_STATE() == SET) {
			
			x |= (1 << i);

			// 跳过剩下的高电平时间
			while (DHT11_DATA_STATE() == SET);
		}
	}
	
	return x;
}

/*
	获取温度和湿度
		@humi:湿度   
		@temp:温度
		@返回值:成功返回0,失败返回-1
*/
int DHT11_GetData(uint8_t *humi, uint8_t *temp) {

	// 使能时钟
	DHT11_DATA_Clock();

	// 1. 发送起始信号
	DHT11_Start();
	
	// 2. 等待响应
	DHT11_DATA_SET(); // 拉高
 	DHT11_DATA_Mode_IN(); // 切换为输入模式
	delay_us(40);
	
	// 如果读取到的引脚电平状态为低电平 则表示dht11发送了响应信号
	if (DHT11_DATA_STATE() == RESET) {

		// 跳过响应时间 80us
		while (DHT11_DATA_STATE() == RESET);

		// 3. DHT11 准备输出阶段 DATA线会被拉高80us
		while (DHT11_DATA_STATE() == SET);
		
		// 4. 接收湿度、温度 I整数 F小数 par校验和
		uint8_t humiI, humiF, tempI, tempF, par;
		humiI = DHT11_Get8Bit();
		humiF = DHT11_Get8Bit();
		tempI = DHT11_Get8Bit();
		tempF = DHT11_Get8Bit();
		par   = DHT11_Get8Bit();
		
		// 5. 验证数据
		if ((uint8_t)(humiI + humiF + tempI + tempF) != par) {
			return -1;
		}

		*humi = humiI;
		*temp = tempI;

		return 0;
	}
	
	return -1;
}

main.c

#include "stm32f4xx.h"

#include "systick.h"
#include "DHT11.h"
#include "usart.h"
#include "stdio.h"

int main(void) {
	
	Usart1_Init(9600);
	
	// 湿度,温度
	uint8_t humi = 0, temp = 0;
	
	while (1) {
		if (DHT11_GetData(&humi, &temp) == -1) {
			printf("DHT11 Getdata failed\r\n");
			// 延时 2s
			delay_ms(2000);
			continue;
		}
		printf("humi = %d, temp = %d\r\n", humi, temp);
		
		// 延时 2s
		delay_ms(2000);
	}
}
  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值