资讯详情

STM32应用开发实践教程:环境温湿度监测的应用开发

.1.1 任务分析 该任务需要设计一个监测环境温度和湿度的应用程序。单总线温湿度传感器(DHT11) 连接到微控制器的电路如图所示 4-1-1 所示。

从图 4-1-1 单总线温湿度传感器(DHT11)某个微控制器 GPIO 引脚相 连接。微控制器每隔一次 2s 将温湿度数据收集到指定格式后,通过 USART 发送到上位机 显示样本为温度:25℃,湿度:67%。 本任务涉及的知识点包括: ? DHT11 温湿度传感器的基本工作原理和性能指标; ? DHT11 传输温湿度传感器的顺序。 4.1.2 知识链接 1.DHT11 概述及其性能指标 DHT11 它是一种集温湿度为一体的数字传感器,内部由一个 电阻测湿元件和负温度系数(NTC)测温元件由测湿测温元件和高性能组成 8 单片机相连。DHT环境温湿度信息的采集可以通过简单的电路连接与微控制器实现。两者之间的通信基于单总线通信协议,微控制器只需要一个 GPIO 引脚与 DHT11 的 DATA 数据通信可以通过连接实现。图4-1-2 是DHT11 实物图,其中V CC 接电源正极,DATA是数据输入输出引脚,N/A 为空脚,GND 接地。表 4-1-1 展示了 DHT11 性能指标。

2.DHT11 的数据格式 DHT11 与微控制器的通信采用单总线数据格式。DHT11 单次传输 5 个字节(40bit)的 数据,高位先出。具体数据构成:8bit 湿度数据 8bit 湿度小数据 8bit 温度整数数 据 8bit 温度小数据 8bit 校验和,包括校验和以前 4 添加并保留低字节数据 8 位。 图 4-1-3 为从 DHT11 一次性读取的数据 样例。 根据表 4-1-1 温湿度分辨率性能指标 可知,DHT11 不能收集温湿度的小部分,所以 微控制器收到的 Byte3(对应湿度的小数部分) 与 Byte1(对应温度的小数部分)无用。 4-1-3 数据处理结果如下: 湿度(Humidity)= Byte4.Byte3 = 45.0 (%RH)。 温度(Temperature)= Byte2.Byte1 = 28.0 (℃)。 校验和(CheckSum)= Byte4 Byte3 Byte2 Byte1 = 0x49 = 73。

3.DHT11 的传输时序 (1)数据通信时序图 微控制器(主机)和 DHT11 数据通信的时间顺序如图所示 4-1-4 所示,包括主机探测 DHT11 是否正确连接和数据传输两个过程。

以下是主机探测 DHT11 数字‘0’和数字‘1’的表示方是否正确连接的顺序 介绍法律。 (2)主机检测 DHT11 时序是否正确连接 从图 4-1-5 可以看出,当数据总线不被占用时, DATA 线默认为高电平,主机检测 DHT11 图4-1-3 从DHT11中一次性读取的数据样例 正确连接的顺序由以下过程组成: ? 主机发送开始信号(至少降低总线) 18 ms); ? 主机拉高总线,延迟等待 10~20μs 释放总线后,准备阅读 DHT11 响应信号; ? DHT11 发送响应信号(低电平) 83μs); ? DHT11 拉高总线 87μs,准备发送数据。

(3)单总线数据格式中数字‘0’和数字‘1’的表示方法 图 4-1-6 和图 4-1-7 单总线数据格式中的数字‘0’和数字‘1’分别显示。

从图 4-1-6 和图 4-1-7 可以看到,DHT11 每发送 1 bit 一个数据 54μs 的低电平 开始,然后提高开始数据发送。微控制器收集的数据是0或1取决于高电平的持续性 间长:高电平持续 23~27μs 表示数据‘0’,持有 续 68~74μs 表示数据‘1’。 当最后 1 bit 数据传输后,DHT11 拉低总线 54μs,表示数据传输完成并释放总线。 后总线从上拉电阻拉高到空闲状态。 DHT11 各种信号的特性见表 4-1-2。

4.1.3 任务实施 1.硬件连接 将 DHT11 温湿度传感器 V CC 引脚连接 3.3 V 电压,GND 引脚接地,DATA 引脚和微控制 器的某 GPIO 引脚(本任务的选择 PG9)相连。 2.编写 DHT11 的控制程序 复制一份任务 2.3 该项目被重命名为task4.1_DHT11”。在“HARDWARE”文件夹 下新建“DHT新建11子文件夹dht11.c”和“dht11.h两工程中加入两个文件, 配置头文件包含路径。dht11.c在文件中输入以下代码:

