DTH11温湿度传感器
DHT11 是一款温湿度复合传感器,常用于单片机系统中进行环境温湿度的测量。以下是对 DHT11 温湿度传感器的详细讲解:
一、传感器概述
DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接。
二、主要特点
- 体积小、功耗低:适合集成到各种小型电子设备中。
- 数字信号输出:无需复杂的模拟信号处理,直接输出数字信号,方便与单片机进行通信。
- 响应速度快:能够快速准确地测量环境温湿度变化。
- 精度较高:温度测量范围为 0℃ - 50℃,精度为 ±2℃;湿度测量范围为 20% - 90% RH,精度为 ±5% RH。
三、工作原理
- 传感器通过单片机的一个 I/O 口进行通信。单片机向 DHT11 发送启动信号后,DHT11 开始采集温湿度数据。
- 采集完成后,DHT11 将温湿度数据转换为数字信号,并通过数据线逐位发送给单片机。
- 单片机接收到数据后,进行校验和处理,以确保数据的准确性。
四、通信协议
- 单片机与 DHT11 之间采用单总线数据格式进行通信。通信过程包括初始化、发送启动信号、接收数据等步骤。
- 初始化时,单片机将数据线拉低一段时间,然后释放数据线,等待 DHT11 的响应。
- 发送启动信号时,单片机将数据线拉低至少 18ms,然后释放数据线,等待 DHT11 的响应。
- DHT11 接收到启动信号后,会发送一个 80μs 的低电平响应信号,接着发送 80μs 的高电平响应信号,表示准备好发送数据。
- DHT11 发送的数据包括 40 位,分别为 8 位湿度整数数据、8 位湿度小数数据、8 位温度整数数据、8 位温度小数数据和 8 位校验和。数据以低位在前的方式逐位发送。
- 单片机接收到数据后,进行校验和计算。如果校验和正确,则表示数据接收成功;否则,需要重新进行数据采集。
五、使用方法
- 硬件连接:将 DHT11 的 VCC 引脚连接到单片机的电源引脚,GND 引脚连接到地,DATA 引脚连接到单片机的一个 I/O 口。
- 软件编程:在单片机程序中,需要实现 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);}
}
成功实现:
相关文章:
DTH11温湿度传感器
DHT11 是一款温湿度复合传感器,常用于单片机系统中进行环境温湿度的测量。以下是对 DHT11 温湿度传感器的详细讲解: 一、传感器概述 DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感…...
【Linux系列】CMA (Contiguous Memory Allocator) 简单介绍
CMA (Contiguous Memory Allocator) CMA是Linux内核中的一种内存分配机制,用于分配物理上连续的内存块。它主要解决了在系统运行一段时间后,物理内存碎片化导致难以分配大块连续物理内存的问题。 CMA的工作原理 在系统启动时,CMA会预留一块…...
基于单片机餐厅呼叫控制系统仿真设计
文章目录 前言资料获取设计介绍设计程序具体实现截图设计获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们…...
详细分析Mysql中的定时任务(Event事件)
目录 前言1. 基本知识2. Event事件3. Demo 前言 基本的知识推荐阅读: 详细分析Mysql触发器的基本使用(图文解析)详细分析SQL Server触发器的基本知识详细分析Corn表达式(附Demo) 特性事件定时任务触发器触发条件基于…...
SpinalHDL之语义(Semantic)(三)
本文作为SpinalHDL学习笔记第七十一篇,介绍SpinalHDL的规则(Rules)。 目录: 1.简介(Introduction) 2.并⾏性(Concurrency) 3.以最后赋值为准(Last valid assignment wins) 4.Scala下的信号和寄存器的内在联系(Signal and register interactions with Scala)(OOP引⽤+函数…...
SpringBoot 请求和响应
1. Spring Boot 请求与响应概述 在 Spring Boot 开发中,客户端通过浏览器发起请求,后端使用内置的 Tomcat Web 服务器处理请求,返回响应数据。请求和响应的过程遵循 HTTP 协议。Spring Boot 的核心 Servlet 程序是 DispatcherServlet&#x…...
LQR算法核心思想
本章以倒立摆为解决目的 什么是线性二次型控制器(LQR) 开环系统 即状态变量的倒数 系统的状态空间矩阵A * 系统状态变量x A状态矩阵:描述系统本身物理特性的一个矩阵,它是由系统本身的机械结构、物理结构决定的,无法…...
AI大模型之旅-最强开源文生图工具Stable Diffusion WebUI 教程
1.1克隆 Automatic1111 的 GitHub 仓库 在你想安装 Web UI 的文件夹路径下执行 git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui 这将会克隆整个仓库到本地。 这里会默认访问 https://huggingface.co/ 下载 因此需要魔法 1.2 进入仓库目录 cd stable-di…...
WinForm程序嵌入Web网页
文章目录 前言一、三方库或控件的选择测试二、Microsoft Edge WebView2安装、使用步骤1.安装2.使用 前言 由于此项目需要winform客户端嵌入web网页并于JAVA端交互数据,所以研究了一下嵌入web网页这部分,趟了一遍雷,这里做下记录。 一、三方库…...
Redis string类型hash类型
string类型 类型介绍 在Redis中的所有的key都是string类型,而value的类型有多种。 Redis中的字符串是直接按照二进制的方式进行存储的,也就是不会做任何的编码转换,存的是什么,取出来的就是什么。这样一般来说,Redi…...
Solidity智能合约中的异常处理(error、require 和 assert)
Solidity 中的三种抛出异常方法:error、require 和 assert 在 Solidity 开发中,异常处理是确保智能合约安全性和正确性的关键步骤。Solidity 提供了三种主要方法来抛出异常:error、require 和 assert。本文将详细介绍这三种方法的用途、实现方…...
True NAS禁用ipv6
在 TrueNAS Scale 中,禁用 IPv6 的方法如下:12 进入 System->Advanced->Sysctl,设置一个 sysctl 可调整变量 net.ipv6.conf.all.disable_ipv6,值为 1,以完全禁用 IPv6。\...
笔记整理—linux进程部分(2)使用fork创建进程
为什么要创建进程,首先每个程序的运行都需要一个进程;多进程实现宏观上的并行。 fork的原理,是进程的分裂生长模式。如果操作系统需要一个新的进程,那么就会以cp的方法得到一个新的进程,此时老的进程是父进程ÿ…...
在Python中实现多目标优化问题(6)
在Python中实现多目标优化问题 在Python中实现多目标优化,除了传统的进化算法(如NSGA-II、MOEA/D)和一些基于机器学习的方法外,还有一些新的方法和技术。这些新方法通常结合了最新的研究成果,提供了更高效的解决方案。…...
Java EE中的编码问题及解决方案
Java EE中的编码问题及解决方案 在Java EE开发中,处理字符编码是确保数据正确传输和显示的重要环节。不同的编码不一致会导致乱码,影响用户体验。本文将总结在Java EE中可能遇到的编码问题及其解决方案。 1. 输入数据编码问题 在表单提交时,…...
9月27日,每日信息差
第一、中国科学家团队在干细胞治疗领域取得重要突破,通过化学重编程技术成功制备出胰岛细胞,并用于移植治疗一名 1 型糖尿病患者,实现了临床功能性治愈。相关研究成果已发表在国际权威期刊《细胞》上。 第二、交通运输部公路局局长周荣峰在国…...
什么是 Angular 开发中的 Dumb components
Dumb components,在 Angular 开发中也被称为 Presentational components,它们的主要职责是通过展示数据和触发事件,把业务逻辑和 UI 表现分离开来。Dumb components 只通过 Input() 接收数据,Output() 向外发送事件,不…...
Docker 进入容器运行命令的详细指南
Docker 进入容器运行命令的详细指南 Docker 是一个开源的容器化平台,广泛应用于开发和生产环境中。它允许开发者打包应用程序及其依赖项到容器中,并能够在不同的平台上快速部署和运行。容器通常是独立且隔离的,但在开发、调试或维护过程中&a…...
如何禁止非真实用户的ip访问网站服务器
为了禁止非真实用户的IP访问网站服务器,可以采用多种技术手段和策略。以下是一些常用的方法: 1. 使用IP黑名单和白名单 黑名单:定期更新和维护一个IP黑名单,阻止已知的恶意IP地址或数据中心IP访问网站。白名单:对于特…...
探索SpringBoot:学科竞赛管理项目开发
2 相关技术简介 2.1Java技术 Java是一种非常常用的编程语言,在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中,Java的身影无处不在,并且拥有旺盛的生命力。Java的跨平台能力十分强大,只需一次编译,任…...
ultralytics yolo v8 示例:加载官方模型进行推理
Ultralytics YOLO 是计算机视觉和 ML 领域专业人士的高效工具。 安装 ultralytics 库: pip install ultralytics 实现代码如下: import cv2 from ultralytics import YOLO# 加载预训练的 YOLOv8n 模型 ckpt_dir "./ckpt/" # 模型缓存地址…...
【中间件学习】Nginx快速入门(为了配置一个项目)
-----------------------------本文章借鉴遇见狂神说--------------------------- 一、一个产品出现瓶颈?? 在一个产品刚刚上线的时候,并发量小,用户使用的少,所以在低并发的情况下,一个jar包启动应该就够…...
鸿蒙harmonyos next flutter通信之MethodChannel获取设备信息
本文将通过MethodChannel获取设备信息,以此来演练MethodChannel用法。 建立channel flutter代码: MethodChannel methodChannel MethodChannel("com.xmg.test"); ohos代码: private channel: MethodChannel | null nullthis.c…...
【笔记】原子结构的近代理论
近代原子结构理论的建立是从氢原子光谱得到启示的。 一、氢原子光谱与波尔理论 1.氢原子光谱 在装有两个电极的真空玻璃管内通入极少量高纯氢气,通高压电使之放电,管中发出的光束通过分光棱镜,得到分立的谱线,称为线状光谱。 发…...
【python】循环中断:break 和 continue
目录: while 循环的基础语法while 循环的基础案例while 循环的嵌套应用while 循环的嵌套案例for 循环的基础语法for 循环的嵌套应用循环中断:break 和 continue综合案例 学习目标: 掌握使用 continue 和 break 关键字控制循环 思考&#…...
WIFI密码默认显示
文章目录 需求分析遇到问题问题原因解决方案 需求 在进入设置,点击某一个wifi,连接wifi 界面,显示密码默认选中状态,效果如下 分析 在 WiFi密码被输入法挡住 中我们已经分析了整个流程,布局文件和控制中心。 结局系统设置WIFI连…...
Emiya 家今天的饭C++
题目: 样例解释: 【样例 1 解释】 由于在这个样例中,对于每组 i,j,Emiya 都最多只会做一道菜,因此我们直接通过给出烹饪方法、主要食材的编号来描述一道菜。 符合要求的方案包括: 做一道用烹饪方法 1、主要…...
Mybatis缓存机制(图文并茂!)
目录 一级缓存 需求我们在一个测试中通过ID两次查询Monster表中的信息。 二级缓存 案例分许(和上述一样的需求) EhCache第三方缓存 在了解缓存机制之前,我们要先了解什么是缓存: 缓存是一种高速存储器,用于暂时存储访问频繁的数据&…...
Git 工作区、暂存区和版本库
Git 工作区、暂存区和版本库 Git 是一个强大的版本控制系统,它帮助开发者管理代码历史,协作开发,以及跟踪和合并更改。为了更好地理解 Git 的工作流程,我们需要了解 Git 中的三个核心概念:工作区(Workspac…...
SSH 远程连接到 Linux 服务器上的 SQLite
通过 SSH 远程连接到 Linux 服务器上的 SQLite 数据库文件的流程,可以分为以下几个步骤: 通过 SSH 连接到远程 Linux 服务器。在远程服务器上执行 SQLite 命令行工具,操作数据库文件。在本地使用工具,通过 SSH 隧道间接访问远程的…...
如何在建设银行网站预约纪念币/深圳网络营销推广招聘网
NSDecimalNumber 是NSNumber的子类。 使用 [NSNumber numberWithDouble:]方法来格式我的NSNumber,但是,由于一些值比较大,我想要用科学计数法来表示。 NSDecimalNumber就提供了科学计数法的表示方法。 什么是科学计数法? 将一个数…...
本地怎么做网站服务器吗/如何推广普通话
欢迎转载,转载请注明出自:www.androidkaifa.com,安卓开发网 开发中对于地图及地理位置的定位是我们经常要用地,地图功能的使用使得我们应用功能更加完善,下面www.androidkaifa.com 总结了一下网络中现有对于介绍android定位的几…...
什么网站有做册子版/学生没钱怎么开网店
创业公司怎样才能被大公司收购?对于一家创业公司来说,虽然自己坚持下去也是个不错的选择,不过要是被像苹果或Google这样最具价值的公司收购,那将是一件无比激动人心的事,那怎么做才能受到它们的青睐,吸引它…...
涞水住房和城乡建设委员会网站/seo网站推广批发
前言:要秋招了,复习一下应对秋招,纠结该先看啥,最后决定先学习《Java高并发编程详解》,此博客为看书所写的笔记,因为是笔记,所以会只记比较重要的东西,不适合初学者。 参考…...
沧州做网站/免费建站哪个比较好
数据库的种类大型数据库有:Oracle、Sybase、DB2、SQL server 小型数据库有:Access、MySQL、BD2等。 2007年4月29日消息,国外媒体报道,据权威调研机构IDC初步数据显示,尽管微软SQL Server发展迅猛,但甲骨文…...
武进常州做网站/新闻软文发布平台
一、背景 工作中经常涉及任务调度,一直都是采用while(true) > if hitted DO > Thread.Sleep(interval)的模式。但是最近实在是感觉这种实现模式很挫。并且没有考虑到性能问题,需要撞击n次才能命中一次,使用效率不足5%(一百次…...