单片机——DHT11 温湿度传感器

DHT11温湿度传感器在51单片机中的应用

DHT11实物图

一、DHT11 模块参数如下:

1 可以检测周围环境的湿度和温度
2 传感器采用 DHT11
3 湿度测量范围: 20%-95%( 0 度-50 度范围)湿度测量误差: ±5%
4 温度测量范围: 0 度-50 度 温度测量误差: ±2 度
4 工作电压 3.3V-5V
5 输出形式 数字输出
6 设有固定螺栓孔,方便安装
7 小板 PCB 尺寸: 3.2cm * 1.4cm
8 电源指示灯(红色)

二、模块电路图

DHT11模块电路图
注意:这是模块的电路图,图中DATA引脚之所以要加上拉电阻,是应为dht11传感器中有如下介绍:
温湿度传感器应用电路图
所以我们如果后面开发不买上面成品温湿度模块,我们可以买那种只有三针引脚的温湿度传感器(如下图)自己按照上面的电路图自己焊电路。最后好奇的童鞋会不会问,那为什么要加上拉电阻呢?这些童鞋可以往后看,在后面时序图中我们可以知道DHT会发送高电平信号,这里加入上拉电阻可以实现输出真正意义上的高电平哦。
在这里插入图片描述

三、 DHT11 模块接线说明

1 VCC 外接 3.3V-5V
2 GND 外接 GND
3 DATA 小板开关数字量输出接口 接单片机 IO 口

四、 DHT11 测试说明

编译环境: keil4
测试单片机 STC89C52
DHT11 模块与单片机连接: VCC-VCC 、GND-GND、 DATA-P2.0
从DHT11的DATA引脚总共接收 40位数据,具体如下:
温度高 8 位 串口发送的第一个数据
温度低 8 位 串口发送的第二个数据(默认为 00)
湿度高 8 位 串口发送的第三个数据
湿度低 8 位 串口发送的第四个数据(默认为 00)
校验 8 位 串口发送的第五个数据

五、 DHT11 功能函数

DHT11.C文件

sbit thd11=P2^0;	//定义DHT11温湿度数据引脚DATA
/*------------------------------------------------
              DHT11延时函数
------------------------------------------------*/
void DHT11_delay_us(uchar n)
{
    while(--n);
}
void DHT11_delay_ms(uint z)
{
   uint i,j;
   for(i=z;i>0;i--)
      for(j=110;j>0;j--);
}
/*--------------------------------------------
              DHT11开始信号
------------------------------------------------*/
void DHT11_start()
{
   thd11=1;
   DHT11_delay_us(2);
   thd11=0;
   DHT11_delay_ms(20);   //延时18ms以上
   thd11=1;
   DHT11_delay_us(30);
}

/*------------------------------------------------
              接收八位二进制
------------------------------------------------*/

uchar DHT11_rec_byte()      //接收一个字节
{
  unsigned char i,dat=0;
  for(i=0;i<8;i++)    //从高到低依次接收8位数据
   {          
      while(!thd11);   等待50us低电平过去
      DHT11_delay_us(8);     //延时60us,如果还为高则数据为1,否则为0 
      dat<<=1;           //移位使正确接收8位数据,数据为0时直接移位
      if(thd11==1)    //数据为1时,使dat加1来接收数据1
        dat+=1;
      while(thd11);  //等待数据线拉低    
   }  
    return dat;
}

/*------------------------------------------------
              接收40bit数据(具体的温湿度)
------------------------------------------------*/
void DHT11_receive(uchar *rec_dat)      //接收40位的数据
{
    uchar R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise; 
    DHT11_start();
    if(thd11==0)
    {
        while(thd11==0);   //等待拉高     
        DHT11_delay_us(80);  //拉高后延时80us
			
        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]='0'+(TH/10);
        rec_dat[3]='0'+(TH%10);
				
    }

}

是不是很多人和我最开始接触单片机一样,不会用模块手册/芯片手册,我在这里还是附上如何看手册编写源程序的方法吧!

单片机时序是指单片机执行指令时发出的控制信号的时间序列。这些信号在时间上的相互关系就是CPU的时序。
CPU发出的时序有两类:
	1. 用于片内各功能部件的控制,它们是芯片设计师关注的问题,对用户没有什么意义
	2. 用于片外存储器或I/O端口的控制,需要通过器件的控制引脚送到片外,这部分时序
	   对分析硬件电路的原理至关重要,也是软件编程遵循的原则,需要认真掌握。

