STM32实战——DHT11温湿度获取并展示

news/2025/3/3 23:03:31/文章来源:https://www.cnblogs.com/penggeon/p/18749612

介绍

DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,包括一个电阻式感湿元件和一个NTC测温元件,可以用来测量温度和湿度。

硬件连线

注意
本实验使用STM32F103C8T6芯片作为主控,使用DHT11(带上拉电阻)模块作为温湿度采集装置。

接线如下表所示:

名称 STM32 注释
VCC 3.3V 供电 3.3V
OUT PB13(任意一个GPIO口即可) 串行数据
GND GDN 接地

由于使用了上拉电阻,因此STM32与DHT11的通信类似于软件模拟IIC通信协议。使用开漏输出模式(OD)控制PB13的高低电平。(如果不懂什么是软件模拟IIC的话,请移步软件I2C读写MPU6050

DHT11

本教程使用DHT11模块如下图所示:

DHT11协议

概述

STM32与 DHT11之间的通信,采用单总线数据格式,一次通信时间4ms左右。

总体通信流程为:开始信号->响应信号->数据传输。

STM32发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束。DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据。

注:DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集。采集数据后转换到低速模式。

总体操作时序如下图所示:

开始信号(STM32控制总线)

首先主机拉低总线至少 18ms,然后再拉高总线,延时 20~40us,取中间值 30us,此时复位信号发送完毕。

注意
是拉低总线18毫秒,不是18微秒,搞错的话是不能正常通信的!

响应信号(DHT11控制总线)

DHT11 检测到复位信号后,触发一次采样,并拉低总线 80us 表示响应信号,告诉主机数据已经准备好了;然后 DHT11 拉高总线 80us,之后开始传输数据。

数据传输(DHT11控制总线)

之后,每 1bit 数据都以 50us 低电平时隙开始。

DHT11 以高电平的长短定义数据位是 0 还是 1。当 50us 低电平时隙过后拉高总线,高电平持续 26~28us 表示数据“0”;持续 70us 表示数据“1”。如下表所示:

输出 表示方法
数字0 50us低电平开始后,26-28us的高电平表示0
数字1 50us低电平开始后,70us的高电平表示1

数据传输结束

当最后一bit数据传送完毕后,DHT11拉低总线50us,随后释放总线,由上拉电阻拉高进入空闲状态。

DHT11数据格式

一次完整的数据传输为40bit,高位先出。数据分小数部分和整数部分,数据格式:

  • 8bit湿度整数数据
  • 8bit湿度小数数据
  • 8bit温度整数数据
  • 8bit温度小数数据
  • 8bit校验和

若数据传送正确,则

校验和数据 = “8bit 湿度整数数据 +8bit 湿度小数数据+8bit温度整数数据 +8bit 温度小数数据”所得结果的末8位。

STM32代码

提示
将Tab缩进更改为2空格体验更好。

注意
需要添加delay.h、oled.h等头文件时,还请自行添加。

DHT11驱动代码

头文件

宏定义“使用引脚”和“控制IO输出1和0的函数”

#ifndef __DHT11_H
#define __DHT11_H// 定义引脚
#define DHT11_GPIO_Port GPIOB
#define DHT11_GPIO_Pin GPIO_Pin_13// 定义函数
#define dht11_high GPIO_SetBits(DHT11_GPIO_Port, DHT11_GPIO_Pin)
#define dht11_low GPIO_ResetBits(DHT11_GPIO_Port, DHT11_GPIO_Pin)
#define DHT11_IN GPIO_ReadInputDataBit(DHT11_GPIO_Port, DHT11_GPIO_Pin)void DH11_GPIO_Init(void);
uint8_t DHT11RstAndCheck(void);
uint8_t DHT11ReadByte(void);
uint8_t DHT11ReadData(uint8_t *Temp_H,uint8_t *Temp_L,uint8_t *Humi_H,uint8_t *Humi_L);#endif

初始化

初始化DHT11使用引脚

/*** @brief  初始化DHT11* @param  无* @retval 无*/
void DH11_GPIO_Init(void)
{// 开启APB2中的GPIOB时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);// 配置GPIO PB12GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_OD; // 开漏输出GPIO_InitStructure.GPIO_Pin   = DHT11_GPIO_Pin;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStructure);
}

复位和检查响应

该函数将“STM32发送开始信号”与“STM32接受响应信号”放置一起

/*** @brief  复位和检测响应* @param  无* @retval 1:响应成功, 0:响应失败*/
uint8_t DHT11RstAndCheck(void)
{uint8_t timer = 0;		// 计数器__set_PRIMASK(1);     // 关总中断dht11_low; 	          // 输出低电平Delay_ms(20);    	    // 拉低至少18msdht11_high; 	        // 输出高电平Delay_us(30);     	  // 拉高20~40us// 检测是否存在第一个低电平while (!DHT11_IN)     // 等待总线拉低,DHT11会拉低40~80us作为响应信号{timer++;            // 总线拉低时计数Delay_us(1);}if (timer>100 || timer<20) // 判断响应时间{__set_PRIMASK(0);      // 开总中断return 0;}// 检测是否存在第二个高电平timer = 0;	// 重置计数器while (DHT11_IN)          // 等待DHT11释放总线,持续时间40~80us{timer++;               	// 总线拉高时计数Delay_us(1);}__set_PRIMASK(0);          // 开总中断if (timer>100 || timer<20) // 检测响应信号之后的高电平{return 0;}// 均存在, 则返回1, 响应正常return 1;
}

获取一个字节数据

/*** @brief  读取一字节数据* @param  无* @retval 读到的数据*/
uint8_t DHT11ReadByte(void)
{uint8_t i;uint8_t byt = 0;__set_PRIMASK(1);      // 关总中断for (i=0; i<8; i++){while (DHT11_IN);  // 等待低电平,数据位前都有50us低电平时隙while (!DHT11_IN); // 等待高电平,开始传输数据位Delay_us(40);byt <<= 1;         // 因高位在前,所以左移byt,最低位补0if (DHT11_IN)      // 将总线电平值读取到byt最低位中{byt |= 0x01;}}__set_PRIMASK(0);      // 开总中断return byt;
}

获取DHT11全部数据

/*** @brief  读取数据* @param  Temp_H 温度整数部分* @param  Temp_L 温度小数部分* @param  Humi_H 湿度整数部分* @param  Humi_L 湿度小数部分* @retval 0-成功,1-失败*/
uint8_t DHT11ReadData(uint8_t *Temp_H,uint8_t *Temp_L,uint8_t *Humi_H,uint8_t *Humi_L)
{uint8_t sta = 0;uint8_t i;uint8_t buf[5];if (DHT11RstAndCheck())       // 检测响应信号{for(i=0;i<5;i++)            // 读取40位数据{buf[i]=DHT11ReadByte(); 	// 读取1字节数据}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]; // 温度 小数部分数据}sta = 0;}else // 响应失败返回-1{*Temp_H = 0;*Temp_L = 0;*Humi_H = 0;*Humi_L = 0;sta = 1;}return sta;    
}

main函数

int main(void)
{DH11_GPIO_Init(); // DHT11初始化uint8_t Temp_H = 0;uint8_t Temp_L = 0;uint8_t Humi_H = 0;uint8_t Humi_L = 0;while (1){// 获取数据DHT11ReadData(Temp_H,Temp_L,Humi_H,Humi_L);// 显示温湿度数据OLED_ShowNum(1,7,Temp_H,2);	 	// 温度 整数部分OLED_ShowNum(1,10,Temp_L,1);	// 温度 小数部分OLED_ShowNum(2,7,Humi_H,2);  	// 湿度 整数部分OLED_ShowNum(2,10,Humi_L,1); 	// 湿度 小数部分}
}

实验效果

实验效果如下图所示:

参考链接

本实验实现过程中参考:

DHT11详细介绍(内含51和STM32代码)-CSDN博客

STM32外接DHT11显示温湿度_stm32与dht11连接用了什么协议-CSDN博客

如果有什么问题和建议,还请读者指出

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows平台调试器原理与编写03.单步

调试器原理与编写03.单步-C/C++基础-断点社区-专业的老牌游戏安全技术交流社区 - BpSend.net 单步 TF - 置位(置1 复位就是置0) 单步步入 -- 遇到call便入单步步过 -- 遇到call不入区分一条指令是不是call指令: 通过反汇编引擎,反汇编出来是个 call 说明 就是 call指令 代码实现…

day14 服务管理篇的学习

day14 服务管理的学习 1.Linux的默认提供的服务 1. shhd 的命令 [root@linux-yzk ~]# netstat -tnlp | grep sshd tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1137/sshd tcp 0 0 127.0.0.1:6010 0.0.0…

关于ADAC儿童安全座椅排名

ADAC官网地址 直接翻看排行榜, 注意, 分数越小,排名越靠前。 国内推荐使用 亚马逊中国这样的app或者网站进行购买,海外直邮。 避免在国内买到贴牌货, 国内, 懂得都懂, 5星批发部, 实际使用的和送检的不是同一种, AB货。当然不是所有的国内的商品都是AB货。ADAC不支持主…

六、MyBatis特殊的SQL:模糊查询、动态设置表名、校验名称唯一性

六、MyBatis特殊的SQL:模糊查询、动态设置表名、校验名称唯一性@目录六、MyBatis特殊的SQL6.1 模糊查询6.2 动态设置表名6.3 校验名称唯一性本人其他相关文章链接 六、MyBatis特殊的SQL 6.1 模糊查询方式1:select * from litemall_user where username like %${username}%(推…

AI生成代码测试,前端加后端

首先是话术, 让我们先理顺一下项目的逻辑,对于这样一个WEB管理系统界面,我们有多个思路,如功能模块化,或者前后端分离。 由于我们的MIS系统相对简单,我们可以将整个开发流程进行功能化细分。 首先,完成基础的环境配置。 需求描述: 请设计一个仓储管理系统原型系统,该系…

目前国内可用Docker镜像源汇总(截至2025年2月)

[目前国内可用Docker镜像源汇总(截至2025年2月) - CoderJia](https://www.coderjia.cn/archives/dba3f94c-a021-468a-8ac6-e840f85867ea) 在国内使用 Docker 的朋友们,可能都遇到过配置镜像源来加速镜像拉取的操作。然而,最近几个月发现许多曾经常用的国内镜像站(包括各种…

我的lua使用初体验

本文记录作者第一次使用lua的一次实践,主要借助lua来保证检查锁和释放锁的原子性使用lua实现检查和删除分布式锁的原子性很多时候出现并发问题的根本原因在于检查和操作不是同一个操作,不具有原子性,所以中间会被其他线程插一脚。所以我们需要有一种工具保证这两种操作的原子…

三剑客与正则系列-sed命令

1.概述核心功能:取行,过滤,替换修改文件内容 难点:后向引用(截取). sed stream editor流编辑器.2.格式命令 选项 详细格式 参数sed 选项 条件动作 文件找谁干啥找谁:条件,匹配哪一行,哪些行. 干啥:动作,增删改查. #显示文件的第3行 sed -n 3p /etc/passwd选项 说明-n 取消默认输…

加速PyTorch模型训练技巧

Pytorch-Lightning 可以在Pytorch的库Pytorch-lightning中找到我们在这里讨论的每一个优化。Lightning是在Pytorch之上的一个封装,它可以自动训练,同时让研究人员完全控制关键的模型组件。Lightning使用最新的最佳实践,并将你可能出错的地方最小化。 我们为MINST定义为Light…

能力全面提升综合题单-练习

Part1 语言基础题 P1089 [NOIP 2004 提高组] 津津的储蓄计划import java.util.Scanner;// P1089 [NOIP 2004 提高组] 津津的储蓄计划 public class P1089 {public static void main(String[] args) {Scanner in = new Scanner(System.in);int[] budget = new int[12];for (int …

kettle插件-git/svn版本管理插件

场景:大家都知道我们平时使用spoon客户端的时候时无法直接使用git的,给我们团队协作带来了一些小问题,需要我们本机单独安装git客户端进行手动上传trans或者job。 我们团队成员倪老师开发了一款kettle的git插件,帮我们解决了这个大难题,大大方便了我们团队协作,今天一起来…