stm32实用篇5:HAL库 DHT11 驱动

2023-11-20

DHT11是很常用的温湿度传感器,时序也比较简单,如下所示:

直接给出HAL库的驱动:

1 微秒级延时函数

HAL库并没有直接的微秒级延时函数,下面是自己实现的微秒堵塞延时函数(使用定时器TIM3);

/**
	* @brief 微秒级延时
	*/
void bsp_delay_us(uint16_t us)
{
	__HAL_TIM_SET_COUNTER(&htim3, 0);
	
	HAL_TIM_Base_Start(&htim3);
	
	while (__HAL_TIM_GET_COUNTER(&htim3) != us);
	
	HAL_TIM_Base_Stop(&htim3);
}

2 配置DHT11数据引脚的输出模式和输入模式;

/**
	* @brief DHT11 输出模式
	*/
static void DHT11_Mode_OUT_PP(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	GPIO_InitStruct.Pin = BSP_DHT11_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	
  HAL_GPIO_Init(BSP_DHT11_PORT, &GPIO_InitStruct);
}

/**
	* @brief DHT11 输入模式
	*/
static void DHT11_Mode_IN_NP(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	GPIO_InitStruct.Pin = BSP_DHT11_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;

  HAL_GPIO_Init(BSP_DHT11_PORT, &GPIO_InitStruct);
}

3 读取一个字节的数据(经过测试,延时时间最好设置为 40 ~ 60,这里我设置为50us);

/**
	* @brief DHT11 读取字节
	*/
uint8_t DHT11_ReadByte(void)
{
	uint8_t i, temp = 0;

	for (i = 0; i < 8; i++)
	{
		while (DHT11_IN == 0);    // 等待低电平结束
		
		// 经过测试,这个值最好是 40 ~ 60,这里我选择 50 us
        bsp_delay_us(50);     // 至少延时 40 微秒  低电平为 0 ,高电平为 1
		
		if (DHT11_IN == 1)
		{
			while (DHT11_IN == 1);	// 等待高电平结束
			
			temp |= (uint8_t)(0X01 << (7 - i));	    // 先发送高位 MSB
		}
		else
		{
			temp &= (uint8_t)~(0X01 << (7 - i));
		}
	}
	return temp;
}

4 完整的读取一次数据(读取数据间隔最好为2s及以上,不然容易出错);

/**
	* @brief DHT11 读取一次数据
	*/
uint8_t DHT11_ReadData(DHT11_Data_TypeDef *DHT11_Data)
{
	DHT11_Mode_OUT_PP();		// 主机输出,主机拉低
	DHT11_OUT_0;	
	HAL_Delay(18);					// 延时 18 ms
	
	DHT11_OUT_1;						// 主机拉高,延时 30 us
	bsp_delay_us(30);	

	DHT11_Mode_IN_NP();			// 主机输入,获取 DHT11 数据
	
	if (DHT11_IN == 0)			// 收到从机应答
	{
		while (DHT11_IN == 0);		// 等待从机应答的低电平结束
		
		while (DHT11_IN == 1);		// 等待从机应答的高电平结束
		
		/*开始接收数据*/   
		DHT11_Data->humi_int  = DHT11_ReadByte();
		DHT11_Data->humi_deci = DHT11_ReadByte();
		DHT11_Data->temp_int  = DHT11_ReadByte();
		DHT11_Data->temp_deci = DHT11_ReadByte();
		DHT11_Data->check_sum = DHT11_ReadByte();
		
		DHT11_Mode_OUT_PP();		// 读取结束,主机拉高
		DHT11_OUT_1;	
		
		// 数据校验
		if (DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int + DHT11_Data->temp_deci)	
		{
			return 1;
		}		
		else
		{
			return 0;
		}
	}
	else		// 未收到从机应答
	{
		return 0;
	}
}

测试程序:

while (1)
{
	if (DHT11_ReadData(&DHT11_Data))
	{
		DEBUG_INFO("\r\n读取DHT11成功!\r\n\r\n湿度为%d.%d %RH ,温度为 %d.%d℃ \r\n",		
		DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci);
	}
	else
	{
		DEBUG_INFO("Read DHT11 ERROR!\r\n");
	}

	HAL_Delay(3000);
}

