DHT11 数字湿温度传感器的原理和应用范例

news2024/11/15 8:32:16

目录

概述

1、应用电路连接说明

2、DHT11 数据结构

3、DHT11的传输时序

3.1  DHT11 开始发送数据流程

3.2  主机复位信号和 DHT11 响应信号

3.3  数字‘0’信号表示方法

3.4  数字‘1’信号表示方法

4、实例应用

4.1 硬件描述

4.2 管脚分配

4.3  程序代码


概述

         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)
管脚排列如下:
引脚说明: Vcc 正电源 、Dout 输出 、NC 空脚 、GND 地。

1、应用电路连接说明

        DHT11 数字湿温度传感器连接方法极为简单。第一脚接电源正,第四脚接电源地端。数据端为第二脚。可直接接主机(单片机)的 I/O 口。为提高稳定性,建议在数据端和电源正之间接一只 4.7K 的上拉电阻。第三脚为空脚,此管脚悬空不用。

2DHT11 数据结构

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

3DHT11的传输时序

3.1  DHT11 开始发送数据流程

        主机发送开始信号后 , 延时等待 20us-40us 后读取 DH11T 的回应信号,读取总线为低电平, 说明 DHT11 发送响应信号, DHT11 发送响应信号后,再把总线拉高, 准备发送数据 , 每一 bit 数据都以低电平开始 , 格式见下面图示。如果读取响应信号为高电平, DHT11 没有响应 , 请检查线路是否连接正常。

3.2  主机复位信号和 DHT11 响应信号

3.3  数字‘0’信号表示方法

3.4  数字‘1’信号表示方法

4、实例应用

4.1 硬件描述

        本项目采用两个三位一体共阳数码管做为湿度,温度显示模块。采用 ATMEL 公司的ATmega8 做为主控芯片,详细如图 4.1 所示。

4.2 管脚分配

4.3  程序代码

/*原程序清单如下所示,本程序在 ICCAVR 6.31A 下测试通过。*/
#include <iom8v.h> 
#include <macros.h> 
typedef unsigned char U8; // defined for unsigned 8-bits integer variable 
typedef signed char S8; // defined for signed 8-bits integer variable 
typedef unsigned int U16; // defined for unsigned 16-bits integer variable 
typedef signed int S16; // defined for signed 16-bits integer variable 
typedef unsigned long U32; // defined for unsigned 32-bits integer variable 
typedef signed long S32; // defined for signed 32-bits integer variable 
typedef float F32; // single precision floating point variable (32bits) 
typedef double F64; // double precision floating point variable (64bits) 
/************************************************************************** 
 数码管显示赋值区
***************************************************************************/ 
#define _a 0x01 
#define _b 0x02 
#define _c 0x04 
#define _d 0x08 
#define _e 0x10 
#define _f 0x20 
#define _g 0x40 
#define _dp 0x80 
#define num0 _g //灭的数码管
#define num1 _a|_d|_e|_f|_g 
#define num2 _c|_f 
#define num3 _e|_f 
#define num4 _a|_d|_e 
#define num5 _b|_e 
#define num6 _b 
#define num7 _d|_e|_f|_g 
#define num8 0x00 
#define num9 _e 
#define num_ _a|_b|_c|_d|_e|_f|_dp
#define num_11 _a|_d|_e|_f 
#define num_E _b|_c|_dp // Err 代码
#define num_r _a|_b|_c|_d|_f|_dp 
#define dc2 0x04 
#define dc3 0x08 
#define dd 0x03 
#define dd4 0x10 
#define dd5 0x20 
#define dd6 0x40 
#define dd7 0x80 
#define dd2 0x04 
#define dd3 0x08 //数码管控制端口
#define led1 dc3 //使用时要先将数码管全熄灭掉
#define led2 dd5 
#define led3 dd4 
#define led4 dd7 
#define led5 dd6 
#define led6 dd2
U8 PLAY[6]={0,0,0,0,0,0}; 
unsigned char Flag = 0; 
unsigned int u16ReadDownStreamTimer; 
const U8 LED[14]={num0,num1,num2,num3,num4,num5,num6,num7,num8,num9, 
num_,num_11,num_E,num_r }; //数码管笔形码数组
//函数声明:
void init_devices(void); 
void time1_start(void); 
void port_init(void); 
void timer0_init(void); 
void timer1_init(void); 
void Delay(unsigned int i); 
void DelayNS (U16 dly) ; 
//***************************************************************************** 
// 显示模块
//***************************************************************************** 
void Display (void) 
 { 
 U8 i; 
 for(i=0;i<=5;i++) 
  { 
   DDRD |= 0XFC; 
   PORTD&=0x03;
   DDRC |= 0X0C; 
   PORTC&=0xF3; 
   Delay(10); 
   switch(i) 
   { 
    case 0: PORTC|=led1;break; 
    case 1: PORTD|=led2;break; 
    case 2: PORTD|=led3;break; 
    case 3: PORTD|=led4;break; 
    case 4: PORTD|=led5;break; 
    case 5: PORTD|=led6;break; 
    default :break; 
   } 
  PORTB=LED[PLAY[i]] ; //送数据 
  if((i==0)|(i==2)|(i==3)|(i==5)) //消小数点
   { 
    PORTB|=0x80; 
   } 
   DelayNS(1); 
  } 
  PORTD&=0x03; 
  PORTC&=0xF3; 
 } 
