一篇文章教会你DHT11读取温湿度,附STM32代码示例

news2024/11/28 12:35:37

目录

一、DHT11说明:

1.典型电路:

2.串行通信说明(单线双向):

单总线说明:

单总线传送数据位定义:

校验位数据定义: 

二、DHT11读取时为啥要切换模式:

1. 通信时序要求

2. 信号检测的灵敏度

3. 浮动输入模式的优势

4. 避免冲突

5. 功耗考虑

6.结论

7.切换模式代码:

 ​三、发送开始准备读取信号:

步骤一:

步骤二:

四、接收DHT11应答信号:

五、接收DHT11发送的数据一位:

读取方法:

六,接收DHT11发送的数据字节:

接收到的40位数据为:

计算:

特殊说明:

示例:

完整时序图:

七、示例代码及结果:


一、DHT11说明:

1.典型电路:

 

  • 在使用DHT11传感器时,其DATA数据线通过一个上拉电阻与微处理器的I/O端口相连,这是为了在数据线空闲时保持一个稳定的高电平状态。对于短距离通信(线长小于5米),通常推荐使用4.7kΩ的上拉电阻。如果通信距离较长(超过5米),可能需要根据实际情况选择一个更小的电阻值,以确保数据线上的信号能够稳定地到达微处理器。

  • 当DHT11使用3.3V电压供电时,推荐保持数据线尽可能短,因为长距离的接线可能会因为线路损耗而导致传感器供电不足,进而影响测量结果的准确性。此外,如果电源部分存在波动,这也可能会影响温度的测量值。特别是当使用开关电源时,电源的不稳定可能会导致温度读数出现跳动。

  • DHT11传感器的一个特性是,它每次读出的温湿度数值实际上是上一次测量的结果。为了获得实时数据,需要连续读取两次,第二次读取的结果通常更接近当前的实时值。但是,不建议连续多次读取传感器,因为这样可能会影响传感器的性能和数据的准确性。每次读取之间应至少间隔2秒钟,这样可以给传感器足够的时间来准备下一次测量,从而获得更准确的数据。

2.串行通信说明(单线双向):

单总线说明:
  • DHT11是一种常用的单总线数字温湿度传感器,它通过一条数据线与微控制器通信。这种单总线的设计意味着所有的数据交换和控制都通过这一根线完成。在这种通信协议中,设备通过一个漏极开路或三态端口连接到数据线,这样当设备不发送数据时,它能够释放总线,允许其他设备使用总线。为了确保在没有数据传输时总线为高电平状态,单总线通常需要外接一个约4.7kΩ的上拉电阻。

  • 由于DHT11采用主从结构,只有主机(微控制器)发起请求时,从机(DHT11)才会响应。因此,主机访问DHT11时必须严格遵守单总线通信序列。如果通信序列出现混乱,DHT11将不会响应主机的请求。

单总线传送数据位定义:
  • DATA用于微处理器与DHT11之间的通讯和同步,采用单总线数据格式,一次传送40位数据, 高位先出。

  • 数据格式: 8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验位。

  • 其中湿度小数部分为0。

校验位数据定义: 

“8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据”=8bit校验位。

二、DHT11读取时为啥要切换模式:

使用推挽输出模式来读取电平变化在某些情况下是可行的,但可能会遇到一些问题,特别是在与DHT11这类传感器通信时。以下是一些关键点,解释了为什么在与DHT11通信时,仅使用推挽输出模式可能不够:

1. 通信时序要求

DHT11通信协议对时序有严格的要求。它依赖于精确的高电平和低电平持续时间来传输数据。在推挽输出模式下,GPIO引脚可以驱动电流,但在读取数据时,需要引脚处于浮动状态以准确检测由传感器拉高或拉低的电平变化。

2. 信号检测的灵敏度

在推挽输出模式下,GPIO引脚会尽力保持其状态(高或低),直到程序改变它。这意味着,如果引脚被配置为输出高电平,它可能无法准确检测到微弱的低电平信号,尤其是当这些信号由外部设备(如DHT11)生成时。

3. 浮动输入模式的优势

