【51单片机快速入门指南】6.4:DHT11、DHT22单总线温湿度传感器

STC89C52
Windows 10 20H2
Proteus 8 Frofessional v8.9 SP2
Keil uVision V5.29.0.0
PK51 Prof.Developers Kit Version:9.60.0.0


硬知识

摘自《温湿度模块 DHT11产品手册》、《数字温湿度传感器 DHT22》

  1. 典型应用电路中建议连接线长度短于5m时用4.7K上拉电阻,大于5m时根据实际情况降低上拉电阻的阻值。
  2. 使用3.3V电压供电时连接线尽量短,接线过长会导致传感器供电不足,造成测量偏差。
  3. 每次读出的温湿度数值是上一次测量的结果,欲获取实时数据,需连续读取2次,但不建议连续多次读取传感器,每次读取传感器间隔大于2秒即可获得准确的数据。
  4. 电源部分如有波动,会影响到温度。如使用开关电源,温度就会跳动。传感器上电后,要等待1s以越过不稳定状态,在此期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100nF的电容,用以去耦滤波。

       引脚说明

  1. VDD:供电3.3~5.5V DC
  2. DATA:串行数据,单总线
  3. NC:空脚
  4. GND:接地,电源负极

DHT11

       DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。
在这里插入图片描述
在这里插入图片描述

DHT22

       DHT22数字温湿度传感器是一款含有己校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT22传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。产品为4针单排引脚封装。连接方便,特殊封装形式可根据用户需求而提供。
在这里插入图片描述
在这里插入图片描述

通信协议

       器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线完成。设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许设备在不发送数据时能够释放总线,而让其它设备使用总线;单总线通常要求外接一个约4.7kΩ的上拉电阻,这样,当总线闲置时,其状态为高电平。由于它们是主从结构,只有主机呼叫从机时,从机才能应答,因此主机访问器件都必须严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。
       DATA用于微处理器与传感器之间的通讯和同步,采用单总线数据格式,一次传送40位数据,高位先出。
数据格式:
8bit湿度高位数据+8bit湿度低位数据+8bit温度高位数据+8bit温度低位数据+8bit校验位。
校验位数据定义:
       校验位等于8bit湿度高位数据+8bit湿度低位数据+8bit温度高位数据+8bit温度低位数据所得结果的末8位
在这里插入图片描述
数据时序图
       用户主机(MCU)发送一次开始信号后,传感器从低功耗模式转换到高速模式,待主机开始信号结束后,传感器发送响应信号,送出40bit的数据,并触发一次信采集。
在这里插入图片描述

读取步骤

  1. 上电后(上电后要等待1S以越过不稳定状态,在此期间不能发送任何指令),测试环境温湿度数据,并记录数据,同时传感器的DATA数据线由上拉电阻拉高一直保持高电平;此时传感器的DATA引脚处于输入状态,时刻检测外部信号。
  2. 微处理器的I/O设置为输出同时输出低电平,且低电平保持时间不能小于18ms(最大不得超过30ms),然后微处理器的I/O设置为输入状态,由于上拉电阻,微处理器的I/O即传感器的DATA数据线也随之变高,等待传感器作出回答信号。
    在这里插入图片描述
  3. 传感器的DATA引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后传感器的DATA引脚处于输出状态,输出83微秒的低电平作为应答信号,紧接着输出87微秒的高电平通知外设准备接收数据,微处理器的I/O此时处于输入状态,检测到I/O有低电平(传感器回应信号)后,等待87微秒的高电平后的数据接收
    在这里插入图片描述
  4. 由传感器的DATA引脚输出40位数据,微处理器根据I/O电平的变化接收40位数据,位数据"0”的格式为:54微秒的低电平和23-27微秒的高电平,位数据"1"的格式为:54微秒的低电平加68-74微秒的高电平。
    在这里插入图片描述
  5. 结束信号:传感器的DATA引脚输出40位数据后,继续输出低电平54微秒后转为输入状态,由于上拉电阻随之变为高电平。但传感器内部重测环境温湿度数据,并记录数据,等待外部信号的到来。
    在这里插入图片描述

数据解读

DHT11

在这里插入图片描述

DHT22

在这里插入图片描述

示例程序

DHT11_22.c

#include "DHT11_22.h"

void delay_ms(int i);
void delay_10us(uint8_t n);

DHT_data DHT_Data = {0};

