基于STM32_DHT11单总线温湿度传感器驱动

基于STM32_DHT11单总线温湿度传感器驱动


文章目录

  • 基于STM32_DHT11单总线温湿度传感器驱动
  • 前言
  • 一、DHT11?
  • 二、原理
    • 1.时序
      • 1.主机复位信号和 DHT11 响应信号
      • 2.信号‘0’的表示
      • 3.信号‘1’的表示
      • 4.整个数据信号收发流程
    • 2.数据结构
  • 三、驱动
    • 1 .h文件:
    • 2 .c文件:


前言

趁热打铁,接上篇DS18B20的介绍再出一篇关于单总线传感器DHT11的介绍,相比之下,DHT11的时序和操作更简单易懂。


一、DHT11?

DHT11 是广州奥松有限公司生产的一款湿温度一体化的数字传感器。该传感器包括一个电阻式测湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接。通过单片机等微处理器简单的电路连接就能够实时的采集本地湿度和温度。 DHT11 与单片机之间能采用简单的单总线进行通信,仅仅需要一个I/O 口。传感器内部湿度和温度数据 40Bit 的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。 DHT11 功耗很低, 5V 电源电压下,工作平均最大电流 0.5mA。性能指标和特性如下:
■ 工作电压范围: 3.5V-5.5V
■ 工作电流 :平均 0.5mA
■ 湿度测量范围:20-90%RH
■ 温度测量范围:0-50℃
■ 湿度分辨率 : 1%RH 8 位
■ 温度分辨率 : 1℃ 8 位
■ 采样周期 : 1S
■ 单总线结构
■ 与 TTL 兼容(5V)
在这里插入图片描述
DHT11 数字湿温度传感器连接方法极为简单。第一脚接电源正,第四脚接电源地端。数据端为第二脚。可直接接主机(单片机)的 I/O 口。为提高稳定性,建议在数据端和电源正之间接一只 4.7K 的上拉电阻。第三脚为空脚,此管脚悬空不用。

二、原理

1.时序

1.主机复位信号和 DHT11 响应信号

在这里插入图片描述
主机拉低信号维持18ms后释放总线(变为高电平),20-40us后,DHT11会将总线拉低维持40-50微秒再将总线拉高维持40-50微秒,主机在对应时间段内依次检测到低电平信号和高电平信号,表示有从机在位,否则从机不在位。

2.信号‘0’的表示

以12-14微秒的低电平作为始,随之而来的高电平信号维持26-28微秒后拉低,此时序表示信号 0
在这里插入图片描述

3.信号‘1’的表示

同样以12-14微秒的低电平作为始,随之而来的高电平信号维持116-118微秒后拉低,此时序表示信号 1
在这里插入图片描述
总结来讲就是看高电平时间维持的长短,可使用while循环等待电平信号是否为低,循环依次延时1us,计数器+1,如果跳出循环则判断计数器数值,小于30则为0,大于30且小于120则为1,大于120则为错误。

4.整个数据信号收发流程

在这里插入图片描述

2.数据结构

DHT11数字湿温度传感器采用单总线数据格式。即,单个数据引脚端口完成输入输出双向传输。其数据包由5Byte( 40Bit)组成。数据分小数部分和整数部分,具体格式在下面说明。
         一次完整的数据传输为40bit,高位先出。
         数据格式: 8bit湿度整数数据+8bit湿度小数数据
                +8bit温度整数数据+8bit温度小数数据
                +8bit校验和
         校验和数据为前四个字节相加。
传感器数据输出的是未编码的二进制数据。数据(湿度、温度、整数、小数)之间应该分开处理。如果,某次从传感器中读取如下5Byte数据:
        在这里插入图片描述
由以上数据就可得到湿度和温度的值,计算方法:
        humi (湿度)= byte4 . byte3=45.0 (%RH)
        temp (温度)= byte2 . byte1=28.0 ( ℃ )
        jiaoyan(校验)= byte4+ byte3+ byte2+ byte1=73(=humi+temp)(校验正确)
