DTH11温湿度传感器

DHT11 是一款温湿度复合传感器,常用于单片机系统中进行环境温湿度的测量。以下是对 DHT11 温湿度传感器的详细讲解:

一、传感器概述

DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接。

二、主要特点

  1. 体积小、功耗低:适合集成到各种小型电子设备中。
  2. 数字信号输出:无需复杂的模拟信号处理,直接输出数字信号,方便与单片机进行通信。
  3. 响应速度快:能够快速准确地测量环境温湿度变化。
  4. 精度较高:温度测量范围为 0℃ - 50℃,精度为 ±2℃;湿度测量范围为 20% - 90% RH,精度为 ±5% RH。

三、工作原理

  1. 传感器通过单片机的一个 I/O 口进行通信。单片机向 DHT11 发送启动信号后,DHT11 开始采集温湿度数据。
  2. 采集完成后,DHT11 将温湿度数据转换为数字信号,并通过数据线逐位发送给单片机。
  3. 单片机接收到数据后,进行校验和处理,以确保数据的准确性。

四、通信协议

  1. 单片机与 DHT11 之间采用单总线数据格式进行通信。通信过程包括初始化、发送启动信号、接收数据等步骤。
  2. 初始化时,单片机将数据线拉低一段时间,然后释放数据线,等待 DHT11 的响应。
  3. 发送启动信号时,单片机将数据线拉低至少 18ms,然后释放数据线,等待 DHT11 的响应。
  4. DHT11 接收到启动信号后,会发送一个 80μs 的低电平响应信号,接着发送 80μs 的高电平响应信号,表示准备好发送数据。
  5. DHT11 发送的数据包括 40 位,分别为 8 位湿度整数数据、8 位湿度小数数据、8 位温度整数数据、8 位温度小数数据和 8 位校验和。数据以低位在前的方式逐位发送。
  6. 单片机接收到数据后,进行校验和计算。如果校验和正确,则表示数据接收成功;否则,需要重新进行数据采集。

五、使用方法

  1. 硬件连接:将 DHT11 的 VCC 引脚连接到单片机的电源引脚,GND 引脚连接到地,DATA 引脚连接到单片机的一个 I/O 口。
  2. 软件编程:在单片机程序中,需要实现 DHT11 的初始化、启动信号发送、数据接收和校验等功能。可以使用定时器或延时函数来满足通信协议的时序要求。

操作时序:

在这里插入图片描述

复位信号和响应信号:

被调函数(DTH11):

#include "reg52.h"
#include "delay.h"sbit dht = P3^6; // 定义连接 DHT11 传感器的引脚,这里连接到 P3.6
char datas[5]; // 用于存储从 DHT11 读取的数据/*
DHT11 的时序逻辑分析:
a : dht = 1  设置引脚为高电平。
b £ºdht = 0  将引脚拉低。
ÑÓʱ30ms  延时 30 毫秒。
c£º dht = 1  将引脚拉高。
在 60us 后读 d 点,如果 d 点是低电平(被模块拉低),说明模块存在。
*/void DH11_Star() {dht = 1; // 设置引脚为高电平dht = 0; // 将引脚拉低Delay30ms(); // 延时 30 毫秒,发送启动信号给 DHT11dht = 1; // 将引脚拉高// 卡 d 点:等待 DHT11 拉低引脚作为响应开始信号while (dht);// 卡 e 点:等待 DHT11 释放引脚(变为高电平),表示准备发送数据while (!dht);// 卡 f 点:等待 DHT11 再次拉高引脚,确认准备发送数据while (dht);
}void Read_Data() {int i; // 用于循环计数,表示读取的数据组数(这里共 5 组数据)int j; // 用于循环计数,表示每组数据中的每一位char temp; // 临时变量,用于存储每一位数据在移位过程中的值char flag; // 标志位,用于表示读取到的数据位是 1 还是 0DH11_Star(); // 调用启动 DHT11 的函数for (i = 0; i < 5; i++) {// 卡 g 点:等待 DHT11 将引脚拉低,表示开始发送一组数据while (!dht);// 有效数据都是高电平,持续时间不一样,延时 50us 后根据引脚电平判断数据是 0 还是 1for (j = 0; j < 8; j++) {while (!dht); // 等待引脚拉低,表示开始读取一位数据Delay40us(); // 延时 40 微秒,根据引脚在这个时间后的电平判断数据位if (dht == 1) {flag = 1; // 如果引脚为高电平,标志位设为 1,表示读取到的数据位是 1while (dht); // 等待引脚再次拉低,准备读取下一位数据} else {flag = 0; // 如果引脚为低电平,标志位设为 0,表示读取到的数据位是 0}temp = temp << 1; // 将 temp 左移一位,为存储下一位数据做准备temp |= flag; // 将标志位的值存入 temp,完成一位数据的读取}datas[i] = temp; // 将读取到的一组数据存储到 datas 数组中}
}

