使用DHT11和51单片机进行温湿度的读取(保证好用版本)

使用DHT11和51单片机进行温度的读取。

1、DHT11

     DHT11是非常用的温湿度传感器。其共有4个引脚,实物图网上一大把,这里就不放了,分别是VCC供电,串行单总线,NC空脚悬空就行,最后便是GND。

2、时序图

  1. ​​​​​​​​​​​​​​这是它从低功耗状态转换高速状态的时序,

从IO口输出至少18ms(不超过30ms)的低电平它就会工作了,外部低电平结束后它会输出83us的低电平作为响应信号,之后输出87us的高电平让单片机做好接收信号的准备.

    

响应信号时序​​​

    2、87us高电平结束后将会接受40bit的数据那么对于dht11的单总线来说何为1何为0呢?它定义在87us高电平结束后会有54us的低电平,如果这54us低电平后有23到27us的高电平则为0,54us低电平后有68到74us的高电平则为1.

时序图如下:

最后是我们喜闻乐见的源码:

头文件。

#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
//#define LCD1602_4PINS

/**********************************
包含头文件
**********************************/
#include<reg51.h>

//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint 
#define uint unsigned int
#endif

/**********************************
PIN口定义
**********************************/
#define LCD1602_DB  P0      //data bus 数据总线
sbit LCD1602_RS = P2^3;
sbit LCD1602_RW = P2^4;
sbit LCD1602_EN = P2^5;	 

/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
//void Lcd1602_Delay1ms(uint c);   //误差 0usvo
void LCD_Delay10ms(unsigned int c);
//void Read_Busy();           //忙检测函数,判断bit7是0,允许执行;1禁止
void Lcd1602_Write_Cmd(unsigned char cmd);     //写命令
void Lcd1602_Write_Data(unsigned char dat);   //写数据
void LcdSetCursor(unsigned char x,unsigned char y);  //坐标显示
void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str);     //显示字符串
void InitLcd1602();              //1602初始化
					  

#endif

/*******************************************************************************
* 实验名			   :温度显示实验
* 使用的IO	     : 
* 实验效果       :1602显示温度
*	注意					 :

*******************************************************************************/

#include<reg51.h>
#include"lcd.h"
#include<intrins.h>
#include<stdio.h>

sbit Temp_data=P2^0;
/*******************************************************************************
* 函数名         : main
* 函数功能		   : 主函数
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
//定义
void DHT11_delay_us(unsigned char n);
void DHT11_delay_ms(unsigned char z);
void DHT11_start();
unsigned char DHT11_rec_byte();
void DHT11_receive();
unsigned char rec_dat[16];


//主函数
void main()
{
	InitLcd1602();
	while(1)
	{
		DHT11_delay_ms(150);
		DHT11_receive();	
    LcdShowStr(0,1,&rec_dat);
		
	}
}



//DHT11起始信号

void DHT11_start()	
{
	Temp_data=1;
	
	DHT11_delay_us(2);
	
	Temp_data=0;
	
	DHT11_delay_ms(20);
	
	Temp_data=1;
	
	DHT11_delay_us(13);

}

//接收一个字节


unsigned char DHT11_rec_byte()
{
	
	unsigned char i,dat;

	
	for(i=0;i<8;i++)
	{
			while(!Temp_data);//度过54us低电平
		  DHT11_delay_us(16);//延时30us后判断高电平为1否则为零
			dat<<=1;
			if(Temp_data==1)
			{
				dat+=1;
			}
			while(Temp_data);
	}

	return dat;

	
}


//接收温湿度数据
void DHT11_receive()
{
	unsigned int R_H,R_L,T_H,T_L;
	unsigned char RH,RL,TH,TL,revise;
	
	DHT11_start();
//	Temp_data=1;
	if(Temp_data==0)//接收83us的应答信号,
	{
		while(Temp_data==0);   //等待拉高现在data为1     
		    while(Temp_data);//退出通知单片机接受信号
        R_H=DHT11_rec_byte();    //接收湿度高八位  
        R_L=DHT11_rec_byte();    //接收湿度低八位  
        T_H=DHT11_rec_byte();    //接收温度高八位  
        T_L=DHT11_rec_byte();    //接收温度低八位
        revise=DHT11_rec_byte(); //接收校正位

        DHT11_delay_us(25);    //结束

        if((R_H+R_L+T_H+T_L)==revise)      //校正
        {
            RH=R_H;
            RL=R_L;
            TH=T_H;
            TL=T_L;
	
        } 
        /*数据处理,方便显示*/
        rec_dat[0]='0'+(RH/10);
        rec_dat[1]='0'+(RH%10);
		rec_dat[2] =' ';
		rec_dat[3] = 'R' ;
		rec_dat[4] = 'H';
        rec_dat[5]=' ';
        rec_dat[6]=' ';
        rec_dat[7]=' ';
        rec_dat[8]=' ';
        rec_dat[9]='0'+(TH/10);
        rec_dat[10]='0'+(TH%10);
		rec_dat[11] =' ';
		rec_dat[12] = 'C';
		rec_dat[13] = ' ' ;
        rec_dat[14]=' ';


	}
	
}

//延时us   --2*n+5us
void DHT11_delay_us(unsigned char n)
{
    while(--n);
}

//延时ms
void DHT11_delay_ms(unsigned char z)
{
   unsigned char i,j;
   for(i=z;i>0;i--)
      for(j=110;j>0;j--);
}


void Read_Busy()           //忙检测函数,判断bit7是0,允许执行;1禁止
{
    unsigned char sta;      //
    LCD1602_DB = 0xff;
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    do
    {
        LCD1602_EN = 1;
        sta = LCD1602_DB;
        LCD1602_EN = 0;    //使能,用完就拉低,释放总线
    }while(sta & 0x80);
}


void Lcd1602_Write_Cmd(unsigned char cmd)     //写命令
{
    //Read_Busy();
    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_DB = cmd;
		LCD_Delay10ms(1);
    LCD1602_EN = 1;
		LCD_Delay10ms(1);
    LCD1602_EN = 0;    
}

void Lcd1602_Write_Data(unsigned char dat)   //写数据
{
      Read_Busy();
      LCD1602_RS = 1;
      LCD1602_RW = 0;
      LCD1602_DB = dat;
			LCD_Delay10ms(1);
      LCD1602_EN = 1;
			LCD_Delay10ms(1);
      LCD1602_EN = 0;
}
//指定位置开始显示数据!
void LcdSetCursor(unsigned char x,unsigned char y)  //坐标显示
{
    unsigned char addr;
    if(y == 0)
        addr = 0x00 + x;//第一行开始,x表示一行的第x个
    else
        addr = 0x40 + x;//第二行开始,x表示一行的第x个
    
    Lcd1602_Write_Cmd(addr|0x80);
}

void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str)     //显示字符串
{
    LcdSetCursor(x,y);      //当前字符的坐标
    while(*str != '\0')
    {
        Lcd1602_Write_Data(*str++);
    }
}

void InitLcd1602()              //1602初始化
{
    Lcd1602_Write_Cmd(0x38);    //打开,5*8,8位数据
    Lcd1602_Write_Cmd(0x0c);
    Lcd1602_Write_Cmd(0x06);
    Lcd1602_Write_Cmd(0x01);    //清屏   
}

void LCD_Delay10ms(unsigned int c)   //误差 0us
{
    unsigned char a,b;
    for(;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}

proteus连接:

 我会把源码和和Proteus工程放到这里。借鉴了好多大佬的欢迎交流

 

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值