注意: DHT11一次通讯时间最大3ms,主机连续采样间隔建议不小于100ms。

三、驱动

1 .h文件:

#ifndef __DHT11_H
#define __DHT11_H#include "stdio.h"	
#include "Config.h"  			//包含初始化GPIO,初始化时钟
#include "SysTick.h"/********************************************DHT11 devier********************************************/
#define DHT11_IS_READY      (1u)
#define DHT11_NOT_READY     (0u) #define DHT11_DQ_IN()       {GPIOG->MODER&=~(3<<(9*2));GPIOG->MODER|=0<<9*2;}//PG9 输入模式
#define DHT11_DQ_OUT()      {GPIOG->MODER&=~(3<<(9*2));GPIOG->MODER|=1<<9*2;}//PG9 输出模式#define DHT11_DQ_PORT       GPIOG
#define DHT11_DQ_PIN        GPIO_Pin_9#define DHT11_DQ_LOW        GPIO_ResetBits(DHT11_DQ_PORT,DHT11_DQ_PIN) 
#define DHT11_DQ_HIGH       GPIO_SetBits(DHT11_DQ_PORT,DHT11_DQ_PIN) #define DHT11_DQ_STATUS     GPIO_ReadInputDataBit(DHT11_DQ_PORT,DHT11_DQ_PIN)		//读取DQ状态#define DHT11_delay_us(a)   SysCtlDelayus(a)			      //延时函数us
#define DHT11_delay_ms(a)   SysCtlDelayus(a * 1000)			//延时函数ms#define DHT11_ACK_TIMEOUT           (uint8_t)100	        //等待DHT11响应信号延时
#define DHT11_BIT_START_TIMEOUT     (uint8_t)100	        //1bit起始信号延时时间
#define DHT11_BIT_STATUS_TIMEOUT    (uint8_t)130	        //表示 0 的延时时间typedef enum
{DHT11_1 = 0,DHT11_2,DHT11_3,DHT11_4,DHT11_Num_Counter
}DHT11_Num;typedef struct
{uint8_t DHT11_IndexNumber;float DHT11_Temp;float DHT11_Humi;
}DHT11_Data_Type;extern uint8_t DHT11_Init(void);
extern void DHT11_Reset(void);
extern uint8_t DHT11_GetTemp_Main(void);
extern float DHT11_Get_Temperature(uint8_t Index);
extern float DHT11_Get_Humidity(uint8_t Index);#endif
## 1.时序

.c文件:

#ifndef __DHT11_H
#define __DHT11_H#include "stdio.h"	
#include "Config.h"  			//包含初始化GPIO,初始化时钟
#include "SysTick.h"/********************************************DHT11 devier********************************************/
#define DHT11_IS_READY      (1u)
#define DHT11_NOT_READY     (0u) #define DHT11_DQ_IN()       {GPIOG->MODER&=~(3<<(9*2));GPIOG->MODER|=0<<9*2;}//PG9 输入模式
#define DHT11_DQ_OUT()      {GPIOG->MODER&=~(3<<(9*2));GPIOG->MODER|=1<<9*2;}//PG9 输出模式#define DHT11_DQ_PORT       GPIOG
#define DHT11_DQ_PIN        GPIO_Pin_9#define DHT11_DQ_LOW        GPIO_ResetBits(DHT11_DQ_PORT,DHT11_DQ_PIN) 
#define DHT11_DQ_HIGH       GPIO_SetBits(DHT11_DQ_PORT,DHT11_DQ_PIN) #define DHT11_DQ_STATUS     GPIO_ReadInputDataBit(DHT11_DQ_PORT,DHT11_DQ_PIN)		//读取DQ状态#define DHT11_delay_us(a)   SysCtlDelayus(a)			      //延时函数us
#define DHT11_delay_ms(a)   SysCtlDelayus(a * 1000)			//延时函数ms#define DHT11_ACK_TIMEOUT           (uint8_t)100	        //等待DHT11响应信号延时
#define DHT11_BIT_START_TIMEOUT     (uint8_t)100	        //1bit起始信号延时时间
#define DHT11_BIT_STATUS_TIMEOUT    (uint8_t)130	        //表示 0 的延时时间typedef enum
{DHT11_1 = 0,DHT11_2,DHT11_3,DHT11_4,DHT11_Num_Counter
}DHT11_Num;typedef struct
{uint8_t DHT11_IndexNumber;float DHT11_Temp;float DHT11_Humi;
}DHT11_Data_Type;extern uint8_t DHT11_Init(void);
extern void DHT11_Reset(void);
extern uint8_t DHT11_GetTemp_Main(void);
extern float DHT11_Get_Temperature(uint8_t Index);
extern float DHT11_Get_Humidity(uint8_t Index);#endif