#include "dht11.h" #include "delay.h" /** * @brief 主机复位 DHT11 * @param None * @retval None */ void DHT11_Reset(void) { DHT11_IO_OUT(); // 设置 DATA 引脚为输出 DHT11_DQ_OUT=0; // 拉低 DATA delay_ms(20); // 拉低至少 18ms DHT11_DQ_OUT=1; // 拉高 DATA delay_us(13); // 主机拉高 10 ~ 20μs } /** * @brief 主机探测 DHT11 连接是否正确 * @param None * @retval 1: 未探测到 DHT11 | 0:DHT11 正常响应 */ uint8_t DHT11_Check(void) { uint8_t retry=0; DHT11_IO_IN(); // 设置 DATA 引脚为输入 while (DHT11_DQ_IN&&retry<100) //DHT11 会拉低 83μs { retry  ; delay_us(1); } if(retry>=100) return 1; else retry=0; while (!DHT11_DQ_IN&&retry<100) //DHT11 拉低后会再次拉高 87μs { retry  ; delay_us(1); } if(retry>=100) return 1; return 0; } /** * @brief 主机从 DHT11 读取 1bit * @param None * @retval 数据 1 or 0 */ uint8_t DHT11_Read_Bit(void) { uint8_t retry=0; while(DHT11_DQ_IN&&retry<100)  // 等待 DATA 变为低电平 { retry  ; delay_us(1); } retry=0; while(!DHT11_DQ_IN&&retry<100) // 等待 DATA 变为高电平 { retry  ; delay_us(1); } delay_us(40);  // 等待 40μs if(DHT11_DQ_IN) return 1; else return 0; } /** * @brief 主机从 DHT11 读取 1 B * @param None * @retval 读取的数据 */ uint8_t DHT11_Read_Byte(void) { uint8_t i,dat; dat = 0; for (i=0; i<8; i  ) { dat<<=1; dat|=DHT11_Read_Bit(); } return dat; } /** * @brief 主机从 DHT11 读取 1 次数据 (40bit) * @param *temp: 存储温度值的变量地址 * @param *humi: 存储湿度值的变量地址 * @retval 1:  读取失败, 0 :读取成功 */ 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  ) // 读取 40bit 数据 { 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; } /** * @brief 初始化 DHT11 的 GPIO 端口,并探测 DHT11 连接是否正确 * @param None * @retval 1: DHT11 不存在, 0 : DHT11 正确连接 */ uint8_t DHT11_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); // 使能 GPIOG 时钟 /* GPIO 引脚配置 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PG9 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // 输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  // 上拉 GPIO_Init(GPIOG, &GPIO_InitStructure); // 配置生效 DHT11_Reset(); return DHT11_Check(); }   在“dht11.h在文件中输入以下代码: #ifndef __DHT11_H #define __DHT11_H #include "sys.h" /* GPIO 方向设置 */ define DHT11_IO_IN() {GPIOG->MODER&=~(3<<(9*2));GPIOG->MODER|=0<<9*2;} // 输入
#define DHT11_IO_OUT() {GPIOG->MODER&=~(3<<(9*2));GPIOG->MODER|=1<<9*2;} // 输出
#define DHT11_DQ_OUT PGout(9)
#define DHT11_DQ_IN PGin(9)
uint8_t DHT11_Init(void);
uint8_t DHT11_Read_Data(uint8_t *temp,uint8_t *humi);
uint8_t DHT11_Read_Byte(void);
uint8_t DHT11_Read_Bit(void);
uint8_t DHT11_Check(void);
void DHT11_Reset(void);
#endif

3.编写 main()函数 在“main.c”文件中输入以下代码:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "dht11.h"
#include <string.h>
char myString[50] = {0};
int main(void)
{
Uint16_t tCount = 0;
uint8_t temperature = 0;
uint8_t humidity = 0;
delay_init(168); // 延时函数初始化
LED_Init(); //LED 端口初始化
USART1_Init(115200); //USART1 初始化
while(DHT11_Init()) //DHT11 初始化
{
printf("DHT11 Init Error!\r\n");
delay_ms(500);
}
printf("DHT11 Init Success!\r\n");
while(1)
{
tCount++;
if(tCount % 2000 == 0)  // 每隔 2s 读取一次
{
DHT11_Read_Data(&temperature,&humidity); // 读取 DHT11 的温湿度值
sprintf(myString," 温度 :%d, 湿度 : 百分之 %d\r\n",temperature,humidity);
printf("%s",myString);
LED1 = ~LED1;
}
delay_ms(1);
}
}

4.观察试验现象 应用程序编译无误后,下载至开发板运行。打开上位机的串口调试助手,设置好波特率等参 数,可观察到图 4-1-8 所示的环境温湿度采集结果。

标签: 接地电阻cc2520

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台