delay函数:
 

#include <intrins.h>
void Delay15ms()//@11.0592MHz
{unsigned char i, j;i = 27;j = 226;do{while (--j);} while (--i);
}void Delay5ms()		//@11.0592MHz
{unsigned char i, j;i = 9;j = 244;do{while (--j);} while (--i);
}void Delay30ms()		//@11.0592MHz
{unsigned char i, j;i = 54;j = 199;do{while (--j);} while (--i);
}void Delay40us()		//@11.0592MHz
{unsigned char i;_nop_();i = 15;while (--i);
}void Delay1000ms()		//@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}

LCD1602:
 

#include "reg52.h"
#include <intrins.h>
#include "delay.h"#define databuffer P0 // 定义 8 位数据总线,连接到 P0 端口sbit RS = P1^0; // 寄存器选择引脚,连接到 P1.0
sbit RW = P1^1; // 读写选择引脚,连接到 P1.1
sbit EN = P1^4; // 使能引脚,连接到 P1.4/*
RS(Register Select):- P1.0- 当 RS = 0 时,选择指令寄存器;当 RS = 1 时,选择数据寄存器。
RW(Read/Write):- P1.1- 当 RW = 0 时,进行写操作;当 RW = 1 时,进行读操作。
E(Enable):- P1.4- 下降沿触发数据传输。*/void check_busy() {char temp = 0x80; // 初始化为 1000 0000,用于读取忙碌标志位databuffer = 0x80;// 当单片机给 1602 发送数据时,通过检查忙碌标志位来避免死循环。// 高电平表示忙碌,在读取时序中,此时模块不能接收命令。如果为低电平表示不忙碌。while (temp & 0x80) {// 进入读时序RS = 0; // 设置为指令寄存器RW = 1; // 设置为读操作EN = 0;_nop_(); // 空操作,可能用于延时等待稳定EN = 1;_nop_();_nop_();temp = databuffer; // 读取数据总线上的值EN = 0;_nop_();}
}// 写指令函数
void Write_Cmd_Func(char cmd) {check_busy(); // 检查忙碌状态// 根据时序图配置引脚RS = 0; // 选择指令寄存器RW = 0; // 选择写操作EN = 0;_nop_(); // 延时等待稳定databuffer = cmd; // 将指令写入数据总线_nop_(); // 延时等待稳定EN = 1;_nop_();_nop_();EN = 0;_nop_();
}// 写数据函数
void Write_data_Func(char datashow) {check_busy(); // 检查忙碌状态RS = 1; // 选择数据寄存器RW = 0; // 选择写操作EN = 0;_nop_(); // 延时等待稳定databuffer = datashow; // 将数据写入数据总线_nop_(); // 延时等待稳定EN = 1;_nop_();_nop_();EN = 0;_nop_();
}void LCD1602_Init() {//(1)延时 15msDelay15ms();//(2)写指令 38H(不检测忙碌信号) Write_Cmd_Func(0x38);//(3)延时 5msDelay5ms();//(4)以后每次写指令、读/写数据操作均需要检测忙碌信号//(5)写指令 38H:显示模式设置Write_Cmd_Func(0x38);//(6)写指令 08H:显示关闭Write_Cmd_Func(0x08);//(7)写指令 01H:显示清屏Write_Cmd_Func(0x01);//(8)写指令 06H:显示光标移动设置Write_Cmd_Func(0x06);//(9)写指令 0CH:显示开及光标设置Write_Cmd_Func(0x0c);
}
void LCD1602_showline(char row, char col, char *string) {// 根据行号设置显示地址switch (row) {case 1:// 设置第一行的显示地址Write_Cmd_Func(0x80 + col);// 循环写入字符串中的每个字符while (*string) {// 将当前字符写入数据寄存器以显示在 LCD 上Write_data_Func(*string);// 指针指向下一个字符string++;}break;case 2:// 设置第二行的显示地址Write_Cmd_Func(0x80 + 0x40 + col);while (*string) {Write_data_Func(*string);string++;}break;}
}

