DHT11温湿度传感器初识

news/2024/12/2 21:59:47/

目录

一、产品概述

1、接线方式

2、特点

3、数据传送逻辑

二、发送时序检测模块是否存在

1、C51单片机(主机)时序分析

2、编写代码检测模块是否存在

3、读取DHT11数据的时序分析

三、温湿度通过串口传到PC显示

四、温湿度检测小系统——使数据显示在LCD1602液晶板上


一、产品概述

DHT11温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,应用领域:暖通空调、汽车、消费品、气象站、温度调节器、除湿器、家电、医疗、自动控制等

1、接线方式

VCC:接供电的正极

GND:接地

DAT:接数据

2、特点

相对湿度和温度的测量

全部校准、数字输出

长期稳定性

超长的信号传输距离:20米

4引脚安装:可以买封装好的

完全互换:直接出结果,不用转化

3、数据传送逻辑

只有一根数据线DATA,上官一号发送序列指令给DHT11模块,模块一次完整的数据传输为40bit高位先出

40bit的数据格式

8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验合

二、发送时序检测模块是否存在

时序逻辑分析

对于主机来说:发送时序的开始在a点,结束在d点

1、C51单片机(主机)时序分析

a:dht=1;
b:dht=0;
b、c之间延时30ms;
c:dht=1;
开始读DHT模块有无信号,在40-100μs之间读,比如在60μs的时候读,如果在60μs的时候是低电平,说明模块存在

那怎么看模块是否有回应呢,请看上图中的de段,C51单片机发送完时序信号是处于高电平的状态,当DHT这边有信号过来时,会把信号从高电平状态拉到低电平状态,所以当de=0时,说明DHT模块有数据显示了

那对于单片机来说怎么获取到这个低电平状态呢,那就得去读取de段的数据了,读上面的引脚是否为低电平

从c点到e点共有两种情况:

第一种:cd之间的延时最短时间是20μs,de之间的延时时间是80μs,那么从c点到e点,所需要的延时时间就是20-100μs

第二种:cd之间的延时最长时间是40μs,de之间的延时时间是80μs,那么从c点到e点,所需要的延时时间就是40-120μs

综上述情况, 我们要读取它们重合的时间,才能把以上两点都包括在内,重合的时间是40-100μs

2、编写代码检测模块是否存在

#include "reg52.h"
#include "intrins.h"sbit dht    = P3^3;
sbit ledOne = P3^7;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 Delay30ms()		//@11.0592MHz
{unsigned char i, j;i = 54;j = 199;do{while (--j);} while (--i);
}void Delay60us()		//@11.0592MHz
{unsigned char i;i = 25;while (--i);
}void check_DHT(){//a:dht=1;dht = 1;//b:dht=0;dht = 0;//b、c之间延时30ms;Delay30ms();//c:dht=1;dht = 1;//开始读DHT模块有无信号,在40-100μs之间读,比如在60μs的时候读,如果在60μs的时候是低电平,说明模块存在Delay60us();if(dht == 0){ledOne = 0;     //亮灯,说明DHT模块存在}
}void main()
{ledOne = 1;      //灭灯Delay1000ms();   //上电后稳定DHT11的供电Delay1000ms();check_DHT();     //看模块是否存在while(1);        //一直循环,不让main退出	
}

执行结果:

当单片机接温湿度传感器的时候,单片机的P3^7小灯就会亮,单片机不接温湿度传感器的时候,小灯就不亮

3、读取DHT11数据的时序分析

a:dht=1;
b:dht=0;
b、c之间延时30ms;
c:dht=1;

由于c点到d点之间有个20-40μs的延时时间,所以不太好找d点的位置,那么怎么找d点的位置呢

采用卡点的方法:

卡d点:while(dht);这时dht=1,当dht=1时,说明一直是高电平信号,当dht不等于1时,条件不满足时,说明信号从高电平下降到低电平了,也就是说找到d点了

卡e点:while(!dht); 这时dht=0,一直处于低电平状态,当dht不等于0时,条件不满足,说明信号从低电平上升到高电平了,也就是找到e点了

