OpenHarmony学习笔记——Hi3861使用DHT11获取温湿度

2023-11-06

前言

此文主要是使用Hi3861的GPIO口,模拟1—Wire时序,获取类单总线协议器件DHT11的温湿度信息,由于小熊派官方的温湿度采集是用的I2C接口的SHT30来实现的,而笔者手头没有这个模块,只有一个DHT11,结合前面的经验,Hi3861的代码逻辑跟STM32差不多,理论上是可以移植的,于是就有了以下写bug的时光。

DHT11简介

DHT11内部包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接,在使用过程中,这个内置的8位单片机会实时采集温湿度并做好转换,等到主机端的起始信号就开始发送40位的数据。学习过单总线的其他器件的同学都知道,单总线的一般通信流程是遵循初始化、ROM、命令功能命令三部曲来实现的,而DHT11由于内部有单片机的存在,所以不需要写入ROM和命令来实现功能,这需要一个起始信号即可实现数据传输。想要深入了解的同学可以参考此文——DHT11使用笔记。这里重点关注下其传输的一帧数据的内容。
在这里插入图片描述

数据传送正确时校验和数据等于“ 8bit 湿度整数数据 +8bit 湿度小数数据
+8bi 温度整数数据 +8bit 温度小数数据 ”所得结果的末8位。

通信流程

对于编程,最主要还是要搞清楚通信流程,尤其是这种使用GPIO进行模拟时序的。DHT11的通信流程如下:
1.总线初始化;(主机拉低总线,时长不小于18ms,然后拉高总线,使得总线回到高电平20-40us,等待从机应答)。
2.DHT11应答;(DHT11将总线拉低80us,然后再拉高80us)。
3.输出数据帧(一次完整的数据传输为40bit,高位先出)。
在这里插入图片描述
实测波形如下,后面框起来的是应答信号和40位的数据(图片截取自立创EDA的【DHT11温湿度计】)。
请添加图片描述
使用逻辑分析仪抓取的波形:
在这里插入图片描述

有关这个波形的详细讲解可以去看立创EDA的——【DHT11温湿度计】在示波器上的波形!

硬件连接

由于采用的是模拟1-Wire的时序,所以可以选取任意一个GPIO口来实现,笔者这里使用的是GPIO11,根据芯片手册最好是使用带上拉电阻的模块。
在这里插入图片描述
接线如下:

Hi3861开发板 DHT11引脚
GPIO11 OUT
5V +
GND -
在这里插入图片描述

编程实现

GPIO API简介

弄清楚了上述的通信流程,可以发现,整个过程中,传输数据的GPIO管脚需要进行输入与输出的切换,在产生起始信号时,GPIO需要配置为输出模式,产生高低电平的切换;在检测应答信号及接收数据时,需要配置成浮空输入模式检测总线的高低电平状态。在这个过程中需要使用到Hi3861的GPIO API接口函数。有关GPIO控制的接口函数目录位置为base\iot_hardware\interfaces\kits\wifiiot_lite
wifiiot_gpio.hwifiiot_gpio_ex.h包含了所有和GPIO操作有关的函数接口。
在这里插入图片描述
这里简介一下需要使用到函数,详细用法直接.h的注释吧,和STM32的GPIO类似:
在这里插入图片描述

复位总线

在产生起始信号时的配置方法:
首先,GpioInit()初始化GPIO;然后配置为普通IO模式;再然后配置为输出模式,最后根据时序要求配置输出高低电平。
笔者这里GPIO2是用来做运行指示灯的。代码如下:

