51单片机使用DHT11温湿度模块实现温湿度监测

一.DHT11介绍

型号 测量范围 测湿精度 测温精度
DHT11 20-90%RH  0-50摄氏度°C 士5%RH   士2℃

二.DHT11接口说明

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

2.VCC接单片机的5v,GND接GND,DAT接单片机的IO口。

三.电源引脚

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

四.DHT11时序图

DHT11初始化从图2开始,一开始先给高电平,然后在给低电平(至少18ms),之后高电平持续20-40us,不确定是多少us,可以用while卡着,定义DAT为dht,dht此时是1,则卡着while(dht),直到跳过while循环以后,DHT11开始响应,此时dht为0,我们也可以卡着,while(!dht),之后过了while循环以后,变成了高电平1,dht=1,此时接着卡,while(dht),当卡过以后开始传输数据(红线部分),如果传的是1则是图4,如果是0则图5,此时只要等待红线部分过去就有数据,此时接着卡,while(!dht),之后给40us延迟,如果40us延迟以后还是高电平则是数据1,数据1一共要维持70us高电平,此时才维持40us,我们要卡着高电平等待过去到下一bit开始,所以while(dht),如果是低电平则数据0,此时不需要卡着,已经来到了下一bit开始的位置。

五.传输数据

一次完整的数据传输为40bit,高位先出。
数据格式:8bit湿度整数数据+8 bit湿度小数数据+8bi温度整数数据+8 bit温度小数数据+8bit校验和
数据传送正确时校验和数据=“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。

六.DHT11测温湿度发送到串口助手的代码

补充知识:下面代码的value=value<<1,value |= flag;在是因为DHT11传的数据高位先出,,要循环8次,所以最后一开始的第一位就到了二级制的最高位。

#include <REGX52.H>
#include <intrins.h>

sbit led4 = P2^3;	//led小灯用来判断模块是否测量
sbit dht = P1^0;	//温湿度传感器信号线
sbit AUXR=0x8E;

char datas[5]; 		//数组分别代表,湿度,湿度小数,温度,温度小数,校验

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

	i = 36;
	j = 217;
	do
	{
		while (--j);
	} while (--i);
}

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 Delay40us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	i = 15;
	while (--i);
}

void Uart_Init()
{
	AUXR = 0x01;
	SCON = 0x40;
	PCON &= 0x7F;
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xFD;		//设定定时初值
	TH1 = 0xFD;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}

void Uart_Sendchar(char Char)
{
	SBUF=Char;
	while(TI==0);
	TI=0;
}

void Uart_Sendstring(char*string)
{
	while(*string!='\0')
	{
		Uart_Sendchar(*string);
		string++;
	}
}

//初始化模块(检测模块是否存在)每次传输数据都要初始化
void DHT_Start()
{
	//根据时序进行高低电平变化
	led4 = 1;
    dht = 1;		//对应初始化时序start
    dht = 0;
    Delay20ms();
	dht=1;
    while(dht);
	while(!dht);
	while(dht);
    led4 = 0;
}

void DHT11_Read()
{
	char value = 0;
	char flag;
	char i = 0;
	char j = 0;
	DHT_Start();
	for(j = 0;j<5;j++)//分别读取五组数据
	{			
		for(i=0;i<8;i++)//每组八位分别处理
		{		
			while(!dht);		//高电平开始计时
			Delay40us();
			
			if(dht == 1)  //如果还为高则是“1”
			{		
				flag = 1;
				while(dht);
			}
			
			 else       //否则“0”
			{				
				flag = 0;
			}
			value = value << 1;		//移位
			value |= flag; 			//赋值
		}
		datas[j] = value;			//赋值
	}
}

void main()
{	
	Delay1000ms();Delay1000ms();
	Uart_Init();
	while(1)
	{
		Delay1000ms();
		DHT11_Read();
		
		Uart_Sendstring("H:");//湿度整数
		Uart_Sendchar(datas[0]/10+0x30);//十位
		Uart_Sendchar(datas[0]%10+0x30);//个位
		Uart_Sendchar('.');//湿度小数
		Uart_Sendchar(datas[1]/10+0x30);
	    Uart_Sendchar(datas[1]%10+0x30);
		Uart_Sendstring("\r\n");
		Uart_Sendstring("T:");//温度整数
		Uart_Sendchar(datas[2]/10+0x30);
		Uart_Sendchar(datas[2]%10+0x30);
		Uart_Sendchar('.');//温度小数
		Uart_Sendchar(datas[3]/10+0x30);
		Uart_Sendchar(datas[3]%10+0x30);
		Uart_Sendstring("\r\n");
	}
}

七.DHT11测温湿度发送到LCD1602上的代码

#include <REGX52.H>
#include <intrins.h>
#define LCE_Dataport P0

sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
sbit led4 = P2^3;	//led小灯用来方便判断DHT11有没有在测量
sbit dht = P1^0;	//温湿度传感器信号线
sbit AUXR=0x8E;

char datas[5]; 		//数组分别代表,湿度,湿度小数,温度,温度小数,校验

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

	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
}

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

	i = 36;
	j = 217;
	do
	{
		while (--j);
	} while (--i);
}

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 Delay40us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	i = 15;
	while (--i);
}

void LCD_WriteCommand(unsigned char Command)//写指令
{
	LCD_RS=0;
	LCD_RW=0;
	LCE_Dataport=Command;
	LCD_EN=1;
	Delay1ms();
	LCD_EN=0;
	Delay1ms();
}

void LCD_WriteData(unsigned char Data)//写数据
{
	LCD_RS=1;
	LCD_RW=0;
	LCE_Dataport=Data;
	LCD_EN=1;
	Delay1ms();
	LCD_EN=0;
	Delay1ms();
}

void LCD_Init()//初始化
{
	LCD_WriteCommand(0x38);
	LCD_WriteCommand(0x0C);
	LCD_WriteCommand(0x06);
	LCD_WriteCommand(0x01);
}

void LCD_Setcursor(unsigned char line,unsigned char column)
{
	if(line==1)//设置光标位置
	{
		//第一列是数字1,但是位置是0x00,要把数字1转换0x00,就把数字1-1就0,所以转十六进制就是0x00
		LCD_WriteCommand(0x80|(column-1));
	}
	else
	{
		//第二行的第一列是从0x40开始,第二列是0x41,相当于0x40+0x01,0x01就是与上面一致
		LCD_WriteCommand(0x80|(column-1)+0x40);
	}
}

void LCD_Showchar(unsigned char line,unsigned char column,unsigned char Char)//line行,column列,Char字符
{//显示一个字符
	LCD_Setcursor(line,column);	
	LCD_WriteData(Char);
}

void LCD_Showstring(unsigned char line,unsigned char column,unsigned char *string)//line行,column列,string字符串
{//显示字符串,字符串直接等于指针,不用数组形式等于字符串,在等于指针形式,那传给指针的就是字符串的第一个字符的地址,然后string【i】一直往下就可以知道字符串,数组是连续的,如果baby的b在第一行第一列,那a就会在第一行,第二列。
	unsigned char i;
	LCD_Setcursor(line,column);		
	for(i=0;string[i]!='\0';i++)
	{
		LCD_WriteData(string[i]);//字符串本身就是地址,所以传进来的字符串用指针string来接
	}
}

//初始化模块(检测模块是否存在)每次传输数据都要初始化
void DHT_Start()
{
	//根据时序进行高低电平变化
	  led4 = 1;	
    dht = 1;		//对应初始化时序start
    dht = 0;
    Delay20ms();
	  dht=1;
		while(dht);
		while(!dht);
		while(dht);
		led4=0;
}

void DHT11_Read()
{
	char value = 0;
	char flag;
	char i = 0;
	char j = 0;
	DHT_Start();
	for(j = 0;j<5;j++)//分别读取五组数据
	{			
		for(i=0;i<8;i++)//每组八位分别处理
		{		
			while(!dht);		//高电平开始计时
			Delay40us();
			if(dht == 1)  //如果还为高则是“1”
			{		
				flag = 1;
				while(dht);
			}
			 else       //否则“0”
			{				
				flag = 0;
			}
			value = value << 1;		//移位
			value |= flag; 			//赋值
		}
		datas[j] = value;			//赋值
	}
}

void main()
{	
	Delay1000ms();Delay1000ms();
	LCD_Init();
	while(1)
	{
		Delay1000ms();
		DHT11_Read();
		
		LCD_Showstring(1,1,"H:");//湿度整数
		LCD_Showchar(1,3,datas[0]/10+0x30);//十位
		LCD_Showchar(1,4,datas[0]%10+0x30);//个位
		LCD_Showchar(1,5,'.');//湿度小数
		LCD_Showchar(1,6,datas[1]/10+0x30);
		LCD_Showchar(1,7,datas[1]%10+0x30);
		LCD_Showstring(2,1,"T:");//温度整数
		LCD_Showchar(2,3,datas[2]/10+0x30);
		LCD_Showchar(2,4,datas[2]%10+0x30);
		LCD_Showchar(2,5,'.');//温度小数
		LCD_Showchar(2,6,datas[3]/10+0x30);
		LCD_Showchar(2,7,datas[3]%10+0x30);
	}
}

八.现象

DHT11模块不要碰底下,不然会卡住不测量了,led4用来判断有没有一直在测量,闪一次就代表正测量一次 

物联沃分享整理
物联沃-IOTWORD物联网 » 51单片机使用DHT11温湿度模块实现温湿度监测

发表评论