由C51单片机,LCD1602显示屏,DHT11温湿度传感器,实现实时温湿度显示

        本程序由主函数main,和DHT11.c和DHT.h,这三个文件组成。关于DHT11的函数全部定义在.C文件中。.h文件为函数声明。LCD1602和DELAY的头文件在此就不展示了(太常见啦)

1.主函数

#include <REGX52.H>
#include "DHT11.H"
#include "LCD1602.H"

unsigned char Humidity_H,Humidity_L,Temprature_H,Temprature_L,check;

void main()
{
	LCD_Init();
	DHT11_Init();   //该初始化只是一个延时1秒的函数,DHT11在开始一秒为不稳定状态,此间不能通信
	LCD_ShowString(1,1,"Humidity:");//湿度显示
	LCD_ShowString(2,1,"Temprature:");//温度显示
	LCD_ShowString(1,12,"%");//湿度后要追加显示百分号
	LCD_ShowString(2,14,".");//显示温度的小数点

	while(1)
	{	  
		DHT11_start();
	    Humidity_H=DHT11_receiveByte();
		Humidity_L=DHT11_receiveByte();//此版本的DHT11,湿度小数部分始终为0,以下不予以显示
		Temprature_H=DHT11_receiveByte();
		Temprature_L=DHT11_receiveByte();
		check=DHT11_receiveByte();
		
		LCD_ShowNum(1,10,Humidity_H,2);
		LCD_ShowNum(2,12,Temprature_H,2);
		LCD_ShowNum(2,15,Temprature_L,1);
		LCD_ShowNum(1,14,check,3);        //check 为校验位,其值为前四个数据之和
	}

}

                               敲重点啦!!!  以下为结合时序图的代码分析

步骤一:

        微处理器的I/O设置为输出同时输出低电平,且低电平保持时间不能小于18ms(最大不得

超过30ms),然后微处理器的I/O设置为输入状态,由于上拉电阻,微处理器的I/O即DHT11的

DATA数据线也随之变高,等待DHT11作出回答信号。

    DHT11_DATA=1;    //其实可以省略,但保险起见,还是加一下吧
    DHT11_DATA=0;    
    Delay(20);               //主机需要拉低总线18毫秒以上
    DHT11_DATA=1;   

 

步骤二:

        DHT11的DATA引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后DHT11的

DATA引脚处于输出状态,输出83微秒的低电平作为应答信号,紧接着输出87微秒的高电平通知

外设准备接收数据,微处理器的I/O此时处于输入状态,检测到I/O有低电平(DHT11回应信号)

后,等待87微秒的高电平后的数据接收。

    while(DHT11_DATA);  //此循环为了等待来自DHT11的拉低信号
    while(!DHT11_DATA); //此循环为了度过上一个拉低信号,并等待来自DHT11的拉高信号
    while(DHT11_DATA);  //此循环为了度过上一个拉高信号,并等待来自DHT11的数据信号(因为开始发送数据都是先拉低的)

        本人一开始看见了时序图上面有好多具体的时间,就想着要用延时函数,(呜~呜~呜~当时好蠢)但是这样有一个问题,因为时序每次的时间肯定都会有些许的误差,整个系统在运作的情况下,随着时间的延长,误差肯定会有所积累,所以用while就可以很好的解决这个问题,并且使得程序更加简洁。

步骤三:

        由DHT11的DATA引脚输出40位数据,微处理器根据I/O电平的变化接收40位数据,位数据

“0”的格式为:54微秒的低电平和23-27微秒的高电平,位数据“1”的格式为:54微秒的低

电平加68-74微秒的高电平。

while(!DHT11_DATA);  //等待来自DHT11的拉高信号
    i = 22;while (--i);  //延时50微秒,只要延时在合理的区间使得可以区分0和1就行
  
     if(DHT11_DATA==1)   
   {  
    Bit=DHT11_DATA;
    while(DHT11_DATA);//等待高电平的结束
    }
     else   
           Bit=DHT11_DATA;

 

 完整程序详见下面

2.DHT.c文件

#include <REGX52.H>
#include "DELAY.H"

sbit DHT11_DATA=P3^7;//DHT11通信端口定义

void DHT11_Init(void)
{
	Delay(1000);
}


void DHT11_start(void)
{
	DHT11_DATA=1;
	DHT11_DATA=0;
	Delay(20);
	DHT11_DATA=1;
	while(DHT11_DATA);
	while(!DHT11_DATA);
	while(DHT11_DATA);
}

bit DHT11_receiveBit(void)  //此为接受bit位的函数,只被下面的接受字节函数调用
{
	bit Bit;
	unsigned char i;
	while(!DHT11_DATA);
	i = 22;while (--i);
	if(DHT11_DATA==1)
	{
		Bit=DHT11_DATA;
		while(DHT11_DATA);
	}
	else
	{
		Bit=DHT11_DATA;
	}
	return Bit;
}

unsigned char DHT11_receiveByte(void)
{
	unsigned char Byte=0x00,i;
	for(i=0;i<8;i++)
	{
		if(DHT11_receiveBit())
			Byte|=(0x80>>i);       //DHT11先给高位,所以要右移
	}
	return Byte;
}

3.DHT.h文件

#ifndef __DHT11_H__
#define __DHT11_H__

void DHT11_Init(void);
void DHT11_start(void);
unsigned char DHT11_receiveByte(void);

#endif

        以上为头文件声明,一共有三个函数:初始化(延时),开始函数,接收字节函数。可为外部调用。

注意事项!!!由于DHT11每次都一定会返回40bit(5字节)的数据,所以在主函数中如果不想要显示某一项数据,也要考虑那一段时间(可以使用一个延时函数,时间由省略的字节数量决定)

  还有,看懂数据手册,啥芯片都不怕(~_~)(藐视一切)!!!

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值