在这里插入图片描述
上图为单片机和DHT11之间通信的时序图。从时序图中可知:
1、主机先拉低总线进行发送开始信号,然后再将总线拉高等待DHT11响应主机。此时DHT11从低功耗模式转换到高速模式,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集。
2、DHT11接收到主机的开始信号后,等待主机开始信号结束,再发送低电平响应信号,然后将总线拉高准备输出。
3、DHT11拉高总线后,就开始给主机传输数据了。
4、DHT11数据传输完后,会将总线拉低50us,通知主机结束(主机将总线拉高)。

1、下面是开始信号的编写方法:

在这里插入图片描述

总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。主机发送开始信号结束后,延时等待20-40us后, 开始读取DHT11的响应信号。

/*--------------------------------------------
              DHT11开始信号
------------------------------------------------*/
void DHT11_start()
{
   thd11=1;//总线先拉高
   DHT11_delay_us(2);
   thd11=0;//总线拉低
   DHT11_delay_ms(20);   //延时18ms以上
   thd11=1;//总线拉高
   DHT11_delay_us(30);//延时等待20-40us后
}

2、下面是接收数据的编写方法

在这里插入图片描述
上图就是DHT11接收到开始信号后,它对总线的时序图。可知:
1、发送80us的低电平响应信号。
2、然后它将总线拉高80us的高电平,为传输数据(温湿度等)做准备。
3、开始在总线上传输数据(此时单片机就可以接收数据了)

作用:所以我们通过上面时序图就可以判断DHT11从什么时候开始响应主机的?而主机也就可以在根据总线的情况,在正确的时间去接收DHT11发送的数据了。

注意:DHT11会一次性发送40位数据,所以主机也要一次性接收40位数据哦。
这个比较简单,就是简单的判断总线电平变化。我这里就不贴代码,最上面有代码,按照时序图一步一步分析就行!

3、接收的数据是0/1的判断方法

在这里插入图片描述
从上面的时序图可知,DHT11在发送数据前都会有一个50us低电平的开始时间,然后输出高电平,这才是真正的数据。根据高电平的时间区分是0还是1。

下面为程序中我们如何按照时序图真确接收数据的方法:
/*------------------------------------------------
              接收八位二进制
------------------------------------------------*/

uchar DHT11_rec_byte()      //接收一个字节
{
  unsigned char i,dat=0;
  for(i=0;i<8;i++)    //从高到低依次接收8位数据
   {          
      while(!thd11);   等待50us低电平过去
      DHT11_delay_us(60);     //延时60us,如果还为高则数据为1,否则为0 
      dat<<=1;           //移位使正确接收8位数据,数据为0时直接移位
      if(thd11==1)    //数据为1时,使dat加1来接收数据1
        dat+=1;
      while(thd11);  //如果为数据1,就要等待数据线拉低,让数据1的信号过去    
   }  
    return dat;
}

总结:从手册中我们可知要接收5次,每次8位二进制,分别对应湿度整数、小数…等。

注意:

在单片机中,只用将上述代码封装在一个“.c”文件中,然后在main函数里 做两步:
1、char dht11_data[4]; //定义用于接收DHT11温湿度数据的数组–保存湿度和温度。
2、DHT11_receive(dht11_data);//调用函数获取温湿度值到dht11_datas数组(博主没有保存最后的校验位),因此就可以显示值了

至于想研究文件中uchar DHT11_rec_byte();void DHT11_start();的写作原理,请参考DHT11的说明手册,都是根据手册中的时序图写的。

手册链接: DHT11说明书.

是不是特别简单,好用记得点赞哦🤭