完整的驱动程序,仅供参考。

bsp_dht11.c

/**
	******************************************************************************
	* @file			bsp_dht11.c
	* @author		
	* @date			
	* @version	v1.0
	* @note			DHT11 driver
	******************************************************************************
	*/

#include "tim.h"
#include "bsp_dht11.h"

/**
	* @brief DHT11 输出模式
	*/
static void DHT11_Mode_OUT_PP(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	GPIO_InitStruct.Pin = BSP_DHT11_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	
  HAL_GPIO_Init(BSP_DHT11_PORT, &GPIO_InitStruct);
}

/**
	* @brief DHT11 输入模式
	*/
static void DHT11_Mode_IN_NP(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	GPIO_InitStruct.Pin = BSP_DHT11_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;

  HAL_GPIO_Init(BSP_DHT11_PORT, &GPIO_InitStruct);
}

/**
	* @brief DHT11 读取字节
	*/
uint8_t DHT11_ReadByte(void)
{
	uint8_t i, temp = 0;

	for (i = 0; i < 8; i++)
	{
		while (DHT11_IN == 0);		// 等待低电平结束
		
		bsp_delay_us(40);					//	延时 40 微秒		低电平为 0 ,高电平为 1
		
		if (DHT11_IN == 1)
		{
			while (DHT11_IN == 1);	// 等待高电平结束
			
			temp |= (uint8_t)(0X01 << (7 - i));			// 先发送高位 MSB
		}
		else
		{
			temp &= (uint8_t)~(0X01 << (7 - i));
		}
	}
	return temp;
}

/**
	* @brief DHT11 读取一次数据
	*/
uint8_t DHT11_ReadData(DHT11_Data_TypeDef *DHT11_Data)
{
	DHT11_Mode_OUT_PP();		// 主机输出,主机拉低
	DHT11_OUT_0;	
	HAL_Delay(18);					// 延时 18 ms
	
	DHT11_OUT_1;						// 主机拉高,延时 30 us
	bsp_delay_us(30);	

	DHT11_Mode_IN_NP();			// 主机输入,获取 DHT11 数据
	
	if (DHT11_IN == 0)			// 收到从机应答
	{
		while (DHT11_IN == 0);		// 等待从机应答的低电平结束
		
		while (DHT11_IN == 1);		// 等待从机应答的高电平结束
		
		/*开始接收数据*/   
		DHT11_Data->humi_int  = DHT11_ReadByte();
		DHT11_Data->humi_deci = DHT11_ReadByte();
		DHT11_Data->temp_int  = DHT11_ReadByte();
		DHT11_Data->temp_deci = DHT11_ReadByte();
		DHT11_Data->check_sum = DHT11_ReadByte();
		
		DHT11_Mode_OUT_PP();		// 读取结束,主机拉高
		DHT11_OUT_1;	
		
		// 数据校验
		if (DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int + DHT11_Data->temp_deci)	
		{
			return 1;
		}		
		else
		{
			return 0;
		}
	}
	else		// 未收到从机应答
	{
		return 0;
	}
}

// 测试程序
/*
while (1)
{
	if (DHT11_ReadData(&DHT11_Data))
	{
		DEBUG_INFO("\r\n读取DHT11成功!\r\n\r\n湿度为%d.%d %RH ,温度为 %d.%d℃ \r\n",					\
		DHT11_Data.humi_int,DHT11_Data.humi_deci,DHT11_Data.temp_int,DHT11_Data.temp_deci);
	}
	else
	{
		DEBUG_INFO("Read DHT11 ERROR!\r\n");
	}

	HAL_Delay(3000);
}
*/

bsp_dht11.h

#ifndef __BSP_DHT11_H
#define __BSP_DHT11_H

#include "tim.h"
#include "stm32f1xx_hal.h"

#define BSP_DHT11_PORT		DHT11_GPIO_Port
#define BSP_DHT11_PIN			DHT11_Pin