将GPIO配置为浮动输入模式(GPIO_Mode_IN_FLOATING)时,引脚会处于高阻抗状态,这意味着它不会尝试驱动信号,而是允许外部信号驱动它。这使得微控制器能够更准确地读取由外部设备设置的电平状态,无论是高还是低。

4. 避免冲突

如果GPIO被配置为推挽输出,并且尝试读取数据,而此时外部设备(如DHT11)也在尝试通过同一引脚驱动信号,可能会导致冲突。这种冲突可能导致不稳定的读数或通信失败。

5. 功耗考虑

在某些低功耗应用中,可能希望在不活跃时减少GPIO引脚的功耗。在输出模式下,GPIO引脚会持续消耗电流以维持其电平状态,而在浮动输入模式下,引脚在不活跃时消耗的电流要少得多。

6.结论

虽然在理论上可以使用推挽输出模式来读取电平变化,但在实践中,特别是在需要精确时序和敏感信号检测的应用(如DHT11通信)中,推荐使用浮动输入模式。这样可以确保微控制器能够准确地检测到由外部设备生成的信号,避免通信错误和提高系统的可靠性。

7.切换模式代码:
 void DHT11_Mode(uint8_t mode) {
     
     GPIO_InitTypeDef GPIO_InitStructure;
     GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     if (mode) {
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //推挽输出
     } else {
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
         //数据线会被上拉电阻拉高,主机通过检测数据线的电平变化来读取DHT11发送的数据。
     }
     GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
 }

 ​三、发送开始准备读取信号:

步骤一:

DHT11上电后(DHT11上电后要等待1s以越过不稳定状态在此期间不能发送任何指令),测试环境温湿度数据,并记录数据,同时DHT11的DATA数据线由上拉电阻拉高一直保持高电平; 此时DHT11的DATA引脚处于输入状态,时刻检测外部信号。

 //初始化PA5引脚
 void DHT11_Init(void) {
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
     DHT11_Mode(1);                       // 推挽输出
     GPIO_SetBits(DHT11_PORT, DHT11_PIN); // 将PA5设置为高电平
 }
步骤二:

微处理器的I/O设置为输出同时输出低电平,且低电平保持时间不能小于18ms(最大不得 超过30ms),然后微处理器的I/O设置为输入状态,由于上拉电阻,微处理器的I/O即DHT11的 DATA数据线也随之变高,等待DHT11作出回答信号。发送信号如图所示:

 void DHT11_Start(void) {
     DHT11_Mode(1);  //推挽输出
     GPIO_ResetBits(DHT11_PORT, DHT11_PIN);
     Delay_ms(20);  // 保持20ms起始信号
     GPIO_SetBits(DHT11_PORT, DHT11_PIN);
     Delay_us(60);  // 拉高等待电平被拉低(确保延时完之前,电平被拉低)
 }

四、接收DHT11应答信号:

DHT11的DATA引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后DHT11的 DATA引脚处于输出状态,输出80微秒的低电平作为应答信号,紧接着输出80微秒的高电平通知外设准备接收数据,微处理器的I/O此时处于输入状态,检测到I/O有低电平(DHT11回应信号)后,等待80微秒的高电平后的数据接收,发送信号如图所示:

 uint8_t DHT11_Reply(void) {
     DHT11_Start();    //发送准备读取信号
     uint8_t timeout = 100;
     DHT11_Mode(0);    //切换模式为浮空输入,接收电平变化
     // 等待低电平结束,DHT11首先输出80微秒的低电平作为应答信号
     while (!GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) && timeout > 0) {
         timeout--;
         Delay_us(1);
          
     }
     if (timeout == 0) return 1;  // 超时
     
     //等待高电平结束,低电平之后输出80微秒的高电平通知 外设准备接收数据
     timeout = 100;//重置timeoutDHT11
     while (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) && timeout > 0) {
         timeout--;
         Delay_us(1);        
     }
     return (timeout > 0) ? 0 : 1;  // 返回0表示成功,1表示失败
 }

五、接收DHT11发送的数据一位:

