ESP8266驱动DHT11模块

1. ESP8266与DHT11的硬件连接


DHT11模块驱动引脚接的是ESP8266模块的GPIO5引脚。

2. DHT11属性

2.1 DHT11模块特点

含有校准数字信号, 可测量环境温度, 相对湿度。 具有极高的可靠性与卓越的长期稳定性。 模块带有电源指示灯。 主要特点如下:

  1. 测量相对湿度范围:5~95%RH
  2. 测量温度范围:-20~60℃
  3. 支持 3.3V~5.5V 工作电压

2.2 模块用途

DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。 它应用专用的数字模块采集技术和温湿度传感技术, 确保产品具有枀高的可靠性与卓越的长期稳定性。 传感器包括一个电容式感湿元件和一个 NTC 测温元件, 并与一个高性能 8 位单片机相连接。
根据 DHT11 的特点, DHT11 模块可以应用在暖通空调、 除湿器、 农业、 冷链仓储、 测试及检测设备、 消费品、 汽车、 自动控制、 数据记录器、 气象站、 家电、 湿度调节器、 医疗、 其他相关湿度检测控制 等方面。

2.3 DHT11通信协议

DHT11 传感器采用简化的单总线通信。 单总线即只有一根数据线, 系统中的数据交换、 控制均由单总线完成。 设备(主机或从机) 通过一个漏极开路或三态端口(单片机 IO 口) 连至该数据线, 以允许设备在不发送数据时能够释放总线(由上拉电阻控制, 把总线上拉成高电平) , 而让其它设备使用总线;单总线通常要求外接一个约 4.7kΩ 的上拉电阻, 这样, 当总线闲置时, 其状态为高电平。由于它们是主从结极, 只有主机呼叫从机时, 从机才能应答, 因此主机访问器件都必须严格遵循单总线序列,如果出现序列混乱, 器件将不响应主机。
DHT11 采用单总线通讯协议,与单片机(主机) 的通讯的过程:主机发送起始信号—>DHT11 检测到并发送响应信号—>DHT11 发送 40 位数据(高位先出) —>DHT11 发送结束信号。

接收到的 40 位数据为:湿度高 8 位,湿度低 8 位,温度高 8 位,温度低 8 位,8 位校验位。湿度的高 8位是测量湿度的整数, 湿度的低 8 位是测量湿度的小数(湿度的小数部分为 0);温度的高 8 位是测量温度的整数, 温度的低 8 位是测量温度的小数;8 位校验和 = 湿度高 8 位 + 湿度低 8 位 + 温度高 8 位 + 温度低 8位, 可参考下图:

- 数据通信协议
用户主机(MCU)发送一次开始信号后, DHT11 从低功耗模式转换到高速模式,待主机开始信号结束后, DHT11 发送响应信号,送出 40bit 的数据,并触发一次信采集。信号发送如图所示。

注:主机从 DHT11 读取的温湿度数据总是前一次的测量值,如两次测间隔时间很长,请连续读两次以第二次获得的值为实时温湿度值。

- 外设读取步骤
步骤一:
DHT11 上电后(DHT11 上电后要等待 1S 以越过不稳定状态在此期间不能发送任何指令),测试环境温湿度数据,并记录数据,同时 DHT11 的 DATA 数据线由上拉电阻拉高一直保持高电平;此时 DHT11 的DATA 引脚处于输入状态,时刻检测外部信号。

步骤二:
微处理器的 I/O 设置为输出同时输出低电平,且低电平保持时间不能小于 18ms(最大不得超过 30ms),然后微处理器的 I/O 设置为输入状态,由于上拉电阻,微处理器的 I/O 即 DHT11 的 DATA 数据线也随之变高,等待 DHT11 作出回答信号,发送信号如图所示:

步骤三:
DHT11 的 DATA 引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后 DHT11 的 DATA引脚处于输出状态,输出 83 微秒的低电平作为应答信号,紧接着输出 87 微秒的高电平通知外设准备接收数据,微处理器的 I/O 此时处于输入状态,检测到 I/O 有低电平(DHT11 回应信号)后,等待 87 微秒的高电平后的数据接收,发送信号如图所示:

