第33章_瑞萨MCU零基础入门系列教程之DHT11温湿度获取实验

2023-09-13 23:11:31

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id=728461040949

配套资料获取:https://renesas-docs.100ask.net

瑞萨MCU零基础入门系列教程汇总https://blog.csdn.net/qq_35181236/article/details/132779862


第33章 DHT11温湿度获取实验

33.1 DHT11简介

33.1.1 产品概述

DHT11是一款可测量温度和湿度的传感器。比如市面上一些空气加湿器,会测量空气中湿度,再根据测量结果决定是否继续加湿。

DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,具有超小体积、极低功耗的特点,使用单根总线与主机进行双向的串行数据传输。DHT11测量温度的精度为±2℃,检测范围为-20℃-60℃。湿度的精度为±5%RH,检测范围为5%RH-95%RH,常用于对精度和实时性要求不高的温湿度测量场合。

33.1.2 硬件连接

主机通过一条数据线与DH11连接,主机通过这条线发命令给DHT11,DHT11再通过这条线把数据发送给主机。

33.1.3 通信时序

主控发出开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,并送出40bit的数据,完成一次信号采集。DHT11接收到开始信号后触发一次温湿度采集,如果没有开始信号,DHT11不会主动进行温湿度采集。采集数据后转换到低速模式。

通讯过程如图所示:

  1. 总线空闲状态为高电平;
  2. 主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号;
  3. DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号;
  4. 主机发送开始信号结束后,延时等待20-40us后,读取DHT11的响应信号;

主机发送开始信号后,可以切换到输入模式,或者输出高电平均可,总线由上拉电阻拉高。

  • 总线为低电平,说明DHT11发送响应信号;
  • DHT11发送响应信号后,再把总线拉高80us,准备发送数据;
  • 每一bit数据都以50us低电平时隙开始,高电平的长短定了数据位是0还是1;如果读取响应信号为高电平,则DHT11没有响应,请检查线路是否连接正常;
  • 当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态;

33.1.4 数据位格式

  1. 数据‘0’

  1. 数据‘1’

33.2 模块配置

和DS18B20非常相似,DHT11也是一个单总线设备。对于时延函数的精度也达到微秒级,因而配置和DS18B20基本一致。DHT11使用的GPIO是P503。

33.2.1 GPIO配置

33.2.2 GPT配置

33.3 驱动程序

33.3.1 IO驱动

和DS18B20的IO驱动一模一样,参考《32.4.1 IO驱动》。

33.3.2 定时器驱动

和DS18B20的GPT驱动一模一样,参考《32.4.2 定时器驱动》。

33.4 DHT11模块

33.4.1 DHT11设备对象

要操作DHT11,只需要对它进行初始化、然后读取数值。抽象出如下结构体:

typedef struct DHT11Dev{
    unsigned int tempture;
    unsigned int humidity;
    int (*Init)(struct DHT11Dev *ptdev);
int (*Read)(struct DHT11Dev *ptdev);
}DHT11Device;

在drv_dht11.c中实现了一个DTH11Dev结构体,代码如下:

static struct DHT11Dev gDevice = {
    .tempture = 0,
    .humidity = 0,
    .Init = DHT11DevInit,
.Read = DHT11DevRead
};

最后需要向上层应用提供获取DHT11设备的接口:

struct DHT11Dev *DHT11GetDevice(void)
{
    return &gDevice;
}

33.4.2 初始化设备

初始化DHT11即初始化IO:

static int DHT11DevInit(struct DHT11Dev *ptdev)
{
    if(NULL == ptdev)   return -EINVAL;
    gDataDevice = IODeviceFind("DHT11 IO");
    if(NULL == gDataDevice)
    {
        printf("Failed to find DHT11 IO!\r\n");
        return -ENXIO;
    }
    if(ESUCCESS != gDataDevice->Init(gDataDevice))
    {
        printf("Failed to init GPIO!\r\n");
        return -EIO;
    }
    return ESUCCESS;
}

33.4.3 温湿度数据读取

DHT11的数据读取不像DS18B20那样需要发送指令,它完全依靠总线的时延特征来区分信号和数据:

static int DHT11DevRead(struct DHT11Dev *ptdev)
{
    if(NULL == ptdev)   return -EINVAL;
    unsigned int timeout = 100;
    static long long tmp = 0;
    unsigned int tempture_data_inter = 0, tempture_data_dec = 0;
    unsigned int humidity_data_inter = 0, humidity_data_dec = 0;
    unsigned char crc_data = 0;

    tmp = 0;
    // 主机拉低最少18ms
    gDataDevice->Write(gDataDevice, 0);
    mdelay(20);
    // 拉高等待DHT11响应,20-40us
    gDataDevice->Write(gDataDevice, 1);
    udelay(30);
    gDataDevice->Read(gDataDevice);
    while((gDataDevice->value==1) && (timeout!=0))
    {
        gDataDevice->Read(gDataDevice);
        udelay(1);
        timeout--;
    }
……………..(省略,读者自行阅读配套代码原文)
    // 响应DHT11拉低总线80us后再拉高总线80us
    if(crc_data==(tempture_data_inter + humidity_data_inter + tempture_data_dec + humidity_data_dec))
    {
        ptdev->tempture = tempture_data_inter;
        ptdev->humidity = humidity_data_inter;
        return ESUCCESS;
    }
    return -EIO;
}

33.5 测试程序

获取到DHT11设备且初始化后,即可开始读取数据。本次实验每隔1s读取一次,并将结果打印出来:

void DeviceTest(void)
{
    UartDevicesRegister();
    TimerDevicesRegister();
    IODevicesRegister();
    
    DHT11Device *pDevice = DHT11GetDevice();
    if(NULL == pDevice)
    {
        printf("Error. There is no DHT11 device!\r\n");
        return;
    }
    pDevice->Init(pDevice);
    printf("\r\n");
    while(1)
    {
        if(pDevice->Read(pDevice) == ESUCCESS)
        {
            printf("环境温度:%d℃ \t 环境湿度:%d℃ \r", pDevice->tempture, pDevice->humidity);
        }
        delay(1);
    }
}

33.6 测试结果

将程序烧录到开发板运行,可以观察到如下结果:


本章完
更多推荐

【SpringMVC】自定义注解

🎉🎉欢迎来到我的CSDN主页!🎉🎉🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚🌟在这里,我要推荐给大家我的专栏《SpringMVC》。🎯🎯🚀无论你是编程小白,还是有一定基础的程序员,这个专栏都能满足你的需求。我会用最简单易懂的语言,带你走进SpringMVC的世界,让你从零开始,一步步

设计模式:组合模式

目录组件代码实现优缺点源码中应用总结组合模式是一种结构型设计模式,用于将对象组织成树形结构,以表示“部分-整体”的层次结构。组合模式使得客户端可以统一地处理单个对象和组合对象,而不需要区分它们之间的差异。在组合模式中,有两种主要类型的对象:叶节点和组合节点。叶节点表示树结构中的最小单位,它们没有子节点。而组合节点则可以

求生之路2服务器搭建插件安装及详细的游戏参数配置教程linux

求生之路2服务器搭建插件安装及详细的游戏参数配置教程linux大家好我是艾西,在上一篇文章中我用windows系统给搭建演示了一遍怎么搭建自己的L4D2游戏。那么也有不少小伙伴想知道linux系统的搭建方式以及在这个过程中有什么区别。那么艾西今天就跟大家分享下用linux服务器系统搭建求生之路2(注:因PT原因本文中w

我用AI画了几张通信工程师工作照,大家看看像不像?

之前我给大家演示过AI写作。今年,我们玩点新花样,尝试一下AI绘画。我注册了百度的文心一格,打算绘制几幅和通信工程师有关的画,邀请大家一起鉴别一下AI的绘画能力。先来个简单的吧。绘画要求①:一个通信工程师在机房加班。大约十几秒钟,结果出来了——这幅画中规中矩。桌面上摆的终端不知道是啥。手是捏鼠标的姿势,可是鼠标明明就在

新概念英语(第二册)复习——Lesson 11 - Lesson15

前言一套教材,少就是多,别怀疑,别较真,努力去做,怕就怕今天用这个,明天用那个,你学十年不如别人学一年。一共96课,你可以每天1文章目录前言Lesson11-Onegoodturndeservesanother原文译文单词Lesson12-Goodbyeandgoodluck原文译文单词Lesson13-TheGree

Jmeter配置不同业务请求比例,应对综合场景压测

背景在进行综合场景压测时,遇到了如何实现不同的请求所占比例不同的问题。有人说将这些请求分别放到单独的线程组下,然后将线程组的线程数按照比例进行配置。这种方法不是很好,因为服务器对不同的请求处理能力不同,有的处理快,有的处理慢。若采取上述方案的话,并不会按照我们预期的比例进行并发。那么如何真实模拟按比例进行并发呢?此前使

【文生图系列】Stable Diffusion Webui安装部署过程中bug汇总(Linux系统)

文章目录bugs虚拟环境pythonPreparingmetadata(setup.py)gfpgan和cythonbugs看网上部署stablediffusionwebui的教程,很简单。而且我也有部署stablediffusionv1/v2的经验,想着应该会很快部署完stablediffusionwebui,但是没

【JavaEE】多线程案例-线程池

文章目录1.什么是线程池2.为什么要使用线程池(线程池有什么优点)3.如何使用Java标准库提供的线程池3.1创建一个线程池对象3.2什么是工厂模式3.3为什么要使用工厂模式3.4Executors创建不同具有不同特性的线程池3.5ThreadPool类的构造方法3.6线程池的拒绝策略3.7调用submit方法添加任务

如何使用高压放大器驱动高容性负载

使用高压放大器驱动高容性负载是一个具有挑战性的任务,需要仔细考虑电路设计和操作技巧。下面西安安泰Aigtek将为您介绍一些关于如何使用高压放大器驱动高容性负载的方法和注意事项。首先,让我们了解一下高容性负载。高容性负载通常指电容值较大的负载元件或电路,在实际应用中常见于声音系统、电力传输和电化学领域等。驱动高容性负载需

Android T 禁止应用添加窗口的操作

序什么情况下会出现我们需要禁止应用添加窗口的情况呢?假如有一个应用的窗口,我们点开后是透明的或者会影响到系统的使用,那么我们就有必要对这个窗口操作一下回顾我们在AndroidTWMS窗口相关流程中所讲的内容禁止应用添加窗口的操作有两种1.直接在客户端对应用禁止添加窗口2.在服务端禁止应用添加窗口客户端对应用禁止添加窗口

9.17 校招 实习 内推 面经

绿泡*泡:neituijunsir交流裙,内推/实习/校招汇总表格1、自动驾驶一周资讯-一汽与Mobileye签署战略合作,小鹏汽车将用经销商销售逐渐替换直营模式,原小鹏汽车副总裁加盟赛力斯自动驾驶一周资讯-一汽与Mobileye签署战略合作,小鹏汽车将用经销商销售逐渐替换直营模式,原小鹏汽车副总裁加盟赛力斯2、校招|

热文推荐