#define DHT11_GPIO  WIFI_IOT_IO_NAME_GPIO_11
IO操作函数											   
#define	DHT11_DQ_OUT_High GpioSetOutputVal(DHT11_GPIO, 1); //设置GPIO输出高电平
#define	DHT11_DQ_OUT_Low GpioSetOutputVal(DHT11_GPIO, 0); //设置GPIO输出低电平  
/****************************************
设置端口为输出
*****************************************/
void DHT11_IO_OUT(void)
{
    //设置GPIO_11为输出模式
    GpioSetDir(DHT11_GPIO, WIFI_IOT_GPIO_DIR_OUT);
}
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在    	 
u8 DHT11_Init(void)
{	 
	//初始化GPIO
    GpioInit();
    //设置GPIO_2的复用功能为普通GPIO
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_2, WIFI_IOT_IO_FUNC_GPIO_2_GPIO);
    //设置GPIO_2为输出模式
    GpioSetDir(WIFI_IOT_GPIO_IDX_2, WIFI_IOT_GPIO_DIR_OUT);
		 //设置GPIO_2输出高电平点亮LED灯
    GpioSetOutputVal(WIFI_IOT_GPIO_IDX_2, 1);
    //设置GPIO_11的复用功能为普通GPIO
	 IoSetFunc(DHT11_GPIO, WIFI_IOT_IO_FUNC_GPIO_11_GPIO);
    //设置GPIO_11为输出模式
    GpioSetDir(DHT11_GPIO, WIFI_IOT_GPIO_DIR_OUT);
		 //设置GPIO_11输出高电平
    GpioSetOutputVal(DHT11_GPIO, 1);		    
		DHT11_Rst();  //复位DHT11
		 return DHT11_Check();//等待DHT11的回应
} 

//复位DHT11
void DHT11_Rst(void)	   
{                
	DHT11_IO_OUT(); 	//SET OUTPUT
   DHT11_DQ_OUT_Low; 	//拉低DQ
    hi_udelay(20000);//拉低至少18ms
   DHT11_DQ_OUT_High; 	//DQ=1 
	hi_udelay(35);     	//主机拉高20~40us
}

DHT11应答

在等待应答阶段,需要将GPIO口配置为浮空输入模式,并且需要检测GPIO的状态来判断DHT11连接是否正常。
代码流程:
首先将GPIO切换为输入模式,然后检测GPIO状态,判断总线的高低电平状态是否满足应答信号。
代码如下:

//获取GPIO输入状态
u8 GPIOGETINPUT(WifiIotIoName id,WifiIotGpioValue *val)
{
    GpioGetInputVal(id,val);
    return *val;
}

/****************************************
设置端口为输入
*****************************************/
void DHT11_IO_IN(void)
{
    GpioSetDir(DHT11_GPIO, WIFI_IOT_GPIO_DIR_IN);//配置为输入模式
    IoSetPull( DHT11_GPIO, WIFI_IOT_IO_PULL_NONE);//配置为浮空输入
}

//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
u8 DHT11_Check(void) 	   
{   
	u8 retry=0;
	  DHT11_IO_IN();//SET INPUT	 
    while (GPIOGETINPUT(DHT11_GPIO,&DHT11_DQ_IN)&&retry<100)//DHT11会拉低40~80us
	{
		retry++;
		hi_udelay(1);
	};	 
	if(retry>=100)return 1;
	else retry=0;
    
    while ((!GPIOGETINPUT(DHT11_GPIO,&DHT11_DQ_IN))&&retry<100)//DHT11拉低后会再次拉高40~80us
	{
		retry++;
		hi_udelay(1);
	};
	if(retry>=100)return 1;	   
	return 0;
}

数据读取

在检测到DHT11的应答后,DHT11会紧接着发送40位BIT的数据,需要通过固定时间间隔去读取总线状态来获取。
编程流程:
继续配置为输入模式,间隔固定时间去读取总线电平,进而得到数据,最后根据数据格式解析出所需内容。
代码如下:

//从DHT11读取一个位
//返回值:1/0
u8 DHT11_Read_Bit(void) 			 
{
 	u8 retry=0;
  while(GPIOGETINPUT(DHT11_GPIO,&DHT11_DQ_IN)&&retry<100){//等待变为低电平
        retry++;
        hi_udelay(1);
    }
    retry=0;
    while((!GPIOGETINPUT(DHT11_GPIO,&DHT11_DQ_IN))&&retry<100){//等待变高电平
        retry++;
        hi_udelay(1);
    }
    hi_udelay(40);//等待40us	//用于判断高低电平,即数据1或0
    if(GPIOGETINPUT(DHT11_GPIO,&DHT11_DQ_IN))return 1; else return 0;
}
//从DHT11读取一个字节
//返回值:读到的数据
u8 DHT11_Read_Byte(void)    
{        
    u8 i,dat;
    dat=0;
	for (i=0;i<8;i++) 
	{
   		dat<<=1; 
	    dat|=DHT11_Read_Bit();
    }						    
    return dat;
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
u8 DHT11_Read_Data(u8 *temp,u8 *humi)    
{        
 	u8 buf[5]={ 0 };
	u8 i;
	DHT11_Rst();
	if(DHT11_Check()==0)
	{
		for(i=0;i<5;i++)//读取40位数据
		{
			buf[i]=DHT11_Read_Byte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])//数据校验
		{
			*humi=buf[0];
			*temp=buf[2];
		}
	}else return 1;
	return 0;	    
}