主函数:

#include "reg52.h"
#include <intrins.h>
#include "delay.h"
#include "uart.h"
#include "lcd1602.h"
#include "dht11.h"
#include "config.h"// 定义用于存储温度和湿度显示字符串的字符数组
char temp[8];
char huma[8];
// 声明外部变量 datas,可能用于存储从 DHT11 传感器读取的数据
extern char datas[5];// 函数用于构建温度和湿度的显示字符串
void build_datas() {// 将湿度的标识字符 'H' 存入 huma 数组的第一个位置huma[0] = 'H';// 将 datas 数组中第一个元素(湿度整数部分的十位数字)转换为 ASCII 码存入 huma 数组的第二个位置huma[1] = datas[0]/10 + 0x30;// 将 datas 数组中第一个元素(湿度整数部分的个位数字)转换为 ASCII 码存入 huma 数组的第三个位置huma[2] = datas[0]%10 + 0x30;// 存入小数点huma[3] = '.';// 将 datas 数组中第二个元素(湿度小数部分的十位数字)转换为 ASCII 码存入 huma 数组的第四个位置huma[4] = datas[1]/10 + 0x30;// 将 datas 数组中第二个元素(湿度小数部分的个位数字)转换为 ASCII 码存入 huma 数组的第五个位置huma[5] = datas[1]%10 + 0x30;// 存入百分号huma[6] = '%';// 字符串结束标志huma[7] = '\0';// 将温度的标识字符 'T' 存入 temp 数组的第一个位置temp[0] = 'T';// 将 datas 数组中第三个元素(温度整数部分的十位数字)转换为 ASCII 码存入 temp 数组的第二个位置temp[1] = datas[2]/10 + 0x30;// 将 datas 数组中第三个元素(温度整数部分的个位数字)转换为 ASCII 码存入 temp 数组的第三个位置temp[2] = datas[2]%10 + 0x30;// 存入小数点temp[3] = '.';// 将 datas 数组中第四个元素(温度小数部分的十位数字)转换为 ASCII 码存入 temp 数组的第四个位置temp[4] = datas[3]/10 + 0x30;// 将 datas 数组中第四个元素(温度小数部分的个位数字)转换为 ASCII 码存入 temp 数组的第五个位置temp[5] = datas[3]%10 + 0x30;// 存入摄氏度符号temp[6] = 'C';// 字符串结束标志temp[7] = '\0';
}int main() {// 延时 1000 毫秒Delay1000ms();// 初始化串口UartInit();// 初始化 LCD1602LCD1602_Init();// 再次延时 1000 毫秒Delay1000ms();Delay1000ms();// 设置 ledOne 为 0,可能用于控制某个 LEDledOne = 0;while (1) {// 延时 1000 毫秒Delay1000ms();// 读取 DHT11 传感器的数据Read_Data();// 如果温度(datas[2])大于等于 24if (datas[2] >= 24) {// 设置风扇状态为关闭(fengshan 可能是一个变量用于控制风扇)fengshan = 0;} else {// 否则设置风扇状态为开启fengshan = 1;}// 构建温度和湿度的显示字符串build_datas();// 发送湿度字符串到串口sent_string(huma);// 发送回车换行符到串口sent_string("\r\n");// 发送温度字符串到串口sent_string(temp);// 发送回车换行符到串口sent_string("\r\n");// 在 LCD1602 的第一行第二列开始显示湿度字符串LCD1602_showline(1, 2, huma);// 在 LCD1602 的第二行第二列开始显示温度字符串LCD1602_showline(2, 2, temp);}
}