#define DHT11_OUT_1				HAL_GPIO_WritePin(BSP_DHT11_PORT, BSP_DHT11_PIN, GPIO_PIN_SET)
#define DHT11_OUT_0				HAL_GPIO_WritePin(BSP_DHT11_PORT, BSP_DHT11_PIN, GPIO_PIN_RESET)

#define DHT11_IN					HAL_GPIO_ReadPin(BSP_DHT11_PORT, BSP_DHT11_PIN)

typedef struct
{
	uint8_t humi_int;				// 湿度的整数部分
	uint8_t humi_deci;	 		// 湿度的小数部分
	uint8_t temp_int;	 			// 温度的整数部分
	uint8_t temp_deci;	 		// 温度的小数部分
	uint8_t check_sum;	 		// 校验和
		                 
} DHT11_Data_TypeDef;

uint8_t DHT11_ReadData(DHT11_Data_TypeDef* DHT11_Data);

#endif	/* __BSP_DHT11_H */

 

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

stm32实用篇5:HAL库 DHT11 驱动 的相关文章

  • .inl文件

    背景 最近工作涉及到thrust库 看了半天也没找到一个头文件的函数定义 本来以为会有一个cpp源文件对应h头文件 后来问头文件的末尾发现了一个include lt inl gt 所以有必要了解这个文件组织形式 引用 作者 Return H
  • JSX、JSX的介绍、JSX特点、JSX的语法、XML基本语法

    1 JSX的介绍 什么是JSX JSX javascript xml就是Javascript和XML结合的一种格式 是 JavaScript 的语法扩展 只要你把HTML代码写在JS里 那就是JSX 在实际开发中 JSX 在产品 打包阶段
  • 自动驾驶路径规划与控制:讨论自动驾驶车辆的路径规划算法,如A*、Dijkstra等,以及控制策略,如PID控制等

    摘要 随着自动驾驶技术的快速发展 路径规划和控制算法在自动驾驶系统中扮演了越来越重要的角色 本文将探讨自动驾驶车辆的路径规划算法 如A 和Dijkstra 以及控制策略 如PID控制 同时 我们将引用相关论文 以便于深入了解这些技术的原理和
  • 中国互联网技术联盟推出国内首个“互联网+”资讯门户

    ITA1024中国互联网技术联盟7月正式推出专注 互联网 的资讯门户网站http abc ita1024 com 这也是国内首个专注于帮助中国企业有效落地 互联网 的服务平台 如果你是负责企业 互联网 转型战略的CEO CIO CFO CM
  • C++ MFC 导出ListControl数据到Excel

    一 导入对应的类 二 开启线程 void CLDITxtQueryDlg OnBnClickedBnExportToXLS TODO 在此添加控件通知处理程序代码 if ui ListCtrlDataResult GetItemCount
  • 并发编程 (6)一不小心就死锁了,怎么办?

    在上一篇文章中 我们用 Account class 作为互斥锁 来解决银行业务里面的转账问题 虽然这个方案不存在并发问题 但是所有账户的转账操作都是串行的 例如账户 A 转账户 B 账户 C 转账户 D 这两个转账操作现实世界里是可以并行的
  • 机器学习之LDA算法

    目录 LDA算法 LDA目标 LDA原理推导 LDA除法模型 LDA减法模型 LDA除法正则模型 LDA减法正则模型 证明 St Sw Sb LDA算法流程 LDA优点 LDA缺点 基于LDA的人脸识别 LDA算法 线性判别分析 linea
  • 2022Java面试题大全(整理版)面试题附答案详解,最全面详细

    目录 JAVA八股文 Java基础 String 和StringBuffer和 StringBuilder的区别 sleep 区间wait 区间有什么区别 Object 中有哪些方法 其中clone 怎么实现一个对象的克隆 Java如何实现
  • 安装MySQL出现Job for mysqld.service failed because the control process exited with error code

    这是因为无法再次初始化 解决办法 rm rf var lib mysql 然后重启service
  • 解决使用EasyPoi导入读取日期格式列获取值为null

    最近在做导入的时候发现 使用EasyPoi读取的日期值为null 这是我的Excel数据 如图 只是设置了列格式 我这里使用的是注解bean的方式解析读取 Map自由导入也尝试过 得到的结果都是null bean定义如下 Data Buil
  • 导出离散傅里叶变换(DFT)的两种方法

    1 原理部分 在这里首先确定DFT的对象为一个有限长的离散非周期序列 这主要因为计算机处理的都是有限长的离散序列 如果你要处理的序列本身不是离散非周期的序列 可以通过截取或者离散化等方法获得所需的有限长的离散非周期序列 对于有限长的离散非周
  • 第三周作业 token防爆破 (基于pikachu平台)burp token的暴力破解

    一 什么是token 简单的说token是由服务端生成的一串字符串 作为客户端向服务端请求的一个标识 在前端使用用户名 密码向服务端发送请求认证 服务端认证成功 那么在服务端会返回token给前端 前端在每次请求时会带上服务端发来的toke
  • SQL实现次日、三日及七日用户留存率的计算

    本篇博客学习如何用SQL来实现次日 三日及七日留存率的计算 假设有一个表 role login back 有字段 event time表示登陆日期时间和device id表示设备ID event time device id 2020 01
  • 【Flowable】Flowable工作流教程

    开始 Flowable是什么 Flowable是一个使用Java编写的轻量级业务流程引擎 Flowable流程引擎可用于部署BPMN 2 0流程定义 用于定义流程的行业XML标准 创建这些流程定义的流程实例 进行查询 访问运行中或历史的流程
  • Fedora 34成哑巴了?

    原由 前几天刚更新了Fedora34 完全沉浸在Gnome40的喜悦中 但是今天用耳机听Apple Music的时候完全傻了 音量控制旋钮调了半天也没有声音 难道声卡坏了 于是 我试探性的用Parrot下的FireFox听听网易云音乐 结果