void DHT_Read(DHT_data *dht_data)
{
    uint8_t DHT_timeout_count, i, j;
	uint8_t data_temp[6];
	uint8_t DHT_Byte;
    //主机拉低18~30ms
    DHT_IO_L();
    delay_ms(20);
    DHT_IO_H();
    //总线由上拉电阻拉高 主机延时50us
    delay_10us(5);
    //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
    if(!DHT_IO_read())		 
    {
        //判断从机是否发出 80us 的低电平响应信号是否结束
        DHT_timeout_count = 0;
        while(!DHT_IO_read())
        {
            delay_10us(1);
            if(++DHT_timeout_count >= 10)
                return;
        }
        //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
        DHT_timeout_count = 0;
        while(DHT_IO_read())
        {
            delay_10us(1);
            if(++DHT_timeout_count >= 10)
                return;
        }
		for(i = 0; i < 5; ++i)
		{
			for(j = 0, DHT_Byte = 0; j < 8; ++j)
			{
				DHT_Byte <<= 1;
				DHT_timeout_count = 0;
				while(!DHT_IO_read())
				{
					delay_10us(1);
					if(++DHT_timeout_count >= 10)
					{
						DHT_Byte = 0;
						break;
					}	
				}
				delay_10us(3);	//跳过数据0的时间段,只检测数据为1时的电平
				if(DHT_IO_read())
				{
					++DHT_Byte;
					while(DHT_IO_read())
					{
						delay_10us(1);
						if(++DHT_timeout_count >= 10)
						{
							DHT_Byte = 0;
							break;
						}	
					}
				}
			}
			data_temp[i] = DHT_Byte;
		}
		for(i = 0, data_temp[5] = 0; i < 4; ++i)
			data_temp[5] += data_temp[i];
		if(data_temp[5] == data_temp[4])	//数据解读
		{
			#ifdef DHT11
				dht_data->RH = data_temp[0] + (data_temp[1] & 0x0f)/10.;
				dht_data->Temp = data_temp[2] + (data_temp[3] & 0x0f)/10.;
				if(data_temp[3] & 0x80)
					dht_data->Temp *= -1;
			#endif
			#ifdef DHT22
				dht_data->RH = ((int16_t)data_temp[0] << 8 | data_temp[1])/10.;
				dht_data->Temp = ((int16_t)(data_temp[2] & 0x7f) << 8 | data_temp[3])/10.;
				if(data_temp[2] & 0x80)
					dht_data->Temp *= -1;
			#endif
		}
    }
}

DHT11_22.h

#ifndef DHT11_22_H
#define DHT11_22_H

#include <STC89C5xRC.H>
#include <stdint.h>

#define DHT11
//#define DHT22

typedef struct 
{
	float RH;
	float Temp;
} DHT_data;

#define DHT_IO_H() {P00=1;}
#define DHT_IO_L() {P00=0;}
#define DHT_IO_read() P00

extern DHT_data DHT_Data;

void DHT_Read(char *Str);

#endif

测试程序

       stdint.h【51单片机快速入门指南】1:基础知识和工程创建
       串口部分见【51单片机快速入门指南】3.3:USART 串口通信
       定时器的介绍和配置源码见【51单片机快速入门指南】3.2:定时器/计数器

       在头文件中选择使用的型号:
在这里插入图片描述

main.c

#include <STC89C5xRC.H>
#include "intrins.h"
#include "stdint.h"
#include "USART.h"
#include "TIM.h"
#include "DHT11_22.h"

void Delay1ms()		//@22.1184MHz
{
	unsigned char i, j;

	_nop_();
	i = 4;
	j = 146;
	do
	{
		while (--j);
	} while (--i);
}


void delay_ms(int i)
{
	while(i--)
		Delay1ms();
}

uint8_t TIM0_Counter = 0;
void delay_10us(uint8_t n)
{
	TL0 = TH0;
	TIM0_Counter = n;
	while(TIM0_Counter > 1);
}

void main(void)
{
	USART_Init(USART_MODE_1, Rx_ENABLE, STC_USART_Priority_Lowest, 22118400, 115200, DOUBLE_BAUD_ENABLE, USART_TIMER_1);
	Timer_Init(TIMER_0, TIMER_MODE_2, GATE_DISABLE, CLK_Internal, 22118400, 10, STC_TIM_Priority_Highest);	//定时器配置为10us中断一次,8位重装载

	delay_ms(1500);
	while(1)
	{	
		DHT_Read(&DHT_Data);
		printf("%f %f\r\n", DHT_Data.RH, DHT_Data.Temp);
		delay_ms(2000);
	}
}

实验现象

DHT11

在这里插入图片描述

DHT22

在这里插入图片描述

版权声明:本文为CSDN博主「乙酸氧铍」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44457994/article/details/122501928

生成海报
点赞 0

乙酸氧铍

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

基于AT89C51的蓝牙循迹避障小车

基于AT89C51的蓝牙循迹避障小车 对标题的解读: AT89C51:在下使用的是STC89C52这款芯片,c51和c52在新手入门阶段是一样的,所以不必纠结于到底是哪个名字&#xff

51单片机+ LCD1602+PCF8574转IIC接口+DHT11数据显示

51单片机+ LCD1602+PCF8574转IIC接口+DHT11数据显示 在做这个实验的时候又一次被自己的不注意,掉坑里面去了,调试了好久都不出数据,结果在延时函数和引脚定义上被自己坑了一把。希望大家在写代码的时候多加注意。 LCD1602

51单片机温度报警

器件:   基于普中51A2单片机 用到的模块:LCD1602、蜂鸣器、4个独立按键、DS18B20温度传感器。现象说明: LCD1602可以显示两行数据,每行可以显示16个字符&#xff