步骤四:
由 DHT11 的 DATA 引脚输出 40 位数据,微处理器根据 I/O 电平的变化接收 40 位数据,位数据“0”的格式为: 54 微秒的低电平和 23-27 微秒的高电平,位数据“1”的格式为: 54 微秒的低电平加 68-74微秒的高电平。位数据“0”、“1”格式信号如图所示:

结束信号:
DHT11 的 DATA 引脚输出 40 位数据后,继续输出低电平 54 微秒后转为输入状态,由于上拉电阻随之变为高电平。但 DHT11 内部重测环境温湿度数据,并记录数据,等待外部信号的到来。

2.4 参考代码

/*
* dht11.c
*
*  Created on: 2019年1月15日
*      Author: Marshal
*/#include "driver/dht11.h"
#include "driver/delay.h"// 全局变量
//==================================================================================
// DHT11_Data_Array[0] == 湿度_整数_部分
// DHT11_Data_Array[1] == 湿度_小数_部分
// DHT11_Data_Array[2] == 温度_整数_部分
// DHT11_Data_Array[3] == 温度_小数_部分
// DHT11_Data_Array[4] == 校验字节
// DHT11_Data_Array[5] == 【1:温度>=0℃】【0:温度<0℃】
//-----------------------------------------------------
u8 DHT11_Data_Array[6] = { 0 };    // DHT11数据数组
u8 DHT11_Data_Char[2][10] = { 0 }; // DHT11数据字符串【行:湿/温度】【列:数据字符串】// DHT11_Data_Char[0] == 【湿度字符串】// DHT11_Data_Char[1] == 【温度字符串】//==================================================================================/**函数名称:void Dht11OutputConfig(bool val)*函数功能:设置DHT11为输出模块*函数形参:bool val 高低电平*返  回  值:无*硬件连接:GPIO5* */
void Dht11OutputConfig(bool val)
{PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5);   // GPIO5设为IO口GPIO_OUTPUT_SET(GPIO_ID_PIN(5), val);//主机发送高电平
}/*
*函数名称:void Dht11InputConfig(void)
*函数功能:设置DHT11为输入模块
*函数形参:无
*返  回  值:无
*硬件连接:GPIO5
* */
void Dht11InputConfig(void)
{PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5);   // GPIO5设为IO口GPIO_DIS_OUTPUT(GPIO_ID_PIN(5));
}/*
*函数名称:u8 Dht11Star(void)
*函数功能:判断DHT11模块释放存在
*函数形参:无
*返  回  值:
*           0:存在  非0:不存在
*硬件连接:GPIO5
* */
u8 Dht11Star(void)
{u8 UsFlag = 0;Dht11OutputConfig(1);//DelayMs(1);//起始信号 -- 主机把数据总线拉低 T(18ms < T < 30ms), 通知传感器准备数据Dht11OutputConfig(0);DelayMs(20);//释放总线Dht11OutputConfig(1);DelayUs(5);//接受响应信号//设置为输入模式,才能接收信号Dht11InputConfig();//等待接收响应信号70US以上while (GPIO_INPUT_GET(GPIO_ID_PIN(5)) == 1 && UsFlag < 70){DelayUs(1);UsFlag++;}if (UsFlag >= 70) return 1;//响应超时UsFlag = 0;//假如低电平时间太长,认为模块有问题while (GPIO_INPUT_GET(GPIO_ID_PIN(5)) == 0 && UsFlag < 200){DelayUs(1);UsFlag++;}if (UsFlag >= 200)return 1;//响应超时elsereturn 0;
}/*
*函数名称:u8 DHT11ReadBit(void)
*函数功能:DHT11模块独一位数据
*函数形参:无
*返  回  值:
*           0/1
*硬件连接:GPIO5
* */
u8 DHT11ReadBit(void)
{u8 UsFlag = 0;    // 延时计时// 等待响应信息的低电平【最迟等150us】while (GPIO_INPUT_GET(GPIO_ID_PIN(5)) == 1 && UsFlag<150){DelayUs(1);        // 1us计时UsFlag++;}UsFlag = 0;        // 低电平计时开始// 数据位的低电平时长计时【最多200us】while (GPIO_INPUT_GET(GPIO_ID_PIN(5)) == 0 && UsFlag<120){DelayUs(1);UsFlag++;  // 低电平时长}// 数据位的低电平结束后,是数据位的高电平// 数据"0"的高电平时长 == [23~27us]// 数据"1"的高电平时长 == [68~74us]DelayUs(45);  // 跳过数据"0"的高电平部分// 延时45us后,检测信号线电平 此时电平为高就输出数据1 电平为低就输出数据0return GPIO_INPUT_GET(GPIO_ID_PIN(5));
}/*
*函数名称:u8 DHT11ReadByte(void)
*函数功能:DHT11模块读一个字节数据
*函数形参:无
*返  回  值:
*           返回一个字节数据
*硬件连接:GPIO5
* */
u8 DHT11ReadByte(void)
{u8 Bit = 0;   // 位计数u8 T_DHT11_Byte_Data = 0;    // DHT11字节数据for (Bit = 0; Bit<8; Bit++)       // 读取DHT11一个字节{T_DHT11_Byte_Data <<= 1;T_DHT11_Byte_Data |= DHT11ReadBit(); // 一位一位的读取}return T_DHT11_Byte_Data;    // 返回读取字节
}/*
*函数名称:u8 DHT11ReadDataComplete(void)
*函数功能:DHT11模块读取所有数据
*函数形参:无
*返  回  值:
*           0:数据读取成功
*           非0:数据读取失败
*硬件连接:GPIO5
* */
u8 DHT11ReadDataComplete(void)
{u8 UsFlag = 0;    // 延时计时// 启动DHT11传输_成功//------------------------------------------------------------------------if (Dht11Star() == 0) // DHT11:输出起始信号->接收响应信号{DHT11_Data_Array[0] = DHT11ReadByte();    // 湿度_整数_部分DHT11_Data_Array[1] = DHT11ReadByte();  // 湿度_小数_部分DHT11_Data_Array[2] = DHT11ReadByte();  // 温度_整数_部分DHT11_Data_Array[3] = DHT11ReadByte();  // 温度_小数_部分DHT11_Data_Array[4] = DHT11ReadByte();  // 校验字节// 如果此时是最后一位数据的高电平,则等待它结束while (GPIO_INPUT_GET(GPIO_ID_PIN(5)) == 1 && UsFlag < 100){DelayUs(1);     // 1us计时UsFlag++;}UsFlag = 0;        // 低电平计时开始// 结束信号的低电平时长计时while (GPIO_INPUT_GET(GPIO_ID_PIN(5)) == 0 && UsFlag < 100){DelayUs(1);       // 1us计时UsFlag++;}if (UsFlag >= 100)return 1;     // 返回1,表示:结束信号的低电平时长超时// 数据校验if (DHT11_Data_Array[4] ==DHT11_Data_Array[0] + DHT11_Data_Array[1] +DHT11_Data_Array[2] + DHT11_Data_Array[3]){// 读取DHT11数据结束,ESP8266接管DHT11信号线//-----------------------------------------------------------//os_delay_us(10);//DHT11_Signal_Output(1); // DHT11信号线输出高(ESP8266驱动)// 判断温度是否为 0℃以上//----------------------------------------------if ((DHT11_Data_Array[3] & 0x80) == 0){DHT11_Data_Array[5] = 1;      // >=0℃}else{DHT11_Data_Array[5] = 0;      // <0℃DHT11_Data_Array[3] &= 0x7F;  // 更正温度小数部分}return 0;   // 返回0,表示:温湿度读取成功}else return 3;      // 返回3,表示:校验错误}else return 2;     // 返回2,表示:启动DHT11传输,失败
}/*
*函数名称:void DHT11NUMChar(void)
*函数功能:将DHT11读取的数据全部转为字符串
*函数形参:无
*返  回  值:无
* */
void DHT11NUMChar(void)
{u8 C_char = 0;        // 字符计数// 湿度数据字符串if(DHT11_Data_Array[0] / 100)          // 湿度整数的百位DHT11_Data_Char[0][C_char++] = DHT11_Data_Array[0] / 100 + 48;if((DHT11_Data_Array[0] % 100) / 10)    // 湿度整数的十位DHT11_Data_Char[0][C_char++] = (DHT11_Data_Array[0] % 100) / 10 + 48;// 湿度整数的个位DHT11_Data_Char[0][C_char++] = DHT11_Data_Array[0] % 10 + 48;DHT11_Data_Char[0][C_char++] = '.';      // 小数点// 湿度整数的小数DHT11_Data_Char[0][C_char++] = DHT11_Data_Array[1] % 10 + 48;DHT11_Data_Char[0][C_char++] = ' ';       // ' 'DHT11_Data_Char[0][C_char++] = '%';        // '%'DHT11_Data_Char[0][C_char++] = 'R';        // 'R'DHT11_Data_Char[0][C_char++] = 'H';        // 'H'DHT11_Data_Char[0][C_char] = 0;        // 添0C_char = 0;       // 重置// 温度数据字符串if(DHT11_Data_Array[5] == 0)           // 温度 < 0℃DHT11_Data_Char[1][C_char++] = '-';if(DHT11_Data_Array[2] / 100)          // 湿度整数的百位DHT11_Data_Char[1][C_char++] = DHT11_Data_Array[2] / 100 + 48;if((DHT11_Data_Array[2] % 100) / 10)    // 湿度整数的十位DHT11_Data_Char[1][C_char++] = (DHT11_Data_Array[2] % 100) / 10 + 48;// 湿度整数的个位DHT11_Data_Char[1][C_char++] = DHT11_Data_Array[2] % 10 + 48;DHT11_Data_Char[1][C_char++] = '.';      // 小数点// 湿度整数的小数DHT11_Data_Char[1][C_char++] = DHT11_Data_Array[3] % 10 + 48;DHT11_Data_Char[1][C_char++] = ' ';       // ' 'DHT11_Data_Char[1][C_char++] = 'C';        // 'C'DHT11_Data_Char[1][C_char] = 0;        // 添0
}
/*
* dht11.h
*
*  Created on: 2019年1月15日
*      Author: Marshal
*/#ifndef APP_INCLUDE_DRIVER_DHT11_H_
#define APP_INCLUDE_DRIVER_DHT11_H_#include "ets_sys.h"
#include "osapi.h"
#include "user_interface.h"
#include "driver/uart.h"
#include "gpio.h"
#include "eagle_soc.h"
#include "driver/delay.h"extern u8 DHT11_Data_Array[6];   // DHT11数据数组
extern u8 DHT11_Data_Char[2][10];   // DHT11数据字符串【行:湿/温度】【列:数据字符串】void Dht11OutputConfig(bool val);
void Dht11InputConfig(void);
u8 Dht11Star(void);
u8 DHT11ReadBit(void);
u8 DHT11ReadByte(void);
u8 DHT11ReadDataComplete(void);
void DHT11NUMChar(void);#endif /* APP_INCLUDE_DRIVER_DHT11_H_ */
/*
* timer.c
*
*  Created on: 2018年8月14日
*      Author: 小良哥
*/#include "driver/delay.h"
#include "driver/led.h"
#include "driver/key.h"
#include "driver/uart.h"
#include "driver/timer.h"
#include "driver/dht11.h"/*
* 函数名称:void TimerInitConfig(uint32_t DelayMs,bool repeat_flag)
* 函数功能:定时器初始化函数
* 函数形参:
*       uint32_t DelayMs   延时时间
*       bool repeat_flag   是否重复
*               1:重复   0:不重复
* 返回值:
* */
os_timer_t os_timer_500ms;//定义一个定时器名称
void TimerInitConfig(uint32_t DelayMs, bool repeat_flag)
{os_timer_disarm(&os_timer_500ms);//关闭定时器os_timer_setfn(&os_timer_500ms, (os_timer_func_t *)TimerBackFunction, NULL);//设置定时器回调函数os_timer_arm(&os_timer_500ms, DelayMs, repeat_flag);
}/*
* 函数名称:void TimerBackFunction(void)
* 函数功能:定时器回调函数
* 函数形参:无
* 返回值:   无
* */
void TimerBackFunction(void)
{if(DHT11ReadDataComplete() == 0)     // 读取DHT11温湿度值{//-------------------------------------------------// DHT11_Data_Array[0] == 湿度_整数_部分// DHT11_Data_Array[1] == 湿度_小数_部分// DHT11_Data_Array[2] == 温度_整数_部分// DHT11_Data_Array[3] == 温度_小数_部分// DHT11_Data_Array[4] == 校验字节// DHT11_Data_Array[5] == 【1:温度>=0】【0:温度<0】//-------------------------------------------------// 温度超过30℃,LED亮//----------------------------------------------------if(DHT11_Data_Array[5] == 1 && DHT11_Data_Array[2] >= 30)GPIO_OUTPUT_SET(GPIO_ID_PIN(4), 0);     // LED亮elseGPIO_OUTPUT_SET(GPIO_ID_PIN(4), 1);      // LED灭// 串口输出温湿度//---------------------------------------------------------------------------------if(DHT11_Data_Array[5] == 1)          // 温度 >= 0℃{os_printf("\r\n湿度 == %d.%d %RH\r\n", DHT11_Data_Array[0], DHT11_Data_Array[1]);os_printf("\r\n温度 == %d.%d ℃\r\n", DHT11_Data_Array[2], DHT11_Data_Array[3]);}else // if(DHT11_Data_Array[5] == 0) // 温度 < 0℃{os_printf("\r\n湿度 == %d.%d %RH\r\n", DHT11_Data_Array[0], DHT11_Data_Array[1]);os_printf("\r\n温度 == -%d.%d ℃\r\n", DHT11_Data_Array[2], DHT11_Data_Array[3]);}// OLED显示温湿度//          DHT11NUMChar(); // DHT11数据值转成字符串}
}
void ICACHE_FLASH_ATTR user_init(void)
{int i;os_DelayMs(1000);uart_init(115200, 115200);//设置串口波特率while (Ds18b20InitConfig()){}//  LedInitConfig();//LED灯初始化函数//   KeyInitConfig();//按键初始化函数// KeyExtiInitConfig();//配置按键外部中断TimerInitConfig(500, 1);//通过定时器回调采集DHT数据//    hw_timer_set_func();//  HwTimerInitConfig();os_printf("=============================================\r\n");os_printf("\t SDK version:\t%s", system_get_sdk_version());os_printf("\r\n嵌入式陈工个人编辑资料\r\n未经本人同意请勿私自传播\r\n");//    os_printf("\r\n温度数据为%d\r\n,Ds18b20ReadTemp()");os_printf("\r\n带看门狗\r\n");os_printf("\r\nSPI Flash 的 ID 号:%d\r\n", spi_flash_get_id());os_printf("=============================================\r\n");
}