随机推荐

  • 基于Matlab的故障检测的核PCA轮廓图

    作者简介 热爱科研的Matlab仿真开发者 修心和技术同步精进 matlab项目合作可私信 个人主页 Matlab科研工作室 个人信条 格物致知 内容介绍 早期故障监测在大型工业工厂中变得非常重要 因为早期故障的早期检测有助于避免重大工厂故
  • Java 中do...while()的使用

    博主前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住也分享一下给大家 点击跳转到网站 do while语句 基本格式 do 循环体语句 while 条件判断语句 完整格式 初始化语句 do 循环体语句 条件控制语句 whi
  • 3. 从0开始学ARM-ARM模式、寄存器、流水线

    关于ARM的一些基本概念 大家可以参考我之前的文章 到底什么是Cortex ARMv8 arm架构 ARM指令集 soc 一文帮你梳理基础概念 科普 关于ARM指令用到的IDE开发环境可以参考下面这篇文章 1 从0开始学ARM 安装Keil
  • Python爬虫被封ip解决方案

    在使用 Python 程序进行网络爬虫开发时 可能因以下原因导致被封 IP 或封禁爬虫程序 1 频繁访问网站 爬虫程序可能会在很短的时间内访问网站很多次 从而对目标网站造成较大的负担和压力 这种行为容易引起目标网站的注意并被封禁IP或限制访
  • python 文件、文件夹和路径操作笔记

    记录python关于文件夹 文件和路径的一些常用操作 方便用时查询 常用的函数备注 os listdir 列出文件夹中所有文件 os path splitext 获取文件的后缀名 返回list 后缀在list 1 中 os path joi
  • 解决win10应用程序图标丢失问题

    1 问题 sublime 软件图标莫名其妙不显示 2 解决办法 1 进入cmd命令提示符 2 输入如下内容 taskkill im explorer exe f cd d userprofile appdata local del icon
  • 数据库之MySQL大全

    目录 1 MySQL数据库概述 2 MySQL的安装 Install MySQL 3 MySQL的配置 4 E R模型 5 创建数据库 6 数据类型 7 创建数据表 8 修改数据表 9 数据表约束 非空与默认值 10 数据表约束 唯一键与自
  • In-Context Retrieval-Augmented Language Models

    本文是LLM系列文章 针对 In Context Retrieval Augmented Language Models 的翻译 上下文检索增强语言模型 摘要 1 引言 2 相关工作 3 我们的框架 4 实验细节 5 具有现成检索器的上下文
  • 利用python(networkx库)画带权&不带权有向图、无向图

    利用python networkx库 画带权 不带权有向图 无向图 效果展示 分段代码 全部源代码 传送门 https download csdn net download weixin 44978992 12719404 当我们处理完几百
  • TCP可靠传输的工作原理-停止等待&连续的ARQ(一)

    在网络传输中 我们认为最理想的传输状态就是 1 传输信道不产生差错 2 不管发送方以多块的速度发送数据 接收方都能来得及接受以及处理这些数据 当然 这种只是理想状态 在实际运用中 几乎是不可能的 因此 我们需要采取一些可靠的传输协议 1 当
  • 物联网平台相关IoTgo

    相关资源 http www geek workshop com thread 12726 1 1 html https github com itead IoTgo https github com itead IoTgo Android
  • h5 关于视频video在微信中的自动播放

    本来video只用autoplay就可以自动播放的 但是由于微信的限制 autoplay在微信中失效 解决方式
  • 软件测试/测试用例设计题详细整理— 助攻高薪求职之路

    前言 8月底了 即将步入金九银十 又有很多小伙伴开始霍霍找工作了 笔者最近也会比较偏向发面试题哟 希望可以帮助到大家 最近收到很多应聘者反馈过来的笔试面试问题 其中有一部分是关于测试用例设计 对了对了笔者发现无论是刚入职场的测试新人还是在具
  • 【内网安全】——windows信息收集

    作者名 Demo不是emo 主页面链接 主页传送门 创作初心 一切为了她 座右铭 不要让时代的悲哀成为你的悲哀专研方向 网络安全 数据结构 每日emo 爱是深渊 目录 一 windows信息收集简介 二 信息收集大纲 1 本机信息 1 系统
  • 【Zabbix实战之故障处理篇】Zabbix-proxy服务启动失败解决方法

    Zabbix实战之故障处理篇 Zabbix proxy服务启动失败解决方法 一 故障说明 1 故障说明 2 故障截图 二 配置环境检查 1 检查zabbix proxy conf文件 2 检查mysql8 0数据库状态 三 故障处理思路 四
  • Mysql如何对两张表的相同字段,同时查询两张数据表

    前言 假设现在有两张数据表 表1如下 表2如下 表1和表2同时都再mysql的情况下 只有他们的uuid是一样的 其他字段信息不同 现在需要用sql语句根据uuid 同时将符合要求的数据查询出来 怎么做呢 sql语句同时查询两张表 废话不多
  • appium - 常用操作

    from appium webdriver common touch action import TouchAction from appium webdriver common multi action import MultiActio
  • 【年度大戏】勒索”嘿客“无间道之战

    年度大戏 勒索 嘿客 无间道之战 为了保护多位表演群众 以下内容均以化名出现 所有图片取自对当事人的报告和贴吧原贴 历史群消息中 并均对ID打码处理 25仔的就不打了 本文只陈述基本事实基本推断 不做结论性推断 内容均无 伪造 瞎编 脑补意
  • Oracle 实现select(查询)的结果集随机顺序展示

    在一些需求中会要求打乱结果集顺序随机展示 Oracle的实现方式如下 select from table order by dbms random value 这种用法没有参数 会返回一个具有38位精度的数值 范围从0 0到1 0 但不包括
  • stm32实用篇5:HAL库 DHT11 驱动

    DHT11是很常用的温湿度传感器 时序也比较简单 如下所示 直接给出HAL库的驱动 1 微秒级延时函数 HAL库并没有直接的微秒级延时函数 下面是自己实现的微秒堵塞延时函数 使用定时器TIM3 brief 微秒级延时 void bsp de