在DHT11发送应答信号结束之后,由DHT11的DATA引脚输出40位数据,微处理器根据I/O电平的变化接收40位数据,位数据 “0”的格式为:50微秒的低电平和26-28微秒的高电平,位数据“1”的格式为:50微秒的低 电平加70微秒的高电平。位数据“0”、“1”格式信号如图所示:

 

读取方法:

可以等待发送位数据“0”的低电平之后的高电平结束之后读取引脚电平,由于位数据“1”的高电平时长比位数据“0”长,如果读取到的为1,则输出的信号为位数据“1”,否则为零。

uint8_t DHT11_ReadBit(void) {
 //DHT11_Reply();          //可用于调试
 int8_t timeout = 100;
 // 等待低电平结束,50微秒的低电平
 while (!GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) && timeout > 0) {
     timeout--;
     Delay_us(1);
 }
 Delay_us(50); //等待超过位数据0值的高电平时间,26-28微秒的高电平
 timeout = -5;
 //检测高电平持续时间,直到高电平结束,或超时timeout>=100
 while (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) && timeout <100) {
     timeout++;
     Delay_us(1);
     
     }
 return (timeout > 0) ? 1 : 0;
 }

六,接收DHT11发送的数据字节:

DHT11传感器通过单总线传输数据,每次通信传输40位,包括湿度的整数部分、湿度的小数部分、温度的整数部分、温度的小数部分以及校验和。每个位的持续时间不同,表示0和1的高低电平持续时间不同,因此需要逐个位地读取并解析。

接收到的40位数据为:

0011 0101(湿度高8位)0000 0000 (湿度低8位)0001 1000(温度高8位 )0000 0100(温度低8位)    0101 0001( 校验位)                                           

校验位=湿度高位+湿度低位+温度高位+温度低位

计算:

00110101+00000000+00011000+00000100=01010001

接收数据正确:

湿度:00110101(整数)=35H=53%RH00000000=00H=0.0%RH=>53%RH+0.0%RH=53.0%RH

温度:00011000(整数)=18H=24℃00000100=04H=0.4℃=>24℃+0.4℃=24.4℃

特殊说明:

当温度低于0℃时温度数据的低8位的最高位置为1。

示例:

-10.1℃表示为0000101010000001

温度:00001010(整数)=0AH=10℃,00000001(小数)=01H=0.1℃

完整时序图:

 //读取一个字节
 uint8_t DHT11_ReadByte(void) {
     uint8_t byte = 0;  // 初始化一个变量来存储最终的字节数据,初值为0
 ​
     for (int i = 0; i < 8; i++) { 
         // 循环8次,因为1个字节等于8个位(bit)
         byte <<= 1; 
         // 将byte变量的当前值左移1位,为新的位数据腾出位置(相当于乘以2)
         byte |= DHT11_ReadBit(); 
         // 读取一个位的数据,使用逻辑或操作(|=)更新byte变量的最低位
     }
     return byte; // 返回组合好的字节数据
 }
 //温度湿度数据读取
 float DHT11_Read_Temperature_Humidity(uint8_t *temp_H, uint8_t *temp_L, uint8_t *humi_H, uint8_t *humi_L) {
     uint8_t buf[5]; // 定义一个数组来存储从DHT11读取的5个字节的数据
     uint8_t i; // 循环计数器
 ​
     if (DHT11_Reply() != 0) { // 检测DHT11的应答信号
         return -1;  // 如果应答失败,返回-1
     }
 ​
     for (i = 0; i < 5; i++) {  // 循环读取5次,因为DHT11每次传输40位数据,即5个字节
         buf[i] = DHT11_ReadByte(); // 调用DHT11_ReadByte函数读取单个字节数据,并存储到buf数组中
     }
 ​
     // 检查数据的校验和是否正确
     if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4]) {
         *humi_H = buf[0]; // 将湿度的高位部分存储到指向的变量中
         *humi_L = buf[1]; // 将湿度的低位部分存储到指向的变量中
         *temp_H = buf[2]; // 将温度的高位部分存储到指向的变量中
         *temp_L = buf[3]; // 将温度的低位部分存储到指向的变量中
         return 0;  // 如果校验和正确,返回0表示成功读取数据
     } else {
         return -2;  // 如果校验和不正确,返回-2表示校验失败
     }
 }

