4. 51 测量空气的温度和湿度(51单片机 + DHT11温湿度 + LCD1602显示)

DHT11温湿度相关介绍

DHT11产品概述

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

测量范围

型号测量范围测湿精度测温精度分辨力封装
DHT1120-90%RH 0-50℃±5%RH±2℃14 针单排直插

接口说明

建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使 用合适的上拉电阻

在这里插入图片描述

电源引脚

DHT11的供电电压为 3-5.5V传感器上电后,要等待 1s 以越过不稳定状态在此 期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100nF 的电容,用以去 耦滤波。

串行接口 (单线双向)

DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次 通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数 部分用于以后扩展,现读出为零。操作流程如下:一次完整的数据传输为40bit,高位先出。

数据格式:8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和 数据传送正确时校验和数据等于8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据”所得结果的末8位。

相关时序及代码

用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集,采集数据后转换到低速模式。

在这里插入图片描述

总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号主机发送开始信号结束后,延时等待20-40us后,读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可,总线由上拉电阻拉高。

在这里插入图片描述

用代码实现上述时序图(起始信号):

DHT11_Data = 1; //先高电平维持一小段时间
Delay30us();//维持30us
DHT11_Data = 0; //拉低电平至少18ms
Delay20ms(); //这里给了20ms
DHT11_Data = 1;	//拉高电平维持20-40us 
Delay30us(); //我这里维持30us

DHT11_Data=1; //拉高电平等待DHT低电平响应

if(DHT11_Data == 0) //判断DHT是否响应
{
	while(!DHT11_Data); //等待DHT80us低电平响应信号过去
	while(DHT11_Data); //等待DHT80us高电平信号过去
		
	/*然后就开始接收DHT11温湿度数据*/

}

总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高80us,准备发送数据,每一bit数据都以50us低电平时隙开始高电平的长短决定了数据位是0还是1。格式见下面图示。如果读取响应信号为高电平,则DHT11没有响应,请检查线路是否连接正常。当最后 1bit 数据传送完毕后,DHT11拉低总线 50us,随后总线由上拉电阻拉高进入空闲状态。

在这里插入图片描述

总共数据为40位 8位的湿度整数部分,8位的湿度小数部分,8位的温度整数部分,8位的温度小数部分。8位的校验位(检测是否接收的是正确数据)

下面代码是获取每8位的代码

unsigned char DHT11_Rec_Byte()
{
		unsigned char i = 0;
		unsigned char Data;
		
		for(i=0;i<8;i++)
		{
				while(!DHT11_data); //等待DHT11 50us低电平过去,
				Delay30us(); 延时大概30us 如何还是高电平 则为1 
				
				Data<<=1; //左移一位 因为数据是从高位开始传
				
				if(DHT11_data==1)
				{
						Data+=1;
				}
				
				while(DHT11_data); //等待DHT拉低 准备下一位开始
		}
		
		return Data;
}

接收每位的代码

void DHT11_Receive()
{
		unsigned int R_H,R_L,T_H,T_L;
		unsigned char RH,RL,TH,TL,CHECK;
		
		DHT11_Start(); //主机发送信号
		DHT11_data = 1; //拉高电平
		
		if(DHT11_data==0) //判断DHT是否进入响应
		{
				while(DHT11_data==0); //等待从机80us低电平响应信号过去
				while(DHT11_data==1); //等待从机80us高电平信号过去
				
				R_H = DHT11_Rec_Byte(); //湿度整数部分
				R_L = DHT11_Rec_Byte(); //湿度小数部分
				T_H = DHT11_Rec_Byte(); //温度整数部分
				T_L = DHT11_Rec_Byte(); //温度小数部分
				CHECK = DHT11_Rec_Byte(); //校验位
				
				DHT11_data=0; //当最后一bit数据传送完毕后,DHT11拉低总线 50us
				Delay55us(); //这里延时55us
				DHT11_data=1; //随后总线由上拉电阻拉高进入空闲状态。
				
				if((R_H+R_L+T_H+T_L) == CHECK) //校验接收到的数据是否正确
				{
						RH = R_H;
						RL = R_L;
						TH = T_H;
						TL = T_L;
				}
		}
		
		rec_data[0] = RH;
		rec_data[1] = RL;
		rec_data[2] = TH;
		rec_data[3] = TL;
}

代码整合

DHT11.c

#include <REGX52.H>
#include "DHT11.h"
#include "delay.h"

sbit DHT11_data = P3^6;

unsigned int rec_data[4];
unsigned char rec_data_lcd0[6];
unsigned char rec_data_lcd1[6];
unsigned char rec_data_lcd2[6];
unsigned char rec_data_lcd3[6];