### 回答1: 好的,下面是 51 单片机读取 DHT11 湿度传感器的代码示例: #include <reg51.h> #include <intrins.h> sbit DHT11_Data = P1^0; unsigned char DHT11_Rx_Byte() { unsigned char i, dat; dat = 0; for (i=0; i<8; i++) { while(!DHT11_Data); _nop_(); _nop_(); dat <<= 1; if(DHT11_Data) { dat |= 1; } while(DHT11_Data); } return dat; } void main() { unsigned char humi_int, humi_deci, temp_int, temp_deci, check; while(1) { DHT11_Data = 1; _nop_(); _nop_(); DHT11_Data = 0; _nop_(); _nop_(); DHT11_Data = 1; while(!DHT11_Data); while(DHT11_Data); humi_int = DHT11_Rx_Byte(); humi_deci = DHT11_Rx_Byte(); temp_int = DHT11_Rx_Byte(); temp_deci = DHT11_Rx_Byte(); check = DHT11_Rx_Byte(); if((humi_int + humi_deci + temp_int + temp_deci) == check) { // 数据校验正确,可以使用 humi_int、humi_deci、temp_int 和 temp_deci 变量中的数据 } else { // 数据校验错误,不能使用 humi_int、humi_deci、temp_int 和 temp_deci 变量中的数据 } } } 该代码实现了 51 单片机读取 DHT11 湿度传感器的功能。它首先向 DHT11 发送信号,然后通过调用 DHT11_Rx_Byte 函数接收 DHT11 发送回来的数据。最后,它还进行了数据校验,确保数据的准确性。 希望这能帮 ### 回答2: 以下是51单片机读取DHT11湿度传感器的示例代码: #include <reg51.h> sbit DHT11_PIN = P1^0; // 定义DHT11信号引脚 void delay_us(unsigned int t) // 微秒级延时函数 { while (t--) { // 通过经验值估算延时时间 for(int i=0; i<11; i++); } } void delay_ms(unsigned int t) // 毫秒级延时函数 { while (t--) { delay_us(1000); } } void start_signal() // 发送起始信号 { DHT11_PIN = 0; delay_ms(20); DHT11_PIN = 1; delay_us(30); } unsigned char read_byte() // 读取一个字节的数据 { unsigned char byte = 0; for (int i = 0; i < 8; i++) { while(!DHT11_PIN); // 等待高电平信号过去 delay_us(30); if(DHT11_PIN) { byte |= (1 << (7 - i)); // 高位在前,低位在后 } while(DHT11_PIN); // 等待低电平信号过去 } return byte; } void main() { unsigned char temperature, humidity; while(1) { start_signal(); while(!DHT11_PIN); // 等待DHT11的响应信号 while(DHT11_PIN); // 等待DHT11的响应信号过去 if(DHT11_PIN) { temperature = read_byte(); // 读取度值的整数部分 read_byte(); // 读取度值的小数部分 humidity = read_byte(); // 读取湿度值的整数部分 read_byte(); // 读取湿度值的小数部分 // 打印湿度值 // ... // 进行其他操作 // ... } delay_ms(2000); // 2秒钟后重新读取湿度值 } } 以上代码是使用51单片机读取DHT11湿度传感器数据的一个示例。其中,通过定义DHT11_PIN为P1^0来指定DHT11信号引脚。通过起始信号和读取字节的函数来与DHT11进行通信。最后,通过打印湿度值或进行其他操作来处理传感器数据。整个过程会附带一些延时函数来确保正确的通信和操作时序。 ### 回答3: 51单片机读取DHT11湿度传感器的代码如下: #include <reg51.h> sbit DHT11_DATA = P1^0; void delay_us(unsigned int t) { while(t--) { _nop_(); } } unsigned char read_byte() { unsigned char i, dat; for(i = 0; i < 8; i++) { while(!DHT11_DATA); delay_us(30); if(DHT11_DATA) { dat |= (1 << (7 - i)); while(DHT11_DATA); } else { while(!DHT11_DATA); } } return dat; } void read_DHT11(unsigned int *temp, unsigned int *humi) { unsigned char i, dat[5]; DHT11_DATA = 0; delay_us(20000); DHT11_DATA = 1; delay_us(30); if(!DHT11_DATA) { while(!DHT11_DATA); while(DHT11_DATA); for(i = 0; i < 5; i++) { dat[i] = read_byte(); } if(dat[0] + dat[1] + dat[2] + dat[3] == dat[4]) { *humi = dat[0]; *temp = dat[2]; } } } void main() { unsigned int temperature, humidity; read_DHT11(&temperature, &humidity); // 处理湿度数据 while(1); } 以上代码首先定义了51单片机的引脚和一些延时函数。read_byte()函数用来读取DHT11传感器发送的数据,根据数据位的高低电平判断是0还是1,并将数据保存在变量dat中。read_DHT11()函数用来读取DHT11传感器的湿度数据,并将其保存在变量temp和humi中。主函数调用read_DHT11()函数获取湿度数据,并进行后续处理。 请注意,以上代码仅供参考,具体的湿度传感器型号和引脚连接可能会有所不同,请根据实际情况进行相应的修改。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

掏一淘哆啦A梦的奇妙口袋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值