七、示例代码及结果:

通过网盘分享的文件:16-DHT11温湿度模块读取
链接: https://pan.baidu.com/s/10ZGZvjZaA7SQtP8yX2gGpQ?pwd=1gbr 提取码: 1gbr

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2192334.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于深度学习的手势控制模型

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有&#xff1a;中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等&#xff0c;曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝&#xff0c;拥有2篇国家级人工智能发明专利。 社区特色…

理解递归和回溯

文章目录 什么是递归回溯 什么是递归 回溯 //使用递归回溯来给小球找路//说明//1. map 表示地图//2. i,j 表示从地图的哪个位置开始出发 (1,1)//3. 如果小球能到 map[6][5] 位置&#xff0c;则说明通路找到.//4. 约定&#xff1a; 当map[i][j] 为 0 表示该点没有走过 当为 1 表…

【Python】wxPython 高 DPI 缩放问题(笔记本上字体模糊问题)

问题 使用 wxPython 编写的程序在某些高 DPI 的电脑&#xff08;通常是笔记本&#xff09;上显示出来的字体会非常模糊&#xff1a; 事实上 wxPython 是支持高 DPI 的&#xff0c;但是由于我们的程序没有显式指明支持高 DPI&#xff0c;因此系统默认不支持高 DPI&#xff0c;…

Bolt.new:终极自动化编程工具

兄弟们&#xff0c;终极写代码工具来了—— Bolt.new&#xff01;全方位的编程支持&#xff1a; StackBlitz 推出了 Bolt․new&#xff0c;这是一款结合了 AI 与 WebContainers 技术的强大开发平台&#xff0c;允许用户快速搭建并开发各种类型的全栈应用。 它的主要特点是无需…

【小沐学GIS】QGIS导入导出OpenStreetMap数据(QuickMapServices、OSM)

文章目录 1、简介1.1 OpenStreetMap地图1.2 QGIS 2、安装插件2.1 QuickMapServices2.2 OSMDownloader2.3 Qgis2threejs 3、使用插件结语 1、简介 1.1 OpenStreetMap地图 https://www.openstreetmap.org/ https://extract.bbbike.org/ Openstreetmap是一种开源地图&#xff0c…

微服务swagger解析部署使用全流程

1、介绍 swagger是一个在线接口说明文档&#xff0c;在代码中通过注解的方式将说明问题集成到项目&#xff0c;代码发生修改&#xff0c;说明文档同步修改&#xff0c;前后台联调可以快速同步数据。 2、应用 1、引入依赖 <dependency><groupId>io.springfox<…

如何使用ssm实现基于Web的穿戴搭配系统的设计与实现+vue

TOC ssm784基于Web的穿戴搭配系统的设计与实现vue 第1章 绪论 1.1 研究背景 互联网概念的产生到如今的蓬勃发展&#xff0c;用了短短的几十年时间就风靡全球&#xff0c;使得全球各个行业都进行了互联网的改造升级&#xff0c;标志着互联网浪潮的来临。在这个新的时代&…

新机配置Win11

Win11跳联网 在连接网络的界面输入ShiftF10打开命令行&#xff0c;然后输入oobe\bypassnro然后会重启&#xff0c;在联网的界面就可以进行跳过了。 编码 在中国大陆Windows使用的编码是GBK编码 查看电脑系统版本 WinR输入winver即可 桌面图标 设置->个性化->主题…

Art. 1 | 信号、信息与消息的区别及其在通信中的应用

信号、信息与消息的区别及其在通信中的应用 通信技术是现代社会的基石&#xff0c;其广泛应用于日常生活的各个方面。从手机、互联网到企业信息管理&#xff0c;通信系统无处不在。在这一技术领域中&#xff0c;信号、信息和消息是三大基础概念&#xff0c;支撑着整个通信系统…

03 去重排序

题目&#xff1a; 桶排序变体&#xff1a; #include<iostream> #include<algorithm> using namespace std; #define M 100005 int a[M];int main() {int N;cin>>N;int count0;for(int i1;i<N;i){int temp;cin>>temp;if(a[temp]1){continue;}else{a…

