1)实验平台:正点原子MiniPro H750开发板
2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-336836-1-1.html
4)对正点原子STM32感兴趣的同学可以加群讨论:879133275

第四十章 DHT11数字温湿度传感器

本章,我们将介绍数字温湿度传感器DHT11的使用,与前一章的温度传感器相比,该传感器不但能测温度,还能测湿度。我们将学习如何获取DHT11传感器的温湿度数据,并把数据显示在LCD上。
本章分为如下几个小节:
40.1 DHT11及其时序简介
40.2 硬件设计
40.3 程序设计
40.4 下载验证

40.1 DHT11及时序简介
40.1.1 DHT11简介
DHT11是一款温湿度一体化的数字传感器。该传感器包括一个电阻式测湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。通过单片机等微处理器简单的电路连接就能够实时的采集本地湿度和温度。DHT11与单片机之间能采用简单的单总线进行通信,仅仅需要一个I/O口。传感器内部湿度和温度数据40Bit的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。DHT11功耗很低,5V电源电压下,工作平均最大电流0.5mA。
DHT11的技术参数如下:
工作电压范围:3.3V ~ 5.5V
工作电流:平均0.5mA
输出:单总线数字信号
测量范围:湿度5 ~ 95%RH,温度-20 ~ 60℃
精度:湿度±5%,温度±2℃
分辨率:湿度1%,温度0.1℃
DHT11的管脚排列如图40.1.1所示:

图40.1.1.1 DHT11管脚排列图
40.1.2 DHT11时序简介
虽然DHT11与DS18B20类似,都是单总线访问,但是DHT11的访问,相对DS18B20来说简单很多。下面我们先来看看DHT11的数据结构。
DHT11数字温湿度传感器采用单总线数据格式。即,单个数据引脚端口完成输入输出双向传输。其数据包由5byte(40bit)组成。数据分小数部分和整数部分,一次完整的数据传输为40bit,高位先处。DHT11的数据格式为:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数部分+8bit校验和。其中校验和数据为前面四个字节相加。
传感器数据输出的是未编码的二进制数据。数据(湿度、温度、整数、小数)之间应该分开处理。例如,某次从DHT11读到的数据如图40.1.2.1所示:

图40.1.2.1 某次读取到DHT11数据
由以上数据就可得到湿度和温度的值,计算方法:
湿度 = byte4 . byte3 = 45.0(%RH)
温度 = byte2 . byte1 = 28.0(℃)
校验 = byte4 + byte3 + byte2 + byte1 = 73 (= 湿度 + 温度) (校验正确)
可以看出,DHT11的数据格式十分简单的,DHT11和MCU的一次通信最大为34ms左右,建议主机连续读取时间间隔不要小于2s。
下面,我们介绍一下DHT11的传输时序。DHT11的数据发送流程如图40.1.2.2所示:

图40.1.2.2 DHT11数据发送流程图
首先主机发送开始信号,即:拉低数据线,保持t1(至少18ms)时间,然后拉高数据线t2(1035us)时间,然后读取DHT11的响应,正常的话,DHT11会拉低数据线,保持t3(7888us)时间,作为响应信号,然后DHT11拉高数据线,保持t4(80~92us)时间后,开始输出数据。
DHT11输出数字‘0’时序如图40.1.2.3所示:

图40.1.2.3 DHT11数字‘0’时序图
DHT11输出数字‘1’的时序如图40.1.2.4所示:

图40.1.2.4 DHT11输出数字‘1’时序图
DHT11输出数字‘0’和‘1’时序,一开始都是DHT11拉低数据线54us,后面拉高数据线保持的时间就不一样,数字‘0’就是2327us,而数字‘1’就是6874us。
通过以上了解,我们就可以通过STM32H750来实现对DHT11的读取了。DHT11的介绍就到这里,更详细的介绍,请参考DHT11的数据手册。
40.2 硬件设计

  1. 例程功能
    本实验开机的时候先检测是否有DHT11存在,如果没有,则提示错误。只有在检测到DHT11之后才开始读取温湿度值,并显示在LCD上,如果发现了DHT11,则程序每隔100ms左右读取一次数据,并把温湿度显示在LCD上。LED0闪烁,提示程序运行。
  2. 硬件资源
    1)LED灯
    LED0 – PB4
    2)串口1(PA9/PA10连接在板载USB转串口芯片CH340上面)
    3)正点原子2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)
    4)DHT11传感器(接在PC13上)
  3. 原理图
    DHT11接口与STM32的连接关系跟上一章节中DS18B20和STM32的关系是一样的,使用到的GPIO口是PC13。这里原理图就不列出来了,可以翻看上一章节原理图。
    DHT11和DS18B20的接口是共用一个的,不过DHT11有4条腿,需要把U6的4个接口都用上,将DHT11传感器插入到这个上面就可以通过STM32来读取温湿度值了。连接示意图如图40.2.1所示:

图40.2.2 DHT11连接示意图
这里要注意,将DHT11贴有字的一面朝内,而有很多孔的一面(网面)朝外,然后插入如图所示的四个孔内就可以了。
40.3 程序设计
DHT11实验中使用的是单总线协议,用到的是HAL中GPIO相关函数,前面也有介绍到,这里就不做展开了。下面介绍一下如何驱动DHT11。
DHT11配置步骤
1)使能DHT11数据线对应的GPIO时钟。
本实验中DHT11的数据线引脚是PC13,因此需要先使能GPIOC的时钟,代码如下:
__HAL_RCC_GPIOC_CLK_ENABLE(); /* PC口时钟使能 */
2)设置对应GPIO工作模式(开漏输出)
本实验GPIO使用开漏输出模式,通过函数HAL_GPIO_Init设置实现。
3)参考单总线协议,编写信号代码(复位脉冲、应答脉冲、读0/1)
复位脉冲:拉低数据线,保持至少18ms时间,然后拉高数据线10~35us时间。
应答脉冲:DHT11拉低数据线,保持78~88us时间。
读0/1信号:DHT11拉低数据线延时54us,然后拉高数据线延时一定时间,主机通过判断高电平时间得到0或者1。
4)编写DHT11的读函数
基于读1bit数据的基础上,编写DHT11读1字节函数。
5)编写DHT11获取温度函数
参考DHT11典型温湿度读取过程,编写获取温湿度函数。
40.3.1 程序流程图

图40.3.1.1 DHT11实验程序流程图
40.3.2 程序解析
1.DHT11驱动代码
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。DHT11驱动源码包括两个文件:dht11.c和dht11.h。
首先我们先看一下dht11.h头文件里面的内容,其定义如下:

/* DHT11 引脚 定义 */
#define DHT11_DQ_GPIO_PORT                  GPIOC
#define DHT11_DQ_GPIO_PIN                   GPIO_PIN_13
#define DHT11_DQ_GPIO_CLK_ENABLE()
do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)   /* PC口时钟使能 */
/* IO操作函数 */
#define DHT11_DQ_OUT(x)     do{ x ? \HAL_GPIO_WritePin(DHT11_DQ_GPIO_PORT, DHT11_DQ_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(DHT11_DQ_GPIO_PORT, DHT11_DQ_GPIO_PIN, GPIO_PIN_RESET); \}while(0)           /* 数据端口输出 */
/* 数据端口输入 */
#define DHT11_DQ_IN    HAL_GPIO_ReadPin(DHT11_DQ_GPIO_PORT, DHT11_DQ_GPIO_PIN)
对DHT11的相关引脚以及IO操作进行宏定义,方便程序中调用。
下面我们直接介绍dht11.c的程序,首先先介绍一下DHT11传感器的初始化函数,其定义如下:
/*** @brief        初始化DHT11的IO口 DQ 同时检测DHT11的存在* @param       无* @retval         0, 正常*                  1, 不存在/不正常*/
uint8_t dht11_init(void)
{GPIO_InitTypeDef gpio_init_struct;DHT11_DQ_GPIO_CLK_ENABLE();     /* 开启DQ引脚时钟 */gpio_init_struct.Pin = DHT11_DQ_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_OUTPUT_OD;            /* 开漏输出 */gpio_init_struct.Pull = GPIO_PULLUP;                         /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;    /* 高速 */HAL_GPIO_Init(DHT11_DQ_GPIO_PORT, &gpio_init_struct);   /* 初始化DQ引脚 */
/* DHT11_DQ引脚模式设置,开漏输出,上拉, 这样就不用再设置IO方向了, 开漏输出的时候(=1),
也可以读取外部信号的高低电平 */dht11_reset();return dht11_check();
}