2 .c文件:

 #include "DHT11.h"//#define DHT11_MORE_THAN_ONE DHT11_Data_Type DHT11_Temp[DHT11_Num_Counter] = {{DHT11_1,0.0,0.0},{DHT11_2,0.0,0.0},{DHT11_3,0.0,0.0},{DHT11_4,0.0,0.0}   };static uint8_t DHT11_Read_Bit(void);
static uint8_t DHT11_Read_Byte(void);
static uint8_t DHT11_Check(void);/************************************************************************************
*@fuction	:DHT11_Init
*@brief		:
*@param		:--
*@return	:void
*@author	:_Awen
*@date		:2022-12-04
************************************************************************************/
extern uint8_t DHT11_Init(void)
{DHT11_Reset();if(DHT11_Check() == DHT11_IS_READY){return DHT11_IS_READY;}
}/************************************************************************************
*@fuction	:DHT11_Reset
*@brief		:
*@param		:--
*@return	:void
*@author	:_Awen
*@date		:2022-12-04
************************************************************************************/
void DHT11_Reset(void)
{//DHT11 复位时序:DQ输出模式 DQ = 0(20us), DQ = 1(30us.DHT11_DQ_OUT();DHT11_DQ_LOW;DHT11_delay_ms(20);DHT11_DQ_HIGH;DHT11_delay_us(30);
}/************************************************************************************
*@fuction	:DHT11_Check
*@brief		:
*@param		:--
*@return	:1-device ok/0-device error
*@author	:_Awen
*@date		:2022-12-04
************************************************************************************/
uint8_t DHT11_Check(void)
{uint8_t wait_time = 0;uint8_t Ready_Dev = 0;//DQ输入模式DHT11_DQ_IN();//等待DQ脚被DHT11拉低while((DHT11_DQ_STATUS) && (wait_time < DHT11_ACK_TIMEOUT)){wait_time++;DHT11_delay_us(1);};if(wait_time >= DHT11_ACK_TIMEOUT){//如果等待时间超时,则退出等待return (uint8_t)DHT11_NOT_READY;}else{wait_time = 0;while((!DHT11_DQ_STATUS) && (wait_time < DHT11_ACK_TIMEOUT)){wait_time++;DHT11_delay_us(1);};if(wait_time >= DHT11_ACK_TIMEOUT){//如果等待时间超时,则退出等待return (uint8_t)DHT11_NOT_READY;}else{//如果未超时,则说明设备存在return (uint8_t)DHT11_IS_READY;              }}
}/************************************************************************************
*@fuction	:DHT11_Read_Bit
*@brief		:
*@param		:--
*@return	:void
*@author	:_Awen
*@date		:2022-12-04
************************************************************************************/
static uint8_t DHT11_Read_Bit(void) 			 //read one bit
{uint8_t wait_time = 0;uint8_t Bit_Status = 0;DHT11_DQ_IN();//等待DQ脚被DHT11拉低while((DHT11_DQ_STATUS) && (wait_time < 100)){wait_time++;DHT11_delay_us(1);}if(wait_time >= 100){//如果等待时间超时,则出现错误,退出等待Bit_Status = 0xFF;}else{wait_time = 0;//等待DQ脚被DHT11抬高while((!DHT11_DQ_STATUS) && (wait_time < DHT11_BIT_START_TIMEOUT)){wait_time++;DHT11_delay_us(1);}if(wait_time >= DHT11_BIT_START_TIMEOUT){//如果等待时间超时,则退出等待Bit_Status = 0xFF;}else{//如果未超时,则说明1bit起始信号正常,wait_time = 0;//进入高电平时长判断while((DHT11_DQ_STATUS) && (wait_time < DHT11_BIT_STATUS_TIMEOUT)){wait_time++;DHT11_delay_us(1);}//如果高电平保持时间小于50us则为0,大于50us则为1if(wait_time <= 50){                 Bit_Status = 0;}else if((50 < wait_time) && (wait_time <= 150)){Bit_Status = 1;              }else{Bit_Status = 0xFF;}}}return Bit_Status;
}
/************************************************************************************
*@fuction	:DHT11_Read_Byte
*@brief		:
*@param		:--
*@return	:void
*@author	:_Awen
*@date		:2022-12-04
************************************************************************************/
static uint8_t DHT11_Read_Byte(void)
{uint8_t i = 0 ,Bit_Status = 0,aByte = 0;//DQ为输入模式DHT11_DQ_IN();for (i = 0; i < 8; i++){//高位先出Bit_Status = DHT11_Read_Bit();aByte = (aByte << 1) | Bit_Status;}return aByte;
}/************************************************************************************
*@fuction	:DHT11_CheckSumFun
*@brief		:
*@param		:--
*@return	:void
*@author	:_Awen
*@date		:2022-12-04
************************************************************************************/
uint8_t DHT11_CheckSumFun(uint8_t* MsgArr, uint8_t Lengh){uint8_t CheckSum = 0;uint8_t i = 0;if((MsgArr == NULL_Ptr) && (Lengh == NULL)){return CheckSum;}for(i = 0; i < Lengh; i++){CheckSum = (CheckSum + MsgArr[i]) % 256;}return CheckSum;}/************************************************************************************
*@fuction	:SplicingFloat
*@brief		:
*@param		:--
*@return	:void
*@author	:_Awen
*@date		:2022-12-04
************************************************************************************/
float SpliceFloat(uint8_t Integer, uint8_t Decimal)
{float Temp = Integer;if(Decimal & 0x80) {Temp = -1 - Temp;}Temp += (Decimal & 0x0f) * 0.1;return Temp;
}/************************************************************************************
*@fuction	:DHT11_GetTemp_Main
*@brief		:
*@param		:--
*@return	:void
*@author	:_Awen
*@date		:2022-12-04
************************************************************************************/
extern uint8_t DHT11_GetTemp_Main(void)
{uint8_t i = 0,temp[5];DHT11_Reset();if(DHT11_Check() == DHT11_IS_READY){for(i = 0;i < 5;i++){temp[i] = DHT11_Read_Byte();}if(DHT11_CheckSumFun(temp,4) == temp[4]){DHT11_Temp[0].DHT11_Humi = SpliceFloat(temp[0],temp[1]);DHT11_Temp[0].DHT11_Temp = SpliceFloat(temp[2],temp[3]);return E_OK;}}
}/************************************************************************************
*@fuction	:DHT11_Get_Temp
*@brief		:
*@param		:--
*@return	:void
*@author	:_Awen
*@date		:2022-12-04
************************************************************************************/
extern float DHT11_Get_Temperature(uint8_t Index)
{return DHT11_Temp[Index].DHT11_Temp;
}/************************************************************************************
*@fuction	:DHT11_Get_Temp
*@brief		:
*@param		:--
*@return	:void
*@author	:_Awen
*@date		:2022-12-04
************************************************************************************/
extern float DHT11_Get_Humidity(uint8_t Index)
{return DHT11_Temp[Index].DHT11_Humi;
}

