基于C51的DHT11(温湿度传感器)编程(详解)

前言
当你点进看这篇博客时,相信对DHT11产品的概述与特性没有任何兴趣,所以跳过那部分,直接上技术活。
1、温湿度如何采集
根据产品说明文档:用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集, 用户可选择读取部分数据.在模式下,DHT11接收到开始信号触发一次温湿度采集, 如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。所以从中我们能提取出三个主要点:

  • 主机开始信号结束后,才会有数据发出,并触发一次信号采集。
  • 发出的是一次40bit数据:
    8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和
  • 读取数据。
    2、时序分析

在这里插入图片描述

  • 如何在代码层面表示出开始信号从发出到结束,开始传送数据
    如图所示:在a处dht=1,在b处dht=0,根据时序图所示,主机至少拉低18ms,我们可以在这里考虑用个延时,比如延时个30ms。然后到C处,dht=1。接下来就是DHT发送响应信号在D处,那我们如何判断到了D处。很明显,上图并没有给显示时间多久到D处,但有一个点我们可以注意到,D处是低电平0。所以我们可以考虑卡个临界点while(dht);同理如何表明进入E处,卡个临界点while(!dht);进入F处卡个临界点
    while(dht);数据开始发送。代码如下:
void DHT11_Start()
{
	dht=1;
	dht=0;
	//延时30ms
	Delay30ms();
	dht = 1;
	while(dht);
	while(!dht);
	while(dht);
}
  • 如何从DHT11读取数据
    高电平表示有效数据,而高电平的长短定了数据位是0或1:
    在这里插入图片描述

DHT发送响应信号后,输出40bit数据,由5部分组成,每一部分为8bit。所以可以从主体上想到用两个for循环。并定义一个临时的tmp变量,用于存储每8bit数据,再将它存入一个数组。
编码如下:

void Read_Data_From_DHT()
{
	int i;
	int j;
	char tmp;
	char flag;
	DHT11_start();
	for(i=0;i<5;i++){
		for(j=0;j<8;j++){
			while(!dht);//判断是否进入高电平状态,高电平长短定了数据位是0还是1.
			Delay40us();
			if(dht == 1){
				flag=1; //数据位是1
				while(dht);//数据位是1,持续70us,所以卡个临界点
			}else{
				flag = 0;//数据位是0
			}
			tmp = tmp << 1;//左移一位
			tmp |= flag; //将一位数据位0或1存入tmp
		}
		datas[i] = tmp;
	}
}

补充说明左移运算符<< 左移会让最高位溢出(也就是把最高位抛弃),向低位补0.
3、代码实现
功能:读取温湿度数据

#include "reg52.h"
#include "intrins.h"
sbit dht = P1^0;
char datas[5];
void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;
	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
void Delay60us()		//@11.0592MHz
{
	unsigned char i;
	i = 25;
	while (--i);
}
void Delay30ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 54;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}
void DHT11_Start()
{
	dht=1;
	dht=0;
	//延时30ms
	Delay30ms();
	dht = 1;
	while(dht);
	while(!dht);
	while(dht);
}
void Read_Data_From_DHT()
{
	int i;
	int j;
	char tmp;
	char flag;
	DHT11_Start();
	for(i=0;i<5;i++){
		//有效数据都是高电平,持续时间不一样,50us读
		for(j=0;j<8;j++){
			while(!dht);
			Delay40us();
			if(dht ==1){
				flag = 1; //模式0或1
				while(dht);
			}else{
				flag = 0;
			}
			tmp = tmp <<1;
			tmp |= flag;
		}
		datas[i] = tmp;
	}
}
void main()
{
	Delay1000ms();
	Delay1000ms();
	while(1){
		Delay1000ms();
		Read_Data_From_DHT();	
	}
}

最后,上述代码运行后,并不会看到结果来验证代码是否正确,可以加上串口代码在电脑端显示,也可以在单片机上加上蓝牙模块或LCD1602模块显示数据。有关方面的代码请参考前面的博客,自行整理一下即可。有问题欢迎留言讨论!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值