成功实现:

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

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

相关文章

【STM32】江科大STM32笔记汇总(已完结)

STM32江科大笔记汇总 STM32学习笔记课程简介(01)STM32简介(02)软件安装(03)新建工程(04)GPIO输出(05)LED闪烁& LED流水灯& 蜂鸣器(06)GPIO输入(07)按键控制LED 光敏传感器控制蜂鸣器(08)OLED调试工具(09)OLED显示屏(10)EXTI外部中断(11)对射式红外传感器计次 旋转编码器…

C++:模拟实现vector

目录 成员变量与迭代器 size capacity empty 迭代器有关函数 实现默认成员函数的前置准备 reserve ​编辑 ​编辑 push_back 构造函数 无参构造 迭代器区间构造 n个val来进行构造 析构函数 拷贝构造函数 赋值重载 增删查改 clear resize pop_back inser…

git add成功后忘记commit的文件丢了?

本文目标&#xff1a;开发人员&#xff0c;在了解git fsck命令用法的条件下&#xff0c;进行git add成功但由于误操作导致丢失的文件找回&#xff0c;达到找回丢失文件的程度。 文章目录 1 痛点2 解决方案3 总结/练习 1 痛点 开发过程中&#xff0c;分支太多&#xff08;基线分…

通信工程学习:什么是MIMO多输入多输出技术

MIMO:多输入多输出技术 MIMO(Multiple-Input Multiple-Output)多输入多输出技术是一种在无线通信中广泛应用的技术,它通过利用多个天线进行数据传输和接收,可以显著提高无线通信系统的性能和容量。以下是对MIMO技术的详细解释: 一、定义与原理 MIMO技术…

铺铜修改后自动重铺

很多初学者对于敷铜操作感到比较麻烦&#xff1a;为什么每次打过孔&#xff0c;修改走线后都需要手动右击-重新修改敷铜。如何提升layout的效率&#xff1f; 版本&#xff1a;Altium Designer 21.9.2 首先&#xff0c;点击面板右边的小齿轮&#xff0c;进入设置 接下来&#…

【国庆要来了】基于Leaflet的旅游路线WebGIS可视化实践

前言 转眼2024年的国庆节马上就要来临了&#xff0c;估计很多小伙伴都计划好了旅游路线。金秋十月&#xff0c;不管是选择出门去看看风景&#xff0c;还是选择在家里看人。从自己生活惯了的城市去别人生活惯了的城市&#xff0c;去感受城市烟火、去感受人文风景&#xff0c;为2…

SpringBoot整合JPA 基础使用

一、什么是JPA ‌‌1.JPA的定义和基本概念‌‌ ‌JPA&#xff08;Java Persistence API&#xff09;‌是Java中用于进行持久化操作的一种规范&#xff0c;它定义了一系列用于操作关系型数据库的API接口。通过这些接口&#xff0c;开发人员可以方便地进行数据库的增删改查等操…

DC00021基于springboot问卷调查管理系统web项目调查问卷管理系统MySQL(附源码)

1、项目功能演示 DC00021基于springboot问卷调查管理系统web项目调查问卷管理系统MySQL 2、项目功能描述 基于springboot问卷调查管理系统包括以下功能&#xff1a; 1、系统登录、系统注册 2、创建题目、题目信息查看 3、创建问卷、我的问卷信息查看 4、创建活动、我的活动信息…

看Threejs好玩示例,学习创新与技术(ThreePipe)

下面这个示例我觉得特别棒&#xff0c;我会推荐给我们的美工&#xff0c;以后产品的宣传图用它。比如下面这个图&#xff0c;不需要PS&#xff0c;仅需拖拽一个照片进去&#xff0c;它会自动铺到笔记本电脑上。完成后点击截图就可以得到高清图片&#xff0c;不需要摆拍和PS。大…

光伏设计难点在哪儿?如何解决?