注意:

1.硬件电路中DQ脚外部会加上拉电阻,主机释放总线会被上拉电阻自动上拉,但为保险器件我们将主机释放中线写为主动上拉为高电平
2. .h文件中对延时函数DS18B20_delay_us(a)的定义,关于 SysCtlDelayus(a)实际是ARM汇编的一种延时函数的写法,参见另一篇关于延时函数的博客(汇编延时)https://blog.csdn.net/Yin_w/article/details/130036593?spm=1001.2014.3001.5501

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

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

相关文章

CSS 笔记/练习

CSS 概述 与 html 配合&#xff0c;实现内容与样式分离样式美化 标签中元素作用 class&#xff1a;class属性用于为元素指定一个或多个样式类。通过为元素添加class属性&#xff0c;可以将其与CSS样式表中的样式规则关联起来&#xff0c;从而改变元素的外观和行为。一个元素可…

网络工程师知识点7

111、IS-IS路由器的三种类型&#xff1f; Level-1路由器&#xff08;只能创建level-1的LSDB&#xff09; Level-2路由器&#xff08;只能创建level-2的LSDB&#xff09; Level-1-2路由器&#xff08;路由器默认的类型&#xff0c;能同时创建level-1和level-2的LSDB&#xff09;…

0基础学习VR全景平台篇第109篇:认识拼接软件PTGui Pro

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01;今天给大家讲解我们全景后期拼接软件PTgui pro&#xff0c;下面我们开始吧&#xff01; &#xff08;PTgui pro软件课程大纲&#xff09; 1.PTGui这个软件是什么 发明人 &#xf…