//***************************************************************************** 
// delay() 
//*****************************************************************************
void DelayNS (U16 dly) //延时子程序 1.010ms 
 { 
  U16 i; 
  for ( ; dly>0; dly--)WDR(); 
  for (i=0; i<1131; i++); 
 } 
void Delay(unsigned int i) 
 { 
  while(i--); 
 } 
void delay1N(unsigned int Dcount) 
{ 
 while(Dcount--) 
 { 
 NOP();NOP();NOP(); 
 } 
} 
void Timer2_Delay150ms(void) // Timer 2
{ 
 TCCR2 = 0x00; 
 TCNT2 = 0xDE; 
 TIFR |= 0X40; 
 TCCR2 = 0x02; 
 } 
//***************************************************************************** 
// 系统初始化函数
//***************************************************************************** 
void init_devices(void) 
 { 
  CLI(); 
  port_init(); 
  timer0_init(); 
  TIMSK = 0x05; 
  SEI(); 
 } 
//***************************************************************************** 
// 端口初始化
//***************************************************************************** 
void port_init(void) 
 { 
  DDRB = 0xFF; 
  PORTB = 0x00; 
  DDRC = 0x0C; 
  PORTC = 0x03; 
  DDRD = 0xF0; 
  PORTD = 0x00; 
} 
//***************************************************************************** 
//TIMER0 initialize - prescale:256 
// desired value: 1mSec 
// actual value: 0.992mSec (0.8%) 
//***************************************************************************** 
void timer0_init(void) 
{ 
 TCCR0 = 0x00; 
 TCNT0 = 0xE1; 
 TCCR0 = 0x04; 
} 
//***************************************************************************** 
//TIMER2 initialize - prescale:8 
// WGM: Normal 
// desired value: 35uSec
// actual value: 34.000uSec (2.9%) 
//***************************************************************************** 
void timer2_init(void) 
{ 
 TCCR2 = 0x00; 
 ASSR = 0x00; 
 TCNT2 = 0xDE; 
 OCR2 = 0x22; 
 TCCR2 = 0x02; 
} 
//***************************************************************************** 
// 定时器 TIMER0 中断
//***************************************************************************** 
#pragma interrupt_handler timer0_ovf_isr:10 
void timer0_ovf_isr(void) 
{ 
 TCNT0 = 0xE1; 
 u16ReadDownStreamTimer++; 
} 
//***************************************************************************** 
// main() function 
//***************************************************************************** 
void main(void) 
 { 
 U16 u16Flag; // 超时计数
 unsigned char iiii; 
 unsigned long u32I; // 接收数据临时变量
 unsigned long ReceiveValue = 0; // 接收数据包变量
 unsigned long ReceiveValue1 = 0; // 接收校验和变量
 unsigned int ReceiveHighByte; // 分解数据包 湿度
 unsigned int ReceiveLowByte; // 分解数据包 温度
 WDR(); 
 DelayNS(2); //提高稳定性的延时
 init_devices(); 
 timer2_init(); 
 u16ReadDownStreamTimer = 0; 
 DDRC &= ~0X20; 
 PORTC |= 0X20; 
 while(1) 
 { 
  Display(); //显示
  WDR(); 
  if(u16ReadDownStreamTimer > 1000) //1s 采集一次
 {
 if(iiii == 0) 
 { 
  DDRC |= 0X20; 
  PORTC &= ~0X20; //发送 0 
  iiii++; 
  u16ReadDownStreamTimer = 991; 
 } 
 else 
 { 
  iiii = 0; 
  delay1N(200); //延时等待对方响应 
  DDRC &= ~0X20; //输入
  PORTC |= 0X20; //拉高
  delay1N(40); //延时等待对方响应 
 if(!(PINC&0X20)) //检测对方是否响应
 { 
  u16Flag = 0; 
  while((!(PINC&0X20)) && ((u16Flag++)<50000)); 
//等待响应低电平拉高, 拉高之后开始传输数据
  ReceiveValue = 0; 
  ReceiveValue1 = 0; 
  u16Flag = 0; 
  while((PINC&0X20) && ((u16Flag++)<50000)); 
// 等待数据 第一个'0'出现
 for(u32I=0x80000000; u32I>0; u32I>>=1) 
 // 4 个字节的数据 湿度(8+8)+温度(8+8)=32(Bit) 
 { 
  u16Flag = 0; 
  while((!(PINC&0X20))&& ((u16Flag++)<30)); 
  Timer2_Delay150ms(); 
  u16Flag = 0; 
  while((PINC&0X20) && ((u16Flag++)<300)); 
  if(TIFR&0x40) 
 { 
  ReceiveValue |= u32I; 
 } 
 } 
  for(u32I=0x80; u32I>0; u32I>>=1) // 1 BYTE 的校验字节
 { 
  u16Flag = 0; 
  while((!(PINC&0X20))&& ((u16Flag++)<30)); 
  Timer2_Delay150ms(); 
  u16Flag = 0; 
  while((PINC&0X20) && ((u16Flag++)<300));
if(TIFR&0x40) 
 { 
  ReceiveValue1 |= u32I; 
 } 
 } 
 DDRC |= 0X20; //输出
 PORTC |= 0X20; //高上拉
 ReceiveLowByte =(unsigned int )( ReceiveValue&0x0000FFFF); 
 ReceiveHighByte = ReceiveValue>>16; 
 if((U8)(*((U8*)(&ReceiveHighByte)+1)+*((U8*)(&ReceiveLowByte)+1)) 
==*(U8 *)(&ReceiveValue1)) 
 { //校验和
  PLAY[3] = *((U8*)(&ReceiveHighByte) + 1)/10; 
  PLAY[4] = *((U8*)(&ReceiveHighByte) + 1)%10; 
  PLAY[2] = 0; 
  PLAY[0] = *((U8*)(&ReceiveLowByte) + 1)/10; 
  PLAY[1] = *((U8*)(&ReceiveLowByte) + 1)%10; 
  PLAY[5] = 0; 
 } 
 else //校验和不正确显示 6 个 8 
 { 
  PLAY[0] = 8; PLAY[1] = 8; 
  PLAY[2] = 8; PLAY[3] = 8; 
  PLAY[4] = 8; PLAY[5] = 8; 
 } 
 } 
 else //没有检测到信号 发送 Err 到显示
 { 
  PLAY[0] = 12;PLAY[1] = 13;PLAY[2] = 13; 
  PLAY[3] = 12;PLAY[4] = 13;PLAY[5] = 13; 
 } 
 DDRC |= 0X20; 
 PORTC |= 0X20; 
 u16ReadDownStreamTimer = 0; //清定时计数位
  } 
 } 
 else // 还没到,等待
  { 
  DelayNS(1);DelayNS(1); 
  DelayNS(1);DelayNS(1); 
   } 
  } 
 }





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

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