卡f点:while(dht);这时dht=1,当dht=1时,说明一直是高电平信号,当dht不等于1时,条件不满足时,说明信号从高电平下降到低电平了,也就是说找到f点了

卡g点:while(!dht); 这时dht=0,一直处于低电平状态,当dht不等于0时,条件不满足,说明信号从低电平上升到高电平了,也就是找到g点了

DHT11传输的有效数据都是高电平,只是持续的时间不一样

表示0时,高电平持续的时间是26-28μs

表示1时,高电平持续的时间是70μs

怎么读取DHT11传送的数据

从g点以后延时一段时间去读数据,比如延时50μs后,如果读到的信号是低电平,说明是数据是0,读到是信号是高电平,说明数据是1,然后读40bit,也是就是读40次,40次分5轮来读,每轮读8次(8bit=1个char)8次形成一个数据

数字0信号表示方法

 数字1信号表示方法

三、温湿度通过串口传到PC显示

1、环境准备:C51单片机连接DHT11温湿度传感器;VCC-5V、GND-GND、DAT-接/发数据引脚

2、编写代码

#include "reg52.h"
#include "intrins.h"sbit dht    = P3^3;
sbit ledOne = P3^7;
sfr AUXR = 0x8E;
char datas[5];void UartInit(void)		//9600bps@11.0592MHz
{AUXR = 0x01;   //降低时钟对外界的辐射SCON = 0x40;   //串行口寄存器工作模式选择方式1,RNE=0,为串行禁止接收状态TMOD &= 0x0F;  //定时器1工作方式位8位自动重装TMOD |= 0x20;TH1 = 0xFD; TL1 = 0xFD;   //9600波特率的初值TR1 = 1;      //启动定时器}void sendByte(char data_msg){  //发送字节SBUF = data_msg;while(!TI);   //智能延时,靠硬件延时TI = 0;
}void sendString(char* str){   //发送字符串while(*str != '\0'){sendByte(*str);str++;}
}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 Delay30ms()		//@11.0592MHz
{unsigned char i, j;i = 54;j = 199;do{while (--j);} while (--i);
}void DHT11_Start(){dht = 1;dht = 0;Delay30ms();dht = 1;while(dht);  //卡d点while(!dht); //卡e点while(dht);  //卡f点}void Delay40us()		//@11.0592MHz
{unsigned char i;_nop_();i = 15;while (--i);
}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);  //卡g点Delay40us();  //延时40usif(dht == 1){flag = 1;while(dht);}else{    flag = 0;}tmp = tmp << 1;tmp |= flag;}datas[i] = tmp;}
}void main()
{ledOne = 1;      //灭灯UartInit();      //初始化一个串口Delay1000ms();   //上电后稳定DHT11的供电Delay1000ms();while(1){Delay1000ms();Read_Data_From_DHT();          //获取DHT数据sendString("H:");              //发送字符串sendByte(datas[0]/10 + 0x30);  //发送第1个bit字节,获取湿度的整数位sendByte(datas[0]%10 + 0x30);sendByte('.');sendByte(datas[1]/10 + 0x30);  //发送第2个bit字节,获取湿度的小数位sendByte(datas[1]%10 + 0x30);sendString("\r\n");            //自动换行sendString("T:");sendByte(datas[2]/10 + 0x30);  //发送第3个bit字节,获取温度的整数位sendByte(datas[2]%10 + 0x30);sendByte('.');sendByte(datas[3]/10 + 0x30);  //发送第4个bit字节,获取温度的小数位sendByte(datas[3]%10 + 0x30);sendString("\r\n");            //自动换行}    	
}

3、执行结果:

四、温湿度检测小系统——使数据显示在LCD1602液晶板上

1、环境准备:C51单片机连接DHT11温湿度传感器和LCD1602液晶板

下面的链接里有C51单片机和LCD1602液晶板的连接方式

初识LCD1602及编程实现字符显示_Love小羽的博客-CSDN博客

2、编写代码

