概述

DHT11模块使用一根data线实现信号触发以及数据反馈,信号格式参考如下

https://zhuanlan.zhihu.com/p/347904660

本文使用GPIO中断的方式采集反馈数据

知识点:GPIO、中断、事件组、定时器

平台

芯片 ESP8266EX

模组 ESP-12F

开发板 NodeMCU

SDK ESP8266_RTOS_SDK

branch master

code

点击查看代码
typedef struct dht11_isr_arg_t{
uint8_t status;//0-未发送触发信号,1-已发送触发信号
uint8_t num;//已采集的波形数量,有效数据是40bit
uint8_t bit_status;//采集1个波形的状态,0-接收到上升沿开始,1-接收到下降沿结束采集
EventGroupHandle_t event;//事件组
uint32_t clk;//用于记录波形时间
uint64_t data;//最终采集到的数据
}dht11_isr_arg_t; /**
* @brief 定时器中断函数,5个clk=1us
*/
void timer_isr(void *arg){
gpio_set_level(GPIO_NUM_2, !gpio_get_level(GPIO_NUM_2)); dht11_isr_arg_t *isr_arg = (dht11_isr_arg_t *)arg;
BaseType_t base;
xEventGroupSetBitsFromISR(isr_arg->event, 0x01, &base);
} /**
* @brief 初始化定时器
*/
void timer_init(void *arg){
hw_timer_init(timer_isr, arg);//注册定时器中断函数
hw_timer_set_reload(true);//允许重载,即循环定时,不止一次
hw_timer_set_clkdiv(TIMER_CLKDIV_16);//16分频
hw_timer_set_intr_type(TIMER_EDGE_INT);
hw_timer_set_load_data((TIMER_BASE_CLK >> hw_timer_get_clkdiv()));//5000000
hw_timer_enable(true);
} /**
* @brief 初始化LED
*/
void led_init(){
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = 1 << GPIO_NUM_2;
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
} /**
* @brief GPIO5的中断函数,上升沿和下降沿均触发
*/
void dht11_isr(void *arg){
dht11_isr_arg_t *isr_arg = (dht11_isr_arg_t *)arg;
//未发送触发信号直接退出
if(0 == isr_arg->status) return; //上升沿开始计时,下降沿结束计时并将数据写入
switch(isr_arg->bit_status){
case 0:
if(1 == gpio_get_level(GPIO_NUM_5)){
isr_arg->clk = hw_timer_get_count_data();
isr_arg->bit_status = 1;
}
break;
case 1:
if(0 == gpio_get_level(GPIO_NUM_5)){
isr_arg->data = isr_arg->data << 1;
//防止两次计时中间经历了定时器重载,实际上在定时器1s中断的情况下基本不存在,因为获取全部41bit数据大概只需要4.1ms
if(isr_arg->clk < hw_timer_get_count_data()){
isr_arg->clk += (TIMER_BASE_CLK >> hw_timer_get_clkdiv());
}
//高电平超过40us即认定为数据1
if(40*5 <= (isr_arg->clk - hw_timer_get_count_data())){
isr_arg->data |= 0x01;
}
isr_arg->num++;
isr_arg->bit_status = 0;
//40bit数据加上触发信号的响应,共41bit信号
if(41 <= isr_arg->num){
BaseType_t base;
xEventGroupSetBitsFromISR(isr_arg->event, 0x02, &base);
}
}
break;
default:
break;
}
} /**
* @brief 使用中断的形式驱动DHT11
* @brief 技术点-GPIO、中断、定时器、事件组
*/
void task_dht11(void *arg){
dht11_isr_arg_t isr_arg;
isr_arg.event = xEventGroupCreate();
//因data线同时需要输入输出,配置为开漏并使用内部上拉
gpio_config_t conf;
conf.mode = GPIO_MODE_OUTPUT_OD;
conf.intr_type = GPIO_INTR_ANYEDGE;
conf.pin_bit_mask = 1 << GPIO_NUM_5;
conf.pull_down_en = 0;
conf.pull_up_en = 1;
gpio_config(&conf);
gpio_install_isr_service(0);
gpio_isr_handler_add(GPIO_NUM_5, dht11_isr, &isr_arg); led_init();
timer_init(&isr_arg); while(1){
//等待定时器事件产生,发送触发信号
EventBits_t bits = xEventGroupWaitBits(isr_arg.event, 0x03, pdTRUE, pdFALSE, portMAX_DELAY);
if(0x01 != (bits | 0x01)) continue;
isr_arg.data = 0;
isr_arg.status = 0;
isr_arg.bit_status = 0;
isr_arg.clk = 0;
isr_arg.num = 0;
gpio_set_level(GPIO_NUM_5, 0);
os_delay_us(20000);
gpio_set_level(GPIO_NUM_5, 1);
isr_arg.status = 1;
os_delay_us(30);
printf("wait dht11 init data\n"); //等待数据采集完毕
bits = xEventGroupWaitBits(isr_arg.event, 0x03, pdTRUE, pdFALSE, portMAX_DELAY);
//防止DHT11异常,当再次接收到定时器事件时重置,间隔1s足够DH11正常响应
if(0x02 != (bits | 0x02)) continue;
uint8_t *data = &(isr_arg.data);
for(int i = 0; i < 8; i++){
printf("data[%d] = %d ", i, data[i]);
}
if(data[0] == (data[1] + data[2] + data[3] + data[4])){
printf("\nhumidity = %d.%d temperature = %d.%d\n", data[4], data[3], data[2], data[1]);
}
}
}