以上三步对应的示波器实际效果如下图(图片截取自立创EDA):
请添加图片描述
注:这里的实现需要导入hi_time.h头文件,调用hi_udelay()实现而不能用usleep()函数。
至此就可以通过DHT11获取到温湿度了,上述代码有极少部分缺失,如有需要,私信笔者,建议大家自己试着配配看。

效果一览

在这里插入图片描述

总结

本文主要是使用使用Hi3861的GPIO口去模拟单总线的时序,进而读取到DHT11的温湿度值,整体代码可以参考任何一个STM32版本的代码,需要特别注意的是,整个过程中需要使用阻塞式的延时hi_udelay(1),而不能使用非阻塞式的usleep(),非阻塞式的延时会产生任务流转,会影响时序,造成数据读取失败,笔者踩了这个坑,分享给大家避雷用。

目录

OpenHarmony学习笔记——南向开发环境搭建
OpenHarmony学习笔记——编辑器访问Linux服务器进行编译
OpenHarmony学习笔记——点亮你的LED
OpenHarmony学习笔记——多线程的创建
OpenHarmony学习笔记——I2C驱动0.96OLED屏幕
OpenHarmony学习笔记——Hi3861使用DHT11获取温湿度
OpenHarmony学习笔记——Hi3861接入OneNET
手把手教你OneNET数据可视化
OpenHarmony学习笔记——Hi386+ASR-01的语音识别助手

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenHarmony学习笔记——Hi3861使用DHT11获取温湿度 的相关文章

  • java中如何创建一个多线程类呢?

    转自 java中如何创建一个多线程类呢 下文笔者讲述创建多线程类的方法分享 如下所示 实现思路 方式1 继承Thread类 重新Run方法 方式2 继承Runnable接口 重写Run方法 方式3 使用拉姆达表达式 例 package co