#include "reg52.h"
#include "intrins.h"
#define databuffer P0 //定义8位数据线,P0端口组sbit dht    = P3^3;
sbit ledOne = P3^7;
sfr AUXR = 0x8E;
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^4;
sbit fengshan = P1^6;  //继电器引脚char datas[5];
char temp[8];   //定义一个温度类型
char huma[8];   //定义一个湿度类型void check_busy(){char tmp = 0x80;databuffer = 0x80;while(tmp & 0x80){RS = 0;RW = 1;EN = 0;_nop_();EN = 1;_nop_();_nop_();tmp = databuffer;  //读取数据_nop_();EN = 0;_nop_();}
}void Write_Cmd_Func(char cmd){check_busy();RS = 0;  //指令寄存器,接收地址RW = 0;EN = 0;_nop_();databuffer = cmd;   //发送指令_nop_();EN = 1;_nop_();_nop_();EN = 0;_nop_();
}void Write_Data_Func(char dataShow){check_busy();RS = 1;  //数据寄存器,接收内容RW = 0;EN = 0;_nop_();databuffer = dataShow;   //发送数据_nop_();EN = 1;_nop_();_nop_();EN = 0;_nop_();     
}void Delay15ms()        //@11.0592MHz
{unsigned char i, j;i = 27;j = 226;do{while (--j);} while (--i);
}void Delay5ms()        //@11.0592MHz
{unsigned char i, j;i = 9;j = 244;do{while (--j);} while (--i);
}void UartInit(void)		//9600bps@11.0592MHz
{AUXR = 0x01;   //降低时钟对外界的辐射SCON = 0x40;   //串行口寄存器工作模式选择方式1,RNE=0,为串行禁止接收状态TMOD &= 0x0F;  //定时器1工作方式位8位自动重装TMOD |= 0x20;TH1 = 0xFD; TL1 = 0xFD;   //9600波特率的初值TR1 = 1;      //启动定时器}void sendByte(char data_msg){  //发送字节SBUF = data_msg;while(!TI);   //智能延时,靠硬件延时TI = 0;
}void sendString(char* str){   //发送字符串while(*str != '\0'){sendByte(*str);str++;}
}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 Delay30ms()		//@11.0592MHz
{unsigned char i, j;i = 54;j = 199;do{while (--j);} while (--i);
}void DHT11_Start(){dht = 1;dht = 0;Delay30ms();dht = 1;while(dht);  //卡d点while(!dht); //卡e点while(dht);  //卡f点}void Delay40us()		//@11.0592MHz
{unsigned char i;_nop_();i = 15;while (--i);
}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);  //卡g点Delay40us();  //延时40usif(dht == 1){flag = 1;while(dht);}else{    flag = 0;}tmp = tmp << 1;tmp |= flag;}datas[i] = tmp;}
}void LCD1602_INIT(){//(1)延时 15ms Delay15ms();
//(2)写指令 38H(不检测忙信号) Write_Cmd_Func(0x38);
//(3)延时 5ms Delay5ms();
//(4)以后每次写指令,读/写数据操作均需要检测忙信号 check_busy();
//(5)写指令 38H:显示模式设置 Write_Cmd_Func(0x38);
//(6)写指令 08H:显示关闭 Write_Cmd_Func(0x08);
//(7)写指令 01H:显示清屏 Write_Cmd_Func(0x01);
//(8)写指令 06H:显示光标移动设置 Write_Cmd_Func(0x06);
//(9)写指令 0CH:显示开及光标设置Write_Cmd_Func(0x0c);
}void LCD1602_showLine(char row,char col,char *string){switch(row){case 1:Write_Cmd_Func(0x80+col);    //选择要显示的地址while(*string){Write_Data_Func(*string);  //发送要显示内容string++;}break;case 2:Write_Cmd_Func(0x80+0x40+col);while(*string){Write_Data_Func(*string);string++;}break;}
}void Build_Datas(){huma[0] = 'H';                 //温度huma[1] = datas[0]/10 + 0x30;huma[2] = datas[0]%10 + 0x30;huma[3] = '.';huma[4] = datas[1]/10 + 0x30;huma[5] = datas[1]%10 + 0x30;huma[6] = '%';huma[7] = '\0';temp[0] = 'T';                  //湿度temp[1] = datas[2]/10 + 0x30;temp[2] = datas[2]%10 + 0x30;temp[3] = '.';temp[4] = datas[3]/10 + 0x30;temp[5] = datas[3]%10 + 0x30;temp[6] = 'C';temp[7] = '\0';}void main()
{Delay1000ms();UartInit();      //初始化一个串口LCD1602_INIT();  //初始化LCD1602液晶显示Delay1000ms();   //上电后稳定DHT11的供电Delay1000ms();ledOne = 0;      while(1){Delay1000ms();Read_Data_From_DHT();           //获取DHT数据if(datas[2] > 29 ){fengshan = 0;}Build_Datas();sendString(huma);               //发送湿度字符串sendString("\r\n");sendString(temp);               //发送温度字符串sendString("\r\n");LCD1602_showLine(1,3,temp);		  //第一行显示湿度LCD1602_showLine(2,3,huma);		  //第二行显示温度}    
}

执行结果:


http://www.ppmy.cn/news/118122.html

相关文章

git创建本地分支的应用实践

场景 我们希望能够不影响本地master分支的情况下自己单独开发一个功能&#xff0c;等开发完成后再合并到master分支中 操作 创建本地分支sortdev&#xff0c;并且切换到该分支上&#xff1a; git checkout -b sortdev git branch -vv 可以查看到本地master分支追踪的是远程…

扔掉老破V100、A100,英伟达新一代计算卡H100来了

本文转载自公众号“夕小瑶的卖萌屋”&#xff0c;专业带逛互联网算法圈的神操作 -----》我是传送门 关注后&#xff0c;回复以下口令&#xff1a; 回复【789】 &#xff1a;领取深度学习全栈手册&#xff08;含NLP、CV海量综述、必刷论文解读&#xff09; 回复【入群】&#xf…

TA100 T3.4

前向/延迟渲染管线 渲染路径渲染方式FORWARD流程Unity中规则 DEFERRED流程几何处理Pass光照Pass 透明物体 不同渲染路径的特性异同优劣前向渲染优点缺点 延迟渲染优点缺点 其他Unity中渲染路径设置TBDR更多渲染路径延迟光照Deferred Lighting分块正向渲染Forward群组渲染Cluste…

js,for循环中的闭包导致的错误,及其四种解决方案

循环中的闭包,将可能导致一种奇怪的错误 function outside() {//* 外部函数var arr = [];for (var i = 0; i < 3; i++

如何系统学习音视频技术

一、音视频技术技术介绍 音视频技术是指涉及音频和视频的数字媒体技术&#xff0c;通常用于多媒体制作、传输和播放等方面。下面是一些常见的音视频技术介绍&#xff1a; 声音采样和编码&#xff1a;将声音转换成数字信号并进行压缩编码&#xff0c;以便于储存、传输和处理。常…

【地平线X3M平台点亮sensor出现问题的分析】

转自地平线论坛经验 1. IC通讯失败的问题以及排查方法。 外界的图像数据一般是通过sensor感知&#xff0c;然后通过mipi接口进入到地平线X3M这款AI芯片的视频处理模块&#xff0c;模块对视频图像做比如放大、缩小、旋转等处理。 问题&#xff1a;IC通讯失败&#xff0c;错误…

如何鉴别电脑电源是否虚标(实际输出瓦数)

发现很多人没有提&#xff0c;大部分的虚标都是在名字上做文章 比如起个名字xx500w&#xff0c;实际额定只有300w。 比起到处翻标签确定额定功率。 直接看12v输出&#xff0c;cpu显卡绝大部分供电都是12v出来。 12v那一路的输出功率差不多等于最大电源功率。 比如12v输出58…

常见的电脑电源种类

常见的电脑电源有以下几种&#xff1a; AT电源&#xff1a;早期电脑使用的标准电源&#xff0c;已经被淘汰。 ATX电源&#xff1a;现代电脑普遍采用的电源&#xff0c;提供更稳定的电压输出和更好的节能性能。 SFX电源&#xff1a;小型电脑和媒体中心等需要小型化设计的设备…