效果如下

点击查看代码
[21:32:11:516] wait dht11 init data␍␊
[21:32:11:526] data[0] = 78 data[1] = 4 data[2] = 27 data[3] = 1 data[4] = 46 data[5] = 1 data[6] = 0 data[7] = 0 ␍␊
[21:32:11:539] humidity = 46.1 temperature = 27.4␍␊
[21:32:12:517] wait dht11 init data␍␊
[21:32:12:527] data[0] = 78 data[1] = 5 data[2] = 27 data[3] = 0 data[4] = 46 data[5] = 1 data[6] = 0 data[7] = 0 ␍␊
[21:32:12:540] humidity = 46.0 temperature = 27.5␍␊
[21:32:13:517] wait dht11 init data␍␊
[21:32:13:527] data[0] = 92 data[1] = 7 data[2] = 27 data[3] = 9 data[4] = 49 data[5] = 1 data[6] = 0 data[7] = 0 ␍␊
[21:32:13:540] humidity = 49.9 temperature = 27.7␍␊

基于 ESP8266_RTOS_SDK 驱动 DHT11的更多相关文章

  1. 【tornado】系列项目(二)基于领域驱动模型的区域后台管理+前端easyui实现

    本项目是一个系列项目,最终的目的是开发出一个类似京东商城的网站.本文主要介绍后台管理中的区域管理,以及前端基于easyui插件的使用.本次增删改查因数据量少,因此采用模态对话框方式进行,关于数据量大采 ...

  2. 【tornado】系列项目(一)之基于领域驱动模型架构设计的京东用户管理后台

    本博文将一步步揭秘京东等大型网站的领域驱动模型,致力于让读者完全掌握这种网络架构中的“高富帅”. 一.预备知识: 1.接口: python中并没有类似java等其它语言中的接口类型,但是python中 ...

  3. 使用 Spring 2.5 基于注解驱动的 Spring MVC

    http://www.ibm.com/developerworks/cn/java/j-lo-spring25-mvc/ 概述 继 Spring 2.0 对 Spring MVC 进行重大升级后,Sp ...

  4. [置顶] 基于视频采集卡驱动的错误修改CX26828

    基于视频采集卡驱动的错误修改CX26828 1. 设置root密码 command:sudo passwd root 2.查看系统状态 输入命令:lsmod root@ubuntu:/home/yu# ...

  5. 使用 Spring 2.5 基于注解驱动的 Spring MVC--转

    概述 继 Spring 2.0 对 Spring MVC 进行重大升级后,Spring 2.5 又为 Spring MVC 引入了注解驱动功能.现在你无须让 Controller 继承任何接口,无需在 ...

  6. 基于领域驱动设计(DDD)超轻量级快速开发架构(二)动态linq查询的实现方式

    -之动态查询,查询逻辑封装复用 基于领域驱动设计(DDD)超轻量级快速开发架构详细介绍请看 https://www.cnblogs.com/neozhu/p/13174234.html 需求 配合Ea ...

  7. 基于“事件”驱动的领域驱动设计(DDD)框架分析

    摘抄自 从去年10月份开始,学了几个月的领域驱动设计(Domain Driven Design,简称DDD).主要是学习领域驱动设计之父Eric Evans的名著:<Domain-driven ...

  8. STM32驱动DHT11温湿度传感器

    DHT11 是一款湿温度一体化的数字传感器.该传感器包括一个电阻式测湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接.通过单片机等微处理器简单的电路连接就能够 实时的采集本地湿度和温 ...

  9. unittest框架扩展(基于代码驱动)自动化-下

    一.数据驱动/代码驱动优缺点: 使用数据驱动的好处:- 代码复用率高.同一测试逻辑编写一次,可以被多条测试数据复用,提高了测试代码的复用率,同时可以提高测试脚本的编写效率.- 异常排查效率高.测试框架 ...

  10. 基于领域驱动设计(DDD)超轻量级快速开发架构

    smartadmin.core.urf 这个项目是基于asp.net core 3.1(最新)基础上参照领域驱动设计(DDD)的理念,并参考目前最为了流行的abp架构开发的一套轻量级的快速开发web ...