在DHT11的初始化函数中,主要对用到的GPIO口进行初始化,同时在函数最后调用复位函数和自检函数,这两个函数在后面会解释到。
下面介绍的是复位DHT11函数和等待DHT11的回应函数,它们的定义如下:

/*** @brief     复位DHT11* @param        data: 要写入的数据* @retval      无*/
static void dht11_reset(void)
{DHT11_DQ_OUT(0);     /* 拉低DQ */delay_ms(20);           /* 拉低至少18ms */DHT11_DQ_OUT(1);      /* DQ=1 */delay_us(30);        /* 主机拉高10~35us */
}/*** @brief       等待DHT11的回应* @param         无* @retval     0, DHT11正常*                 1, DHT11异常/不存在*/
uint8_t dht11_check(void)
{uint8_t retry = 0;uint8_t rval = 0;while (DHT11_DQ_IN && retry < 100)     /* DHT11会拉低83us */{retry++;delay_us(1);}if (retry >= 100){rval = 1;}else{retry = 0;while (!DHT11_DQ_IN && retry < 100)   /* DHT11拉低后会再次拉高87us */{retry++;delay_us(1);}if (retry >= 100) rval = 1;
}return rval;
}

以上两个函数分别代表着前面所说的复位脉冲与应答信号,大家可以对比前面的时序图进行理解。那么在上一章DS18B20的实验中,也对复位脉冲以及应答信号进行了详细的解释,大家也可以对比理解。
DHT11与DS18B20有所不同,DHT11是不需要写函数,只需要读函数即可,下面介绍从DHT11读取一个位函数和从DHT11读取一个字节函数,它们的定义如下:

/*** @brief         从DHT11读取一个位* @param        无* @retval     读取到的位值: 0 / 1*/
uint8_t dht11_read_bit(void)
{uint8_t retry = 0;while (DHT11_DQ_IN && retry < 100)   /* 等待变为低电平 */{retry++;delay_us(1);
}retry = 0;while (!DHT11_DQ_IN && retry < 100)  /* 等待变高电平 */{retry++;delay_us(1);
}delay_us(40);      /* 等待40us */if (DHT11_DQ_IN)    /* 根据引脚状态返回 bit */{return 1;}else {return 0;}
}/*** @brief       从DHT11读取一个字节* @param       无* @retval     读到的数据*/
static uint8_t dht11_read_byte(void)
{uint8_t i, data = 0;for (i = 0; i < 8; i++)             /* 循环读取8位数据 */{data <<= 1;                       /* 高位数据先输出, 先左移一位 */data |= dht11_read_bit();      /* 读取1bit数据 */
}return data;
}

在这里dht11_read_bit函数从DHT11处读取1位数据,大家可以对照前面的读时序图进行分析,读数字0和1的不同,在于高电平的持续时间,所以这个作为判断的依据。dht11_read_byte函数就是调用一字节读取函数进行实现。
下面介绍读取温湿度函数,其定义如下:

/*** @brief         从DHT11读取一次数据* @param       temp: 温度值(范围:-20~60°)* @param          humi: 湿度值(范围:5%~95%)* @retval      0, 正常.*             1, 失败*/
uint8_t dht11_read_data(uint8_t *temp, uint8_t *humi)
{uint8_t buf[5];
uint8_t i;dht11_reset();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;
}
读取温湿度函数也是根据时序图进行实现的,在发送复位信号以及应答信号产生后,即可以读取5Byte数据进行处理,校验成功即读取数据有效成功。
2. main.c代码
在main.c里面编写如下代码:
int main(void)
{uint8_t t = 0;uint8_t temperature;uint8_t humidity;sys_cache_enable();                        /* 打开L1-Cache */HAL_Init();                                 /* 初始化HAL库 */sys_stm32_clock_init(240, 2, 2, 4);    /* 设置时钟, 480Mhz */delay_init(480);                          /* 延时初始化 */usart_init(115200);                      /* 串口初始化为115200 */mpu_memory_protection();                  /* 保护相关存储区域 */led_init();                                   /* 初始化LED */lcd_init();                                     /* 初始化LCD */lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);lcd_show_string(30, 70, 200, 16, 16, "DHT11 TEST", RED);lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);while (dht11_init())                /* DHT11初始化 */{lcd_show_string(30, 130, 200, 16, 16, "DHT11 Error", RED);delay_ms(200);lcd_fill(30, 130, 239, 130 + 16, WHITE);delay_ms(200);}lcd_show_string(30, 130, 200, 16, 16, "DHT11 OK", RED);lcd_show_string(30, 150, 200, 16, 16, "Temp:  C", BLUE);
lcd_show_string(30, 170, 200, 16, 16, "Humi:  %", BLUE);while (1){if (t % 10 == 0)   /* 每100ms读取一次 */{dht11_read_data(&temperature, &humidity);                 /* 读取温湿度值 */lcd_show_num(30 + 40, 150, temperature, 2, 16, BLUE);/* 显示温度 */lcd_show_num(30 + 40, 170, humidity, 2, 16, BLUE);   /* 显示湿度 */}delay_ms(10);t++;if (t == 20){t = 0;LED0_TOGGLE();  /* LED0闪烁 */}}
}