源代码参考:https://github.com/ChenJiliang00/ESP8266

ESP8266--驱动DHT11相关推荐

  1. ⑦ ESP8266 开发学习笔记_By_GYC 【ESP8266 驱动 DHT11 温湿度传感器】

    目录 一.准备材料 二.硬件连接 三.软件编程 1.修改工程名 2.添加组件 3.编程 4.反馈结果 5.核心代码 四.总结 ⑦ ESP8266 开发学习笔记_By_GYC [ESP8266 驱动 D ...

  2. ESP8266和DHT11通讯

    文章目录 DHT11介绍 1.通讯与数据说明 2. DHT11通讯实现 3.官方程序 1:输出启动信号>>接受响应信号 2.读取一个位的数据 3.数据用结构体保存 4.ESP8266 SD ...

  3. vc 控制台添加托盘显示_开源:ESP8266读DHT11温湿度,小程序实时显示

    第一.原理讲解 原理简述:利用发布订阅模式.第一步,先读取DHT11温湿度数值,第二步,新建主题,然后esp8266往这个主题发送消息,第三步.小程序通过http API接口获取数据.小程序控制原理: ...

  4. esp8266驱动_【直播视频】微信小程序连接阿里云物联网控制esp8266实现rgb调节。...

    前天晚上感谢各位小伙伴的捧场直播:我今年下半年立志会出一档实战视频<微信和支付宝小程序如何控制esp8266>,会第一时间通知大家! 昨晚在遇到一些小问题,耽误了一个小时,开始直播时候喉咙 ...

  5. ESP8266 驱动1.3寸SH1106 OLED屏幕显示库

    ESP8266 驱动1.3寸SH1106 OLED屏幕显示库 Adafruit_SH110X 接线说明 SDA---D2(GPIO4) SCL---D1(GPIO5) 驱动示例程序 /******** ...

  6. 用esp8266驱动0.96寸OLED屏幕 太空人动画

    昨天闲来没事玩了一下OLED屏幕 之前只是做过显示图片 还没弄过动画的 (其实差不多–) 用esp8266驱动0.96寸LED屏幕 太空人动画 入门esp8266 看这篇文章 参考https://bl ...

  7. ESP8266驱动1.44寸TFT屏幕(例程问题)

    ESP8266驱动1.44寸TFT屏幕(例程问题) 一.接线说明 二.引脚对应 D1 - 5 D2 - 4 D3 - 0 三.修改例程 将D1.D2.D3改成5.4.0然后编译上传即可 .D2.D3改 ...

  8. 【玩玩硬件】esp8266驱动墨水屏

    本项目是使用esp8266驱动点亮微雪家的2.13寸墨水屏代码教程 (随缘更新) 在github地址上排版比这里会好看很多, 觉得帮助到你能否点个star~ 目录简介 source: 源代码文件 fo ...

  9. 08.ESP8266驱动WS2812彩灯

    本篇介绍ESP8266使用NeoPixel库来驱动IOT Kit板载WS2812彩灯. 1. WS2812彩灯介绍 WS2812是一个集控制电路与发光电路于一体的智能外控LED光源,外型与5050LE ...

  10. 使用ESP8266驱动微雪e-paer2.13墨水屏

    使用ESP8266驱动微雪e-paer墨水屏 前些时候使用Arduino nona小板子,成功驱动了微雪e-paer2.13墨水屏,但由于Arduino nona小板子内存小.主频低,虽然可以显示,但 ...

最新文章

  1. mysql低级知识坑
  2. 博客作业05--查找
  3. python3.6.5安装教程-Centos7 安装Python3.6.
  4. Kafka Java consumer动态修改topic订阅
  5. Mac计算器的计算过程怎么看?教你一键查看运算记录!
  6. C++基础——函数模板
  7. SQL Server数据库占用过多内存的解决方法
  8. (3) numpy数组保留小数位数
  9. 面试结束后,向面试官要问的问题
  10. centos 7.6编译安装nginx
  11. 01 HA haproxy 功能简介以及应用
  12. kali安装wps办公软件
  13. Java程序设计的基本结构 - 选择结构
  14. 微信网页授权的2种方式
  15. 计算机程序是通过专利保护,《专利审查指南》修改后计算机程序的专利保护研究.doc...
  16. 我主修计算机科学英文,计算机科学,computer science英语短句,例句大全
  17. 我们要做杨百万,不做杨白劳
  18. 转一首普希金的诗,给郁闷的日子煽煽情!
  19. sqlserver 查询语句时,显示列名无效
  20. node04-buffer

热门文章

  1. 第四届“”世安杯“”线上赛题解(Web+Stego+Misc+Crypto)
  2. 阐述矩阵初等变换方法在线性代数中的应用
  3. C语言输入月份,输出月份的英文名
  4. Xcode中的iOS模拟器(iOS Simulator)的介绍和使用心得
  5. 数据库框架Sugar的使用
  6. Element UI 之table表格的封装
  7. 2019届爱奇艺秋招笔试题【局长的食物】【清雨的自助餐】【库特君的面条】
  8. 拿下10亿新融资 华云数据开启A股上市新征程
  9. 使用unity制作瞄准镜
  10. 1507四舍五入c语言,Excel工作表中的“四舍五入”都不掌握,还敢称Excel达人?