一、光伏设计的主要难点 1.技术门槛高 光伏设计领域的一大难题在于技术使用的复杂性。用户往往需要下载并安装特定的软件和控件&#xff0c;这些工具操作复杂&#xff0c;增加了学习成本和使用难度。此外&#xff0c;现有的设计工具并非专为光伏设计而生&#xff0c;组件库不…

【华为】用策略路由解决双出口运营商问题

需求描述 不同网段访问互联网资源时&#xff0c;走不同的出口&#xff0c;即PC1走电信出口&#xff0c;PC2走移动出口。 客户在内网接口下应用策略路由后往往出现无法访问内网管理地址的现象&#xff0c;该举例给出解决办法。 拓扑图 基础配置 #sysname R1 # # interface G…

Android15音频进阶之新播放器HwAudioSource(八十六)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+…

亚马逊IP关联揭秘:发生ip关联如何处理

在亚马逊这一全球领先的电商平台上&#xff0c;IP关联是一个不可忽视的问题&#xff0c;尤其是对于多账号运营的卖家而言。本文将深入解析亚马逊IP关联的含义、影响以及应对策略&#xff0c;帮助卖家更好地理解和应对这一问题。 什么是亚马逊IP关联&#xff1f; 亚马逊IP关联…

Redis篇(应用案例 - 优惠卷秒杀)

目录 一、全局唯一ID 1. 简介 2. Redis实现全局唯一Id 3. 测试类 3.1. 关于 countdownlatch 3.2. CountDownLatch 中有两个最重要的方法 二、添加优惠卷 三、实现秒杀下单 四、库存超卖问题分析 六、乐观锁解决超卖问题 七、优惠券秒杀-一人一单 八、集群环境下的并…

1比25万基础电子地图(港澳版)

我们为你分享过四川、云南、江西、贵州、重庆、青海、西藏、新疆、甘肃、黑龙江、吉林、湖北、内蒙古、广东、广西、浙江、河南、湖南、宁夏、山西、陕西、天津、山东、河北、江苏、福建、辽宁、北京、安徽、上海、海南和台湾的1比25万基础电子地图&#xff0c;现在再为你分享港…

MySQL --数据类型

文章目录 1.数据类型分类2.数值类型2.1 tinyint类型2.2 bit类型2.3小数类型2.31float2.32decimal 3.字符串类型3.1 char3.2varchar3.3 char和varchar比较 4.日期和时间类型5.enum和set 1.数据类型分类 2.数值类型 2.1 tinyint类型 数值越界测试&#xff1a; create table tt1…

ubuntu内网穿透后在公网使用ssh登录

需求&#xff1a; 我有一台内网可以通过ssh 22端口访问的设备操作系统是ubuntu server我还有1台拥有公网IP的服务器&#xff0c;IP地址是 6.66.666.6666我想随时从其他网段通过ssh访问我的ubuntu server设备 实现&#xff1a; 工具准备&#xff1a;frp 网址&#xff1a;https…

Spring源码学习:SpringMVC(3)mvcannotation-driven标签解析【RequestMappingHandlerMapping生成】

目录 前言mvc:annotation-driven标签概述mvc:annotation-driven标签解析【RequestMappingHandlerMapping生成】AnnotationDrivenBeanDefinitionParser#parse &#xff08;解析入口&#xff09;RequestMappingHandlerMapping的实例化类图afterPropertiesSetAbstractHandlerMetho…

MySQL数据库——索引

目录 什么是索引&#xff08;Index&#xff09;&#xff1f; 怎样加索引&#xff1f; 索引的特点 索引类型 主键索引(Primary Key) 辅助索引&#xff08;二级索引&#xff09; 聚集索引和非聚集索引 聚集索引 非聚集索引 单列索引和联合索引 单列索引 联合索引 创…

mac Wireshark You do not have permission to capture on device “rvio“.

原因&#xff1a; 权限不足 解决方案&#xff1a; 打开终端在终端输入 whoamin (会在终端显示本机的实际用户名字) 例如&#xff1a;xiaoming进入 /dev 目录 cd /dev输入命令&#xff1a;ls -la | grep bp输入命令&#xff1a;sudo chown whoamin xiaoming:admin bp*重新打开 …