相关文章

@所有燃气企业,城燃企业数字化转型重点抓住的八个关键点

关键词&#xff1a;智慧燃气、燃气数字化、设备设施数字化 数字化转型是用信息技术全面重塑企业经营管理模式&#xff0c;是企业发展模式的变革创新&#xff0c;是企业从工业经济时代迈向数字经济时代的必然选择。加快推进企业数字化转型&#xff0c;打造数字时代企业业务运行…

2023年中国超导磁体市场规模、需求量及行业竞争现状分析[图]

超导磁体一般是指用超导导线绕制的能产生强磁场的超导线圈&#xff0c;还包括其运行所必要的低温恒温容器。通常电磁铁是利用在导体中通过电流产生磁场&#xff0c;由于超导材料在超导状态下具有零电阻特性&#xff0c;因此可以以极小的面积通过巨大的电流。超导磁体具有场强高…

意大利航天飞行器公司【Sidereus】完成510万欧元融资

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;位于意大利萨莱诺的航天飞行器公司Sidereus Space Dynamics今日宣布已完成510万欧元融资。 本轮融资由Primo Space和CDP Venture Capital Sgr领投&#xff0c;通过Italia Venture II - Fondo Impr…

element picker 时间控件,指定区间和指定月份置灰

直接上代码 <el-date-pickerv-model"fillingList.declareDate"type"month":disabled"isDisplayName"placeholder"选择填报时间"value-format"yyyy-MM":picker-options"pickerOptions"change"declareDate…