公司如何防止源代码外泄,保护开发部门代码安全呢?

在智能制造业中&#xff0c;研发人员的开发环境&#xff0c;大多数采用c#开发语言svn 或c#git进行软件系统的开发&#xff0c;但是c#语言如何来防泄密保护呢&#xff1f;德人合科技针对于制造类企业制定了安全稳定的源代码防泄密方案&#xff0c;不影响员工的正常工作&#xff…

【数字图像处理笔记】01-数字图像基础

01-数字图像基础 图像类型 黑白(二值)图像 只有黑白两种颜色的图像称为黑白图像或单色图像&#xff0c;图像的每个像素只能是黑或白&#xff0c;没有中间的过渡&#xff0c;故又称为二值图像。 二值图像的像素值只能为0或1&#xff0c;图像中的每个像素值用1位存储。图像矩阵中…

Eudic欧路词典 for Mac(可离线英语学习工具)

Eudic欧路词典是一款功能强大的英语学习工具&#xff0c;旨在为用户提供全面的词汇解释和例句。该软件整合了多个权威词典&#xff0c;包括牛津、柯林斯等&#xff0c;提供了全面准确的词汇解释和用法示例。同时&#xff0c;它还支持离线使用&#xff0c;用户可以在无网络连接的…

EasyExcel

EasyExcel 官方文档 EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel (alibaba.com) 优势 Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存&#xff0c;poi有一套SAX模式的API可以一定程度的解决一些内存溢出…

电脑蓝牙与ESP32蓝牙连接,让电脑发现ESP32

win11蓝牙默认只查看常见蓝牙设备。ESP32创建的蓝牙很有可能是看不到的。 再蓝牙设备发现一栏选择高级&#xff0c;才能查看所有蓝牙设备。 只要下面几行代码&#xff0c;就能让PC发现ESP32 #include <BLEDevice.h> // 引入相关库void setup() {BLEDevice::init("…

学习pytorch13 神经网络-搭建小实战Sequential的使用

神经网络-搭建小实战&Sequential的使用 官网模型结构根据模型结构和数据的输入shape&#xff0c;计算用在模型中的超参数coderunning log网络结构可视化 B站小土堆pytorch视频学习 官网 https://pytorch.org/docs/stable/generated/torch.nn.Sequential.html#torch.nn.Se…

图扑智慧仓储数据可视化监控平台

随着市场竞争加剧和市场需求的不断提高&#xff0c;企业亟需更加高效、智能且可靠的仓储物流管理方式&#xff0c;以提升企业的物流效率&#xff0c;减少其输出成本&#xff0c;有效应对市场上的变化和挑战。 图扑软件应用自研 HT for Web 产品搭建的 2D 智慧仓储可视化平台&a…

全流程TOUGH系列软件实践技术应用