主函数代码比较简单,一系列硬件初始化后,如果DHT11初始化成功,那么在循环中调用dht11_get_temperature函数获取温湿度值,每隔100ms读取数据并显示在LCD上。
40.4 下载验证
假定DHT11传感器已经接上去正确的位置,将程序下载到开发板后,可以看到LED0不停的闪烁,提示程序已经在运行了。LCD显示当前的温度值的内容如图40.4.1所示:

图40.4.1 程序运行效果图
至此,本章实验结束。大家可以将本章通过DHT11读取到的温度值,和前一章的通过DS18B20读取到的温度值对比一下,看看哪个更准确?

【正点原子STM32连载】第四十章 DHT11数字温湿度传感器 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1相关推荐

  1. 【正点原子STM32连载】第四章 STM32初体验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

  2. 【正点原子STM32连载】第四十五章 SD卡实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

  3. 【正点原子STM32连载】第四十七章 汉字显示实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

  4. 【正点原子STM32连载】第十四章 蜂鸣器实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

  5. 【正点原子STM32连载】第六章 新建寄存器版本MDK工程 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

  6. 【正点原子STM32连载】第三十九章 DS18B20数字温度传感器实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

  7. 【正点原子STM32连载】第五十七章 USB读卡器(Slave)实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

  8. 【正点原子STM32连载】 第三十章 DMA实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

  9. 【正点原子STM32连载】第四十六章 FATFS实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

最新文章

  1. 基于微服务的电商系统架构
  2. 全面容器化之后,来电科技如何实现微服务治理?
  3. Qt Remote Object(QtRO)动态Replica实现进程间通信
  4. jbpm 和 drools_Drools和jBPM KIE A​​pps平台
  5. redis java序列化_java处理redis的几种序列化策略
  6. 前端学习(2358):v-bind和v-for
  7. JS高级——模块化学习笔记
  8. erlang开发环境配置
  9. mysql表空间界限_MySQL5.7 import表结构报错超出表空间界限
  10. 【ASP.NET Web API教程】5.2 发送HTML表单数据:URL编码的表单数据
  11. 二分的思想在算法中体现
  12. 洛阳计算机学校排名2015年,洛阳最好的中专学校有哪些 十大中专学校排名
  13. 远程连接Ubuntu服务器
  14. 关于python 输出中文
  15. vue里面下载配置使用zepto vue中怎样使用zepto
  16. hp服务器 raid卡驱动安装系统,hp 服务器 linux raid驱动
  17. IEEE会议文章接收后提交流程
  18. 标准差和标准误的区别
  19. 微信表情符号已写入判决书
  20. C语言:简易商品库存管理系统(简单易懂,不用指针的入门级示例,数据结构大作业)

热门文章

  1. leetcode刷题总结(主要是各个博主的总结链接)
  2. echarts K线图candlestick
  3. java毕设项目开发 基于SSM库存物资管理系统 仓库物资管理系统 物资库存管理系统Java
  4. 数独(Sudoku)求解程序
  5. Vitis-Ai 3.0 板卡镜像制作、模型量化编译教程
  6. 第3章 垃圾收集器与内存分配策略6
  7. 911S5正式谢幕后 如何找到一个好用的替代品
  8. 中公教育python培训讲师面试题_中公教育教师招考讲师面试经验
  9. PHP实现微信小程序登录
  10. 打怪升级之小白的大数据之旅(四十六)<HDFS各模块的原理>