介绍

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 PB12
GPIO_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); // 拉低至少18ms
dht11_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,最低位补0
if (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博客

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

STM32实战——DHT11温湿度获取并展示的更多相关文章

  1. STM32驱动DHT11温湿度传感器

    DHT11 是一款湿温度一体化的数字传感器.该传感器包括一个电阻式测湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接.通过单片机等微处理器简单的电路连接就能够 实时的采集本地湿度和温 ...

  2. DHT11温湿度传感器编程思路以及代码的实现(转载)

    源自:https://blog.csdn.net/qq_34952376/article/details/81193938 在我们刚开始进入单片机的学习中,练习写传感器的时序是必不可少的,其实我比较推 ...

  3. Arduino和C51开发DHT11温湿度传感器

    技术:51单片机.Arduino.DHT11.温湿度传感器.传感器   概述 学习单片机离不开对传感器的学习,本文主要介绍DHT11温湿度传感器的使用方法,同学也可以了解更多的传感器,这对你以后开发产 ...

  4. 【雕爷学编程】Arduino动手做(55)--DHT11温湿度传感器

    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践(动手试试)出真知的理念,以学习和交流为目的,这里准备 ...

  5. STC15系列通用-STC15F2K60S2/STCW4K32S4读取DHT11温湿度传感器数据串口输出代码实例工程免费下载

    //为了方便大家调试,另附程序工程共大家下载,下载地址:https://www.90pan.com/b1908750 ​ //************************** //程序说明:stc ...

  6. 在树莓派上读取DHT11温湿度传感器-python代码实现及常见问题(全面简单易懂)

    最近由于自己的课题需要,想要用在树莓派上使用DHT11温湿度传感器来读取空气中温湿度,遇到了几个问题,解决之后也对之前的知识进行了回顾,总结,特整理如下,希望能给也在学习树莓派的小伙伴们带来一些帮助. ...

  7. STM32—驱动DHT11数字温湿度传感器

    文章目录 DHT11模块简介 DHT11数据传输 DHT11通信时序 代码实现 相关引脚初始化 复位模块 判断响应模块 读取数据包模块 DHT11模块简介 DHT11数字温湿度传感器,用来测量环境的温 ...

  8. 四博智慧物联系统入门示例-1.增加一个DHT11温湿度传感器

    1.准备工作 DOIT农业控制开发板或者esp32模组,并下载 四博智慧物联系统快速入门-2.准备工作 章节中的固件 DHT11连接在端口01 使用快速入门注册的管理账号和用户 2.配置网络 3.绑定 ...

  9. DL4J实战之六:图形化展示训练过程

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本篇是<DL4J实战>系列的第六 ...

  10. 【读书笔记《Bootstrap 实战》】2.作品展示站点

    假设我们已经想好了要给自己的作品弄一个在线站点.一如既往,时间紧迫.我们需要快一点,但作品展示效果又必须专业.当然,站点还得是响应式的,能够在各种设备上正常浏览,因为这是我们向目标客户推销时的卖点.这 ...

随机推荐

  1. 常用bat代码

    清除空文件夹 | 清理空文件夹 | 删除空文件夹 @echo off for /f "tokens=*" %%i in ('dir/s/b/ad^|sort /r') do rd ...

  2. Qt编写可视化大屏电子看板系统24-模块2当月计划

    一.前言 延续分层模块化的设计思路,当月计划模块主要包括模具达成率.零件达成率.零件数.每日工序达成数5个子模块,其中模具达成率采用自定义控件环形图展示,比如计划多少达成多少,达成作为进度:零件达成率 ...

  3. MySql中的driverClassName、url

    在Java桌面开发或者Java Web开发(基于SSM框架)配置MySQL数据源时,driverClassName属性如果填错了,会导致了这一系列错误.归结其原因就是 mysql-connector- ...

  4. postgresql-10.12-2-windows-x64安装成功后在安装postgis-bundle-pg96x64-setup-2.5.3-1时提示Spatial database creation failed

    问题描述: postgresql-10.12-2-windows-x64安装成功后在安装postgis-bundle-pg96x64-setup-2.5.3-1时提示Spatial database ...

  5. Java中使用Callable和FutureTask创建多线程的基本用法

    我们先定义一个Callable任务MyCallableTask: 步骤1:创建Callable实现类,并实现call()接口 package cn.cetc;//包名可自定义 import java. ...

  6. vue3.0实现炫酷的随机验证码功能

    先上图 接下来楼一眼实现代码 这里说明一下,我用到了vue3.0,vant3.0以及阿里图标,vant 很人性化针对vue3.0新出了个vant3.0版本,阿里则是适配vue3.0的.我们将verif ...

  7. 深入解析 Spring AI 系列:以OpenAI与Moonshot案例为例寻找共同点

    今天,我们将重点探讨对接的业务逻辑.为了帮助大家更直观地掌握其中的规律性,我将通过对比OpenAI与<月之暗面>中的Moonshot两个案例来阐述这一点.通过这样的对比,大家可以更清晰地看 ...

  8. .NET 异步 /Task

    老版本的写法经常是以BeginXXX, EndXXX, 或者xx.xxxAsycn(........) 新的支持 async异步关键字配合Task可读性和易用性比老板好多了. 新旧例子: using ...

  9. biancheng-Spring MVC

    MVC设计模式简介 http://c.biancheng.net/spring_mvc/ MVC 设计模式一般指 MVC 框架,M(Model)指数据模型层,V(View)指视图层,C(Control ...

  10. SM4代码实现

    算法过程 更多的原理介绍参考:SM4原理介绍 代码实现 S盒实现 #include <stdio.h> /* SM4-S盒实现: 由三个复合函数组成,S(x)=L(I(L(x))),其中L ...