玩转ChatGPT:图像识别(vol. 1)

一、写在前面 来了来了&#xff0c;终于给我的账号开放图像识别功能了&#xff0c;话不多说&#xff0c;直接开测&#xff01;&#xff01;&#xff01; 二、开始尝鲜 &#xff08;1&#xff09;咒语&#xff1a; GPT回复&#xff1a; 这幅图显示了从2005年1月到2012年12月的…

uniapp app获取keystore等一系列常用数据

https://blog.csdn.net/deepdfhy/article/details/88698492 参考文章 一、获取安卓证书keystore的SHA1和SHA256值 参数上面引用链接 window r : $ cmd $ D: 进入D盘 $ keytool -genkey -alias testalias -keyalg RSA -keysize 2048 -validity 36500 -keystore 项目名称.ke…

uniapp app端使用谷歌地图选点定位

国内需要vpn 和申请谷歌地图的Maps JavaScript API 类型的 key,指引链接这里不详细介绍 一 、我们得通过webview 跳转谷歌地图 ,需要创建一个webview页面,里面跳转承载谷歌地图的html页面,如果是放在本地的话 html文件须遵守规范 放在 “项目根目录下->hybrid->html->…

Spring三级缓存流程再梳理

本文主要是说下在使用spring时遇到了循环依赖&#xff0c;Spring利用三级缓存怎么解决 getBean(beanName)doGetBean(name, null, null, false);getSingleton(beanName)方法&#xff0c; 最后会通过addSingleton(beanName, singletonObject)存到一级缓存里面去createBean(beanN…

如何进行pyhon的虚拟环境创建及管理

无论服务器或者本地&#xff0c;创建虚拟环境都是&#xff1a; 【Python】搭建虚拟环境_python创建虚拟环境_今天自洽了吗的博客-CSDN博客 虚拟环境绑定到项目 这个是运行环境&#xff0c;可以切换任意运行环境 如果是服务器上&#xff1a;可以先source xx/bin/active&#xf…

颠覆性语音识别:单词级时间戳和说话人分离 | 开源日报 No.53

vbenjs/vue-vben-admin Stars: 19.7k License: MIT Vue Vben Admin 是一个免费开源的中后台模板&#xff0c;使用最新的 vue3、vite4 和 TypeScript 等主流技术进行开发。该项目提供了现成的中后台前端解决方案&#xff0c;并可用于学习参考。 使用先进的前端技术如 Vue3/vit…