随机推荐

  1. 7. The Singular Value Decomposition(SVD)

    7.1 Singular values and Singular vectors The SVD separates any matrix into simple pieces. A is any m ...

  2. HarmonyOS NEXT调优工具Smart Perf Host高效使用指南

      在软件开发的过程中,很多开发者都经常会遇到一些性能问题,比如应用启动慢.点击滑动卡顿.应用后台被杀等,想要解决这些问题势必需要收集大量系统数据.而在收集数据的过程中,开发者则需要在各种工具和命令之 ...

  3. HarmonyOS多音频播放并发政策及音频管理解析

      音频打断策略 多音频并发,即多个音频流同时播放.此场景下,如果系统不加管控,会造成多个音频流混音播放,容易让用户感到嘈杂,造成不好的用户体验.为了解决这个问题,系统预设了音频打断策略,对多音频播放 ...

  4. mysql 重新整理——sql 执行语句的顺序[五]

    前言 盗图: 其实在复杂的语句中,需要我们逐步去分析,然后呢,我们了解一些优化器到底是如何帮我们优化的,就知道到底是mysql怎么执行代码. 我把以前的丢了,后续补全.

  5. 存储过程编写·记(“xxx“在需要下列之一:if)

    存储过程编写·记("xxx"在需要下列之一:if) 使用的数据库为Oracle数据库,数据库客户端为DBeaver 简单来说,就是使用SQL语句进行一些函数编写,进而进行一些过滤啊 ...

  6. HarmonyOS NEXT应用开发之多层嵌套类对象监听

    介绍 本示例介绍使用@Observed装饰器和@ObjectLink装饰器来实现多层嵌套类对象属性变化的监听. 效果图预览 使用说明 加载完成后显示商品列表,点击刷新按钮可以刷新商品图片和价格. 实现 ...

  7. 阿里云2020上云采购季,你的ECS买好了吗?

    阿里云2020上云采购季,超级品类日,天天有爆款. 今日爆款推荐:云服务器. 重磅推荐两款,限时抢购. 新品共享型s6: 企业级共享型n4: 想看更多云产品,来阿里云采购季: https://www. ...

  8. Elastic与阿里云助力汽车及出行产业数字化转型

    ​简介:目前,阿里云和Elastic在全国已经有很多的项目正在开展合作,而在移动出行领域与享道出行的合作案例,则是代表性的. 在汽车产业变革逐步深入的当下,云计算.大数据等信息技术成为了汽车企业经历数 ...

  9. Flink + Iceberg + 对象存储,构建数据湖方案

    ​简介: 上海站 Flink Meetup 分享内容,如何基于Flink.对象存储.Iceberg 来构建数据湖生态. 本文整理自 Dell 科技集团高级软件研发经理孙伟在 4 月 17 日 上海站 ...

  10. dotnet core 不自动从 https 到 http 的 302 重定向

    本文记录一个已知问题,或者准确来说是设计如此的行为,在 dotnet core 下,无论是 dotnet core 3.1 还是 dotnet 5 或 dotnet 6 或 dotnet 7 等,如果 ...