写点什么

STM32+DHT11 监测环境的温湿度

作者:DS小龙哥
  • 2023-06-13
    重庆
  • 本文字数:2616 字

    阅读完需:约 9 分钟

【1】DHT11 传感器

DHT11 是一种数字温湿度传感器,能够通过数字信号输出当前环境的温度和湿度值。DHT11 可以通过一条数据信号线连接到微控制器或其他外设,从而实现温湿度的实时测量和数据读取。


DHT11 采用单总线通信协议,只需要连接一个数字信号线和两个电源线,即可实现传感器的数据读取。传感器本身具有一定的温度和湿度校准能力,因此输出的数据比较可靠。


DHT11 传感器的测量范围为 0~50°C 的温度和 20%~90%的相对湿度,测量精度为±2°C 和±5%RH。


【2】通信协议

DHT11 采用单总线通信协议,使用一条数据信号线来传输数据,其中包括起始信号、数据位和校验位。通信协议如下:


  1. 主机发送一个开始信号给 DHT11,即将数据信号线拉低至少 18ms 以上。

  2. 主机发出启动信号之后,拉低数据线至少 80us,在这个过程中,DHT11 将会检测到主机发送的启动信号,并做出回应。

  3. DHT11 响应主机发出的启动信号后,会拉高数据信号线至少 80us,表示传输数据前的“准备工作”已经完成。

  4. DHT11 开始向主机发送数据,每个数据包包含 40 个位,高位先传输。在数据传输的过程中,DHT11 会将数据信号线从低电平转换为高电平,表示 1 的开始,持续时间 26~28us,然后将数据线拉低,表示 0 的开始,持续时间~70us。

  5. 在发送完 40 位数据后,DHT11 会发送一个校验位。校验位的计算方法是将前四个字节数据相加,求出一个 8 位校验码,将此校验码与第五个字节进行比较,如果相等,则数据传输成功,否则需要重传数据。

  6. 主机接收到数据后,需要将数据信号线拉高,以结束传输。

【3】读取 DHT11 温湿度数据

以下是一个读取 DHT11 传感器的温度和湿度示例代码:


Copy Code#include "stm32f10x.h"#include "dht11.h"
#define DHT11_GPIO_PORT GPIOB#define DHT11_GPIO_PIN GPIO_Pin_12
void delay_us(uint32_t us){ us *= (SystemCoreClock / 1000000) / 5; while (--us);}
void dht11_start(void){ GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = DHT11_GPIO_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
/* 发送开始信号 */ GPIO_ResetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN); delay_us(18000);
GPIO_SetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN); delay_us(40);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);}
uint16_t dht11_read_bit(void){ uint16_t retry = 0;
while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == RESET) { retry++; if (retry > 1000) { return 0; } delay_us(1); }
retry = 0;
while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == SET) { retry++; if (retry > 1000) { return 0; } delay_us(1); }
if (retry < 30) { return 0; } else { return 1; }}
uint8_t dht11_read_byte(void){ uint8_t i; uint8_t data = 0;
for (i = 0; i < 8; i++) { data <<= 1; if (dht11_read_bit()) { data |= 0x01; } }
return data;}
uint8_t dht11_read_data(dht11_data_t *data){ uint8_t i; uint8_t buf[5]; uint8_t checksum = 0;
dht11_start();
if (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == RESET) { /* 等待DHT11响应 */ while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == RESET);
/* 等待DHT11发射数据 */ while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == SET);
/* 接收数据 */ for (i = 0; i < 5; i++) { buf[i] = dht11_read_byte(); }
/* 校验和 */ checksum = buf[0] + buf[1] + buf[2] + buf[3];
if (checksum == buf[4]) { data->humidity = buf[0]; data->temperature = buf[2]; return 1; } }
return 0;}
int main(void){ dht11_data_t data;
GPIO_InitTypeDef GPIO_InitStruct;
/* 使能GPIOB时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* 配置DHT11引脚为输入模式 */ GPIO_InitStruct.GPIO_Pin = DHT11_GPIO_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
while (1) { if (dht11_read_data(&data)) { printf("Temperature: %d°C Humidity: %d%%\n", data.temperature, data.humidity); } else { printf("Error reading data from DHT11.\n"); } delay_us(2000000); }}
复制代码


在这个示例代码中,首先定义了一个dht11_data_t结构体,用于保存读取的温度和湿度数据。然后,编写了一些函数来执行 DHT11 读取操作。


delay_us()函数是一个简单的延迟函数,用于等待一定量的时间。需要精确地计算一个微秒的延迟,并在循环中使用该延迟来等待一段时间。


dht11_start()函数用于发送 DHT11 的开始信号。将 DHT11 引脚配置为输出模式,并发送 18 毫秒的低电平信号,然后再发送 40 微秒的高电平信号。


dht11_read_bit()函数用于读取 DHT11 传输的数据位。等待 DHT11 输出信号的变化,并根据变化的时间来判断数据位的值。如果一个数据位的响应时间小于 30 微秒,则被判定为 0,否则为 1。


dht11_read_byte()函数用于读取一个字节的数据(8 个数据位)。通过调用dht11_read_bit()函数 8 次来读取每个数据位,并将结果组合成一个字节。


dht11_read_data()函数用于读取整个 DHT11 数据包,包括温度、湿度和校验和。首先调用dht11_start()函数发送开始信号,然后等待 DHT11 发送数据。使用dht11_read_byte()函数读取 5 个字节的数据,并验证校验和以确保数据完整和正确。


最后,在main()函数中,初始化 GPIO 口和 DHT11 传感器,并执行一个循环来读取数据。如果读取成功,则将温度和湿度打印到串口终端上,否则输出错误信息。

发布于: 刚刚阅读数: 4
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022-01-06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
STM32+DHT11监测环境的温湿度_6月优质更文活动_DS小龙哥_InfoQ写作社区