[电源选项]没有系统散热方式,没有被动散热选项

背景 笔记本的风扇声音太大&#xff0c;想改成被动散热方式&#xff0c;又不想影响性能。 于是我打开了控制面板\所有控制面板项\电源选项&#xff0c;点更改计划设置-> 更改高级电源设置。 想把散热方式改成被动散热。发现win11中好像没有这个选项了&#xff01; 如何…

JVM(一)

字节码文件的组成: 基础信息:魔数&#xff0c;字节码文件对应的java版本号&#xff0c;访问表示public final以及父类和接口 常量池:保存了字符串常量&#xff0c;类或者是接口名&#xff0c;字段名&#xff0c;主要在接口中使用 字段:当前类或者是接口声明的字段信息 方法:当…

win10 wsl安装步骤

参考&#xff1a; 安装 WSL | Microsoft Learn 一、安装wsl 1.若要查看可通过在线商店下载的可用 Linux 发行版列表&#xff0c;请输入&#xff1a; wsl --list --online 或 wsl -l -o> wsl -l -o 以下是可安装的有效分发的列表。 使用 wsl.exe --install <Distro>…

知识体系图谱

知识体系图谱 最近更新简历的时候&#xff0c;有种好像去年到今年学了很多&#xff0c;但是都零零散散的&#xff0c;不成体系&#xff0c;就想着抽时间总结归纳一下知识体系&#xff0c;目前我个人的技术栈是这样的&#xff1a; 还是稍微有点乱&#xff0c;下一次更新的时候再…

HQChart支持的画图工具列表

HQChart支持的画图工具列表 线段类线段射线标价线垂直线箭头趋势线水平线水平线段平行射线平行线平行通道价格通道线M头W底头肩型波浪尺AB波浪尺箱型线涂鸦线段 图形类圆弧线矩形平行四边形三角形圆对称角度 文字类文本箭头NoteAnchoredTextPriceLabelPriceNote 其他江恩角度线…

Ubuntu下怎么配置vsftpd

2023年10月12日&#xff0c;周四中午 目录 首先要添加一个系统用户然后设置这个系统用户的密码给新创建的系统用户创建主目录启动vsftpd服务查看vsftpd服务的状态打开外界访问vsftpd服务所需的端口获取服务器的IP地址大功告成 首先要添加一个系统用户 useradd 用户名然后设置…

如何应对量化交易,个人股票账户如何实现量化程序化自动交易

目前股票量化交易是对个人账户开放的&#xff0c;如果你没开通&#xff0c;可能是没有找对渠道&#xff0c;很多券商的手机客户端是包含某些简易版的策略交易&#xff0c;如网格策略&#xff0c;自动止盈止损等&#xff0c;这些策略交易虽然简单、灵活性差&#xff0c;但也是量…

【数据安全】数据安全运维是什么意思?有什么意义?

随着数字化大力发展&#xff0c;保障企业重要资产数据的安全越发重要&#xff0c;因此衍生了数据安全运维工作。那你知道数据安全运维是什么意思&#xff1f;有什么意义&#xff1f; 数据安全运维是什么意思&#xff1f; 数据安全运维是将数据分析技术用于管理数据的过程&…

【萌新向】Sql Server保姆级安装教程-图文详解手把手教你安sql

首先打开百度&#xff0c;搜索sql server&#xff0c;找到图示词条&#xff0c;点击进去。 一般版本是需要付费的&#xff0c;正常开发可以使用免费版本【Express】&#xff0c;点击下载 下载完成后打开下载的文件。三个选项&#xff0c;我们选自定义方式。 选择语言和位置…

第四范式破发,AI大模型之殇?

9月28日&#xff0c;决策类AI独角兽第四范式敲钟挂牌港交所&#xff0c;发行价为55.60港元/股&#xff0c;IPO首日报收58.50港元/股&#xff0c;涨幅5.22%。不过也就日内富贵&#xff0c;在之后的几个交易日里&#xff0c;市值蒸发超20亿港元&#xff0c;截止目前&#xff0c;股…