/*
void DHT11_delay_us(unsigned char n)
{
		while(--n);
}

void DHT11_delay_ms(unsigned int z)
{
		unsigned int i,j;
		for(i=z;i>0;i++)
			for(j=110;j>0;j--);
}
*/

void DHT11_UART_Init()
{
		SCON = 0x40;
		REN  = 1;
		
		TMOD = 0x20;
		TH1  = 0xF3;
		TL1  = 0xF3;
		
		TI   = 1;
		TR1  = 1;
}

void DHT11_Start()
{
		DHT11_data = 1;
		Delay30us();
		
		DHT11_data = 0;
		Delay20ms();
		
		DHT11_data = 1;
		Delay30us();
}

unsigned char DHT11_Rec_Byte()
{
		unsigned char i = 0;
		unsigned char Data;
		
		for(i=0;i<8;i++)
		{
				while(!DHT11_data);
				Delay30us();
				
				Data<<=1;
				
				if(DHT11_data==1)
				{
						Data+=1;
				}
				
				while(DHT11_data);
		}
		
		return Data;
}

void DHT11_Receive()
{
		unsigned int R_H,R_L,T_H,T_L;
		unsigned char RH,RL,TH,TL,CHECK;
		
		DHT11_Start();
		DHT11_data = 1;
		
		if(DHT11_data==0)
		{
				while(DHT11_data==0);	   //等待从机80us低电平响应信号过去
				while(DHT11_data==1);
				
				R_H = DHT11_Rec_Byte();
				R_L = DHT11_Rec_Byte();
				T_H = DHT11_Rec_Byte();
				T_L = DHT11_Rec_Byte();
				CHECK = DHT11_Rec_Byte();
				
				DHT11_data=0;
				Delay55us();
				DHT11_data=1;
				
				if((R_H+R_L+T_H+T_L) == CHECK)
				{
						RH = R_H;
						RL = R_L;
						TH = T_H;
						TL = T_L;
				}
		}
		
		rec_data[0] = RH;
		rec_data[1] = RL;
		rec_data[2] = TH;
		rec_data[3] = TL;
}

DHT11.h

#ifndef _DHT11_h_
#define _DHT11_h_

void DHT11_delay_us(unsigned char n);
void DHT11_delay_ms(unsigned int z);
void DHT11_UART_Init(void);
void DHT11_Start(void);
unsigned char DHT11_Rec_Byte(void);
void DHT11_Receive(void);

#endif

LCD1602.c

在51分栏第3篇中可以找到 3. 51——LCD1602显示 字符、字符串、数字

LCD1602.h

在51分栏第3篇中可以找到 3. 51——LCD1602显示 字符、字符串、数字

main.c

#include "regx52.h"
#include "intrins.h"
#include "LCD1602.h"
#include "DHT11.h"
#include <stdio.h>

extern unsigned int rec_data[4];
extern unsigned char rec_data_lcd0[6];
extern unsigned char rec_data_lcd1[6];
extern unsigned char rec_data_lcd2[6];
extern unsigned char rec_data_lcd3[6];

void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void main()
{
		DHT11_UART_Init();
		LCD_Init();
		LCD_ShowString(1,1,"Humi:");
		LCD_ShowString(2,1,"Temp:");
		
		while(1)
		{
				Delay1000ms();;
				DHT11_Receive();
				
				sprintf(rec_data_lcd0,"%d",rec_data[0]);
				sprintf(rec_data_lcd1,"%d",rec_data[1]);
				sprintf(rec_data_lcd2,"%d",rec_data[2]);
				sprintf(rec_data_lcd3,"%d",rec_data[3]);
				
				Delay100ms();
				
				LCD_ShowString(1,6,rec_data_lcd0);
				LCD_ShowString(1,8,".");
				LCD_ShowString(1,9,rec_data_lcd1);
				LCD_ShowString(1,15,"%");
				
				LCD_ShowString(2,6,rec_data_lcd2);
				LCD_ShowString(2,8,".");
				LCD_ShowString(2,9,rec_data_lcd3);
				LCD_ShowString(2,15,"C");
				
//				printf("Humi:%d.%d \n",rec_data[0],rec_data[1]); //通过串口
//				printf("Temp:%d.%d °C\n",rec_data[2],rec_data[3]);

		}
}

效果展示

在这里插入图片描述

由于经费不足,没钱买可变电阻接V0,只能从特殊角度观察到!哈哈哈,不好意思!

在这里插入图片描述

如果觉得这篇文章对你有用。欢迎大家点赞、评论哈哈哈!!!
需要整个工程代码,欢迎大家打赏,评论区留上你的邮箱 or vx or qq。o( ̄︶ ̄)o

在这里插入图片描述
在这里插入图片描述

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值