查看原文>>>全流程TOUGH系列软件实践技术应用 TOUGH系列软件是由美国劳伦斯伯克利实验室开发的&#xff0c;旨在解决非饱和带中地下水、热运移的通用模拟软件。和传统地下水模拟软件Feflow和Modflow不同&#xff0c;TOUGH系列软件采用模块化设计和有限积分差网格剖分…

JavaScript系列从入门到精通系列第二十篇:使用工厂方法创建JavaScript对象,JavaScript构造函数详解,JavaScript类概念的介绍

文章目录 一&#xff1a;使用工厂方法创建对象 1&#xff1a;原始写法 2&#xff1a;工厂方式 3&#xff1a;结果验证 二&#xff1a;构造函数 1&#xff1a;什么是构造函数 2&#xff1a;构造函数和普通函数的区别 3&#xff1a;构造函数的执行流程 三&#xff1a;类…

计算机网络中的CSMA/CD算法的操作流程(《自顶向下》里的提炼总结)

具有碰撞检测的载波侦听多路访问&#xff08;CSMA/CD算法&#xff09; 以下内容总结&#xff0c;对应《计算机网络自顶向下第七版》第六章链路层和局域网P299 操作流程&#xff1a; NIC&#xff08;适配器&#xff0c;即网络接口&#xff09;从网络层接收数据报&#xff0c;…

pycharm远程连接miniconda完整过程,以及遇到的问题解决

问题1&#xff1a;no-zero exit code(126) env: ‘/home/user2/miniconda3/envs/ihan/bin/python3’: Too many levels of symbolic links Python interpreter process exited with a non-zero exit code 126 因为选择的新建导致太多软连接&#xff0c;先在服务器上建好虚拟环…

【yolov8系列】yolov8的目标检测、实例分割、关节点估计的原理解析

1 YOLO时间线 这里简单列下yolo的发展时间线&#xff0c;对每个版本的提出有个时间概念。 2 yolov8 的简介 工程链接&#xff1a;https://github.com/ultralytics/ultralytics 2.1 yolov8的特点 采用了anchor free方式&#xff0c;去除了先验设置可能不佳带来的影响借鉴Genera…

液压自动化成套设备比例阀放大器

液压电气成套设备的比例阀放大器是一种电子控制设备&#xff0c;用于控制液压动力系统中的液压比例阀1。 比例阀放大器通常采用电子信号进行控制&#xff0c;以控制比例阀的开度和流量&#xff0c;以实现液压系统的可靠控制。比例阀放大器主要由以下组成部分&#xff1a; 驱动…

Ps:变形

Ps菜单&#xff1a;编辑/变换/变形 Edit/Transform/Warp 变形 Warp是自由变换的一种模式&#xff0c;不仅可以用于物体的伸缩扭曲&#xff0c;也可用于人体的局部塑形。 除了从菜单打开&#xff0c;通常情况下&#xff0c;按 Ctrl T 进入自由变换&#xff0c;然后在画面上右击…

专题三:穷举、暴搜、深搜、回溯、剪枝【递归、搜索、回溯】

1、全排列 class Solution { public:vector<vector<int>> ret;vector<int> path;bool check[7];void dfs(vector<int>& nums){if(nums.size() path.size()) {ret.push_back(path);return;}for(int i 0;i < nums.size();i){if(check[i] fals…

Android查看签名信息系列 · 使用Android Studio获取签名

前言 Android查看签名信息系列 之使用Android Studio获取签名&#xff0c;通过Android Studio自带的gradle来获取签名信息。 优点&#xff1a;此法可查看 MD5、SHA1 等信息。 缺点&#xff1a;升级某个Studio版本后&#xff0c;没有签名任务了&#xff0c;特别不方便。 实现…

VulnHub lazysysadmin

一、信息收集 1.nmap扫描开发端口 开放了&#xff1a;22、80、445 访问80端口&#xff0c;没有发现什么有价值的信息 2.扫描共享文件 enum4linux--扫描共享文件 使用&#xff1a; enum4linux 192.168.103.182windows访问共享文件 \\192.168.103.182\文件夹名称信息收集&…