随机推荐

  • 陷波滤波器(Notch Filter)和峰值滤波器(Peak Filter)

    陷波滤波器 Notch Filter 陷波滤波器是带阻滤波器的一种 其阻带很窄 因此也称点阻滤波器 常常用于去除固定频率分量或阻带很窄的地方 如用于去除直流分量 去除某些特定频率分量 峰值滤波器与陷波滤波器恰好相反 峰值滤波器是带通滤波器的
  • Sublime Text 3高亮主题配置

    之前由于sublime的默认主题 灰白 比较难看 所以用得少 最近找到了一个比较漂亮的主题 再次因为sublime的轻便再次高频使用 先上图 以下是python代码的显示情况 这里使用的是theme freesia主题1 该主题下还有很多配
  • 构建模型三要素与权重初始化

    学习过程中的好文 谨防失效 转载自博客园 结合此篇看 1 模型三要素 三要素其实很简单 必须要继承nn Module这个类 要让PyTorch知道这个类是一个Module 在 init self 中设置好需要的组件 比如conv pooli
  • 操作数及寻址方式

    操作数是什么 操作数是指 指令执行的操作所需要数据的来源 操作数是汇编语言指令的一个字段 例如 Mov AX 5678H操作数 AX 5678H 在操作数这个字段中可以放操作数本身 也可以放操作地址 还可以放操作地址的计算方法 通常一条指令
  • 数据结构之链表及LinkedList源码分析

    链表 1 概念 链表 Linked list 是一种物理存储单元上非连续 非顺序的存储结构 数据元素的逻辑顺序是通过链表中的指针链接次序实现的 链表由一系列结点 链表中每一 个元素称为结点 组成 结点可以在运行时动态生成 每个结点包括两个部
  • 设置Qt窗体透明度

    第一步给窗体设置属性 setWindowFlags Qt FramelessWindowHint setAttribute Qt WA TranslucentBackground 第二部重写paintevent 方法 void Loadin
  • GPG 错误由于没有公钥,无法验证下列签名

    问题描述 输入apt get update 时 提示 没有数字签名 无法安全地用该源进行更新 所以默认禁用该源 主要原因是由于apt get update没有公钥 无法验证下列签名 错误 1 http mirrors aliyun com
  • Vuex状态管理详解

    Vuex详解 学习目录 vuex介绍 解释 Vuex是一个专门为Vue js应用程序开发的状态管理模式 它采用集中式存储管理应用的所有组件 并以相应的规则保证状态以一种可预测的方式发生变化 配套的公共数据管理工具 它可以把一些共享的数据放到
  • Styles and Themes

    http blog csdn net recordgrowth article details 52310974
  • 下载matlab内存不足怎么办,MATLAB 内存不足 "Out of memory" 解决办法

    如果你的系统是32位系统 进程最大支配2G空间 另外2G给系统进程了 在使用matlab 运行耗内存程序时候 会可能出现 out of memory 错误 这是因为matlab没有足够内存可以使用的缘故 解决的简单方法是加内存和升级为64位
  • Flash Linux to eMMC

    实验目的 从eMMC启动Linux系统 Step1 确定eMMC被挂在哪个设备 哪个设备含有boot0分区和boot1分区 就是eMMC 实验中是位于mmcblk1上 root am64xx evm ls l dev mmcblk brw
  • QT入门Input Widgets之QScrollBar

    目录 一 界面布局功能 1 界面位置介绍 2 控件界面基本属性 2 1 horizontalScrollBar界面属性 3 样式设置 此文为作者原创 创作不易 转载请标明出处 一 界面布局功能 1 界面位置介绍 QScrollBar主要分为
  • Python使用Matplotlib可视化多组并排的柱状图

    Python使用Matplotlib可视化多组并排的柱状图 Matplotlib是Python中最流行的数据可视化库之一 它可以创建各种类型的图表 包括线性图 散点图 饼图等等 在本文中 我们将重点介绍如何使用Matplotlib库创建多组
  • CyclicBarrier调试

    一CyclicBarrier 控制所有线程等待 知道达到某种条件 所有的线程才会继续走下去 是一个同步工具类 它允许一组线程互相等待 直到到达某个公共屏障点才停止等待 与CountDownLatch不同的是该barrier 屏障 在释放等待
  • 在vw中运行linux,Windows系统直接运行Linux,竟是如此简单

    要想在Windows10以前的系统上 运行Linux程序是比较复杂的 需要使用cygwin之类的工具 不仅下载慢 而且功能有限 后来出现了诸如VirtualBox VMWare Workstation和Microsoft Hyper V之类
  • 使用python随机生成IP+域名并写入excel表

    题目要求 使用python随机生成IP 随机域名 并创建excel表 将生成的随机IP与域名数据写入 代码如下 import random import socket import struct import xlwt book xlwt
  • Window 安装Hive

    基本环境资源 Hadoop 2 7 X Hive 2 1 X bin tar gz 版本 Hive 1 x src tar gz 源码版本 第一步 windows 安装Hadoop2 7 x 请参考 第二步 下载Hive tar gz 官网
  • ASP.NET Core 企业级开发架构简介及框架汇总

    ASP NET Core 企业开发架构概述 企业开发框架包括垂直方向架构和水平方向架构 垂直方向架构是指一个应用程序的由下到上叠加多层的架构 同时这样的程序又叫整体式程序 水平方向架构是指将大应用分成若干小的应用实现系统功能的架构 同时这样
  • VScode连接本地Docker

    一 安装VScode和Docker 1 vscode的安装 官网下载到最新的X64安装包 然后使用下述命令进行安装 dpkg i code 1 73 1 1667967334 amd64 deb 安装成功之后 可以在应用的安装列表中查看到
  • OpenHarmony学习笔记——Hi3861使用DHT11获取温湿度

    文章目录 前言 DHT11简介 通信流程 硬件连接 编程实现 GPIO API简介 复位总线 DHT11应答 数据读取 效果一览 总结 目录 前言 此文主要是使用Hi3861的GPIO口 模拟1 Wire时序 获取类单总线协议器件DHT11