[C语言]第十一节 函数递归一基础知识到高级技巧的全景探索

目录 11.1. 递归是什么&#xff1f; 11.1.1 递归的思想&#xff1a; 11.2 递归的限制条件 举例1&#xff1a;求n的阶乘 画图推演 举例2&#xff1a;顺序打印⼀个整数的每⼀位 画图推演 11.3. 递归与迭代 举例3&#xff1a;求第n个斐波那契数 11.1. 递归是什么&#xff…

oh-topic-editor: OpenHarmony HarmonyOS平台上基于RichEditor实现的支持添加话题、@用户的文本编辑组件

需求 在App开发中&#xff0c;我们常常会遇到发布文章、评论的时候需要添加话题或者用户的需求&#xff0c;就像微博那样。这在Android、iOS或者其他平台上都有现成的组件可供使用&#xff0c;但是HarmonyOS NEXT作为一个新兴平台&#xff0c;三方库实在匮乏&#xff0c;连微博…

SpringBoot中,接口签名,通用方案,以确保接口的安全性

1. 为什么需要接口签名&#xff1f; 接口签名目的&#xff1a;防止第三方伪造请求。请求伪造&#xff1a;未经授权的第三方构造合法用户的请求来执行不希望的操作。转账接口示例&#xff1a;展示了如果接口没有安全措施&#xff0c;第三方可以轻易伪造请求&#xff0c;例如将资…

用户在网页上输入一个网址,它整个页面响应的流程是什么?

目录 一、流程的大致过程 二、流程的详细分析 1. 浏览器先分析超链接中的URL 2. DNS解析 3. 建立TCP连接 建立连接&#xff08;三次握手&#xff09; HTTP中的请求报文 4. 浏览器发送HTTP请求 5. 服务器处理请求并发送响应 HTTP的响应报文 6. 浏览器接收响应 7. 渲…

After-kaoyan

知乎 - 安全中心 有态度&#xff0c;有回应&#xff0c;有温度&#xff0c;是跟双鱼相处的基础 我今天跟大家泄漏一个秘密&#xff0c;这个秘密也很简单&#xff0c;就是我每次遇到困难险阻时候我从不退缩&#xff0c;我也不会想着&#xff1a;“算了吧&#xff0c;我做不到&a…

基于Springboot+Vue的零食批发商仓库管理系统(含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 在这个…

Python调试技巧:高效定位与修复问题

Python调试技巧&#xff1a;高效定位与修复问题 在Python编程过程中&#xff0c;调试是不可避免的重要环节。无论是刚接触编程的初学者还是经验丰富的开发者&#xff0c;都可能会遇到代码运行不符合预期的情况。高效的调试技巧不仅能帮助我们快速找到问题&#xff0c;还能减少…

Graphiti:如何让构建知识图谱变得更快、更具动态性?

扩展大语言模型数据提取&#xff1a;挑战、设计决策与解决方案 Graphiti 是一个用于构建和查询动态、时间感知的知识图谱的 Python 库。它可以用于建模复杂、不断演变的数据集&#xff0c;并确保 AI 智能体能够访问它们完成非平凡任务所需的数据。它是一个强大的工具&#xff…

9个微服务最佳实践

1⃣分离数据存储&#xff1a;独立数据库&#xff0c;提升灵活性。 2⃣代码成熟度一致&#xff1a;质量稳定&#xff0c;避免技术债务 3⃣独立构建流程&#xff1a;独自构建&#xff0c;快速部署。 4⃣单一职责原则&#xff1a;业务功能单一&#xff0c;简化维护。 5⃣容器化部署…

Android车载——VehicleHal初始化(Android 11)

1 概述 VehicleHal是AOSP中车辆服务相关的hal层服务。它主要定义了与汽车硬件交互的标准化接口和属性管理&#xff0c;是一个独立的进程。 2 进程启动 VehicleHal相关代码在源码树中的hardware/interfaces/automotive目录下 首先看下Android.bp文件&#xff1a; cc_binary …