DTH11温湿度传感器

news2024/9/27 13:38:18

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 毫秒,发送启动信号给 DHT11
    dht = 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 还是 0
    DH11_Star(); // 调用启动 DHT11 的函数

    for (i = 0; i < 5; i++) {
        // 卡 g 点:等待 DHT11 将引脚拉低,表示开始发送一组数据
        while (!dht);

        // 有效数据都是高电平,持续时间不一样,延时 50us 后根据引脚电平判断数据是 0 还是 1
        for (j = 0; j < 8; j++) {
            while (!dht); // 等待引脚拉低,表示开始读取一位数据
            Delay40us(); // 延时 40 微秒,根据引脚在这个时间后的电平判断数据位

            if (dht == 1) {
                flag = 1; // 如果引脚为高电平,标志位设为 1,表示读取到的数据位是 1
                while (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)延时 15ms
    Delay15ms();

    //(2)写指令 38H(不检测忙碌信号) 
    Write_Cmd_Func(0x38);

    //(3)延时 5ms
    Delay5ms();

    //(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();
    // 初始化 LCD1602
    LCD1602_Init();
    // 再次延时 1000 毫秒
    Delay1000ms();
    Delay1000ms();
    // 设置 ledOne 为 0,可能用于控制某个 LED
    ledOne = 0;

    while (1) {
        // 延时 1000 毫秒
        Delay1000ms();
        // 读取 DHT11 传感器的数据
        Read_Data();

        // 如果温度(datas[2])大于等于 24
        if (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.coloradmin.cn/o/2170123.html

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

相关文章

如何在Unity WebGL上实现一套全流程简易的TextureStreaming方案

项目介绍 《云境》是一款使用Unity引擎开发的WebGL产品&#xff0c;有展厅&#xff0c;剧本&#xff0c;Avatar换装&#xff0c;画展&#xff0c;语音聊天等功能&#xff0c;运行在微信小程序和PC&#xff0c;移动端网页&#xff0c;即开即用。 当前问题和现状 当前项目…

Qt-QTableWidget多元素控件(37)

目录 描述 QTableWidget 方法 QTableWidgetItem 信号 QTableWidgetItem 方法 使用 图形化界面操作 代码操作 描述 这是一个表格控件&#xff0c;表格中的每一个单元格&#xff0c;都是一个 QTableWidgetItem 对象 QTableWidget 方法 item(int row,int column)根据⾏数…

[半导体检测-7]:半导体检测技术:无图案晶圆检测与图案晶圆检测

前言&#xff1a; 半导体检测技术中&#xff0c;无图案晶圆检测与图案晶圆检测是两种重要的检测方式&#xff0c;它们在检测原理、应用场景及挑战等方面存在显著差异。以下是对这两种检测技术的详细分析&#xff1a; 一、无图案晶圆检测 1. 检测原理 无图案晶圆检测主要关注…

DRF实操学习——收货地址的设计

DRF实操学习——收货地址的设计 1.行政区划表的设计2. 行政区划表接口演示1.返回所有的省份2. 查询指定上级行政区划的所有子区划&#xff0c;以及展示自身区划 3.行政区划表接口重写补充&#xff1a;前端请求逻辑4. 优化5.收货地址的设计6. 收货地址表接口重写7.优化1. 优化返…

Android 12系统源码_输入系统(三)输入事件的加工和分发

前言 上一篇文章我们具体分析了InputManagerService的构造方法和start方法&#xff0c;知道IMS的start方法经过层层调用&#xff0c;最终会触发Navite层InputDispatcher的start方法和InputReader的start方法。InputDispatcher的start方法会启动一个名为InputDispatcher的线程&…

混拨动态IP代理的优势是什么

在当今互联网时代&#xff0c;隐私保护和网络安全成为了人们关注的焦点。无论是个人用户还是企业&#xff0c;都希望能够在网络上自由、安全地进行各种活动。混拨动态IP代理作为一种新兴的技术手段&#xff0c;正逐渐受到大家的青睐。那么&#xff0c;混拨动态IP代理到底有哪些…

【工具】JDK版本不好管理,SDKMAN来帮你

前言 &#x1f34a;缘由 SDKMAN真是好&#xff0c;JDK切换没烦恼 &#x1f423; 闪亮主角 大家好&#xff0c;我是JavaDog程序狗 今天跟大家能分享一个JDK版本管理工具SDKMAN 当你同时使用JDK 1.8的和JDK 17并行维护两个项目时。每次在两个项目之间并行开发&#xff0c;切…

进阶数据库系列(十三):PostgreSQL 分区分表

概述 在组件开发迭代的过程中&#xff0c;随着使用时间的增加&#xff0c;数据库中的数据量也不断增加&#xff0c;因此数据库查询越来越慢。 通常加速数据库的方法很多&#xff0c;如添加特定的索引&#xff0c;将日志目录换到单独的磁盘分区&#xff0c;调整数据库引擎的参…

2.4卷积3

2.4卷积3 文章学习自https://zhuanlan.zhihu.com/p/41609577&#xff0c;详细细节请读原文。 狄拉克 δ \delta δ 函数&#xff1a; δ ( x ) { ∞ , x 0 0 , x ≠ 0 \delta (x){\begin{cases} \infty ,& x0\\ 0,& x\neq 0\end{cases}} δ(x){∞,0,​x0x0​ 并…

小柴冲刺软考中级嵌入式系统设计师系列二、嵌入式系统硬件基础知识(2)嵌入式微处理器基础

目录 冯诺依曼结构 哈佛结构 一、嵌入式微处理器的结构和类型 1、8位、16位、32位处理器的体系结构特点 2、DSP处理器的体系结构特点 3、多核处理器的体系结构特点 二、嵌入式微处理器的异常与中断 1、异常 2、中断 flechazohttps://www.zhihu.com/people/jiu_sheng …

54 循环神经网络RNN_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录循环神经网络使用循环神经网络的语言模型困惑度&#xff08;perplexity&#xff09;梯度剪裁 循环神经网络 使用循环神经网络的语言模型 输入“你”&#xff0c;更新隐变量&#xff0c;输出“好”。 困惑度&#xff08;perplexity&#xff…

【递归】8. leetcode 671 二叉树中第二小的节点

题目描述 题目链接&#xff1a;二叉树中第二小的节点 2 解答思路 注意这句话&#xff1a;该节点的值等于两个子节点中较小的一个 二叉树的根节点的值是整棵树中最小的值 本道题所要求的是二叉树中第二小的节点。因为根节点是最小的节点&#xff0c;那么我们只需要找到第一…

HT5169内置BOOST升压的11W I2S输入D类音频功放

1 特性 ● 电源供电 升压输入VBAT:2.5V-5.5V; 升压输出PVDD可调&#xff0c;最高7.5V DVDD/AVDD分辨率:3.3V ● 音频性能 9.0W (VBAT3.7V, PVDD 7.5V, RL3Ω.THDN10%) 11.0W(VBAT3.7V, PVDD 7.5V, RL2Ω.THDN10% 5.5W (VBAT3.7V, PVDD 6.5V, RL4Ω.THDN10%) ● 灵活的…

红米k60至尊版工程固件 MTK芯片 资源预览 刷写说明 与nv损坏修复去除电阻图示

红米k60至尊版机型代码为:corot。 搭载了联发科天玑9200+处理器。此固件mtk引导为MT6985。博文将简单说明此固件的一些特点与刷写注意事项。对于NV损坏的机型。展示修改校验电阻的图示。方便改写参数等 通过博文了解 1💝💝💝-----此机型工程固件的资源刷写注意事项 2…

css 中 ~ 符号、text-indent、ellipsis、ellipsis-2、text-overflow: ellipsis的使用

1、~的使用直接看代码 <script setup> </script><template><div class"container"><p><a href"javascript:;">纪检委</a><a href"javascript:;">中介为</a><a href"javascript:…

曲线图异常波形检测系统源码分享

曲线图异常波形检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comput…

【cache】浅析四种常用的缓存淘汰算法 FIFO/LRU/LFU/W-TinyLFU

本文浅析淘汰策略与工作中结合使用、选取&#xff0c;并非针对算法本身如何实现的 文章目录 FIFOLFULRUW-TinyLFU实践与优化监控与调整 FIFO first input first output &#xff0c; 先进先出&#xff0c;即最早存入的元素最先取出&#xff0c; 典型数据结构代表&#xff1a;…

SpringCloud-Netflix第一代微服务快速入门

1.springCloud常用组件 Netflix Eureka 当我们的微服务过多的时候&#xff0c;管理服务的通信地址是一个非常麻烦的事情&#xff0c;Eureka就是用来管理微服务的通信地址清单的&#xff0c;有了Eureka之后我们通过服务的名字就能实现服务的调用。 Netflix Ribbon\Feign : 客…

Python精选200Tips:171-175

深度学习实战项目 P171--CIFAR10数据集图像分类(Image Classification)P172--MS COCO数据集物体检测(Object Detection)P173-- MNIST手写数字数据集DCGAN生成P174--基于EasyOCR的字符识别P175--基于Air Quality数据集的变分自编码器(Variational autoEncoder&#xff0c;VAE) 运…

QT版数据采集系统研发过程记录

研发目的&#xff1a;通过智能监测设备将各个变电站运行的电压、电流、温湿度等数据采集汇总到计算机中心服务器&#xff0c;通过系统软件展示各个站点对应的运行工况。 软件架构&#xff1a;使用QT开发跨平台&#xff08;Windows系统、Ubuntu20.04&#xff09;客户端软件、连…