【mqtt参数上云和小程序开发】【第4期】dht11调试成功,吹风机检验

pa15引脚多加关注,需要接触jtag在这里插入图片描述

在这里插入图片描述
GPIO_PinRemapConfig

DHT11传感器特性

温湿度测量范围

  • 湿度测量范围:20% ~ 90% RH(相对湿度)
  • 温度测量范围:0℃ ~ 50℃
  • 湿度精度:±5% RH
  • 温度精度:±2℃
  • 分辨率:湿度1% RH,温度1℃
  • 采样周期:≥ 1秒

电气特性

  • 工作电压:3.3V ~ 5.5V
  • 单总线通信
  • 尺寸:15.5mm × 12mm × 5.5mm

DHT11驱动代码(STM32 HAL库版本)

1. 头文件 dht11.h

#ifndef __DHT11_H
#define __DHT11_H

#include "main.h"

// DHT11引脚配置 - 根据实际连接修改
#define DHT11_GPIO_PORT       GPIOA
#define DHT11_GPIO_PIN        GPIO_PIN_15

// 函数声明
void DHT11_Init(void);
uint8_t DHT11_ReadData(uint8_t *temperature, uint8_t *humidity);
uint8_t DHT11_Start(void);
uint8_t DHT11_ReadByte(void);
uint8_t DHT11_ReadBit(void);
void DHT11_Reset(void);

// 模式切换宏
#define DHT11_IO_IN()  do{ \
    GPIO_InitTypeDef GPIO_InitStruct = {0}; \
    GPIO_InitStruct.Pin = DHT11_GPIO_PIN; \
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \
    GPIO_InitStruct.Pull = GPIO_PULLUP; \
    HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct); \
}while(0)

#define DHT11_IO_OUT() do{ \
    GPIO_InitTypeDef GPIO_InitStruct = {0}; \
    GPIO_InitStruct.Pin = DHT11_GPIO_PIN; \
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; \
    GPIO_InitStruct.Pull = GPIO_NOPULL; \
    HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct); \
}while(0)

#define DHT11_DQ_OUT_HIGH()   HAL_GPIO_WritePin(DHT11_GPIO_PORT, DHT11_GPIO_PIN, GPIO_PIN_SET)
#define DHT11_DQ_OUT_LOW()    HAL_GPIO_WritePin(DHT11_GPIO_PORT, DHT11_GPIO_PIN, GPIO_PIN_RESET)
#define DHT11_DQ_IN()         HAL_GPIO_ReadPin(DHT11_GPIO_PORT, DHT11_GPIO_PIN)

#endif

2. 源文件 dht11.c

#include "dht11.h"
#include "main.h"

// 微秒级延时函数(需要根据系统时钟调整)
static void DHT11_Delay_us(uint16_t us)
{
    __HAL_TIM_SET_COUNTER(&htim1, 0);  // 使用TIM1,根据实际使用的定时器修改
    while (__HAL_TIM_GET_COUNTER(&htim1) < us);
}

/**
  * @brief  DHT11初始化
  */
void DHT11_Init(void)
{
    // 初始化GPIO为输出模式
    DHT11_IO_OUT();
    DHT11_DQ_OUT_HIGH();  // 拉高总线
    HAL_Delay(1000);      // 上电稳定延时
}

/**
  * @brief  重置DHT11
  */
void DHT11_Reset(void)
{
    DHT11_IO_OUT();
    DHT11_DQ_OUT_HIGH();
    HAL_Delay(100);
}

/**
  * @brief  启动DHT11
  * @retval 0:成功 1:失败
  */
uint8_t DHT11_Start(void)
{
    uint8_t retry = 0;
    
    // 主机拉低至少18ms
    DHT11_IO_OUT();
    DHT11_DQ_OUT_LOW();
    HAL_Delay(20);        // 拉低20ms
    
    // 主机拉高20-40us
    DHT11_DQ_OUT_HIGH();
    DHT11_Delay_us(30);   // 拉高30us
    
    // 设置为输入模式,等待DHT11响应
    DHT11_IO_IN();
    
    // 等待DHT11拉低总线(80us)
    retry = 100;
    while (DHT11_DQ_IN() && retry) {
        DHT11_Delay_us(1);
        retry--;
    }
    if (retry == 0) return 1;
    
    // 等待DHT11拉低结束(80us)
    retry = 100;
    while (!DHT11_DQ_IN() && retry) {
        DHT11_Delay_us(1);
        retry--;
    }
    if (retry == 0) return 1;
    
    return 0;
}

/**
  * @brief  读取一个位
  * @retval 读取的位值
  */
uint8_t DHT11_ReadBit(void)
{
    uint8_t retry = 0;
    
    // 等待50us低电平
    while (!DHT11_DQ_IN() && retry < 100) {
        DHT11_Delay_us(1);
        retry++;
    }
    
    // 延时40us判断高电平持续时间
    DHT11_Delay_us(40);
    
    if (DHT11_DQ_IN()) {
        // 高电平持续时间>40us,表示'1'
        // 等待高电平结束
        while (DHT11_DQ_IN() && retry < 100) {
            DHT11_Delay_us(1);
            retry++;
        }
        return 1;
    } else {
        // 高电平持续时间<40us,表示'0'
        return 0;
    }
}

/**
  * @brief  读取一个字节
  * @retval 读取的字节
  */
uint8_t DHT11_ReadByte(void)
{
    uint8_t i, data = 0;
    
    for (i = 0; i < 8; i++) {
        data <<= 1;
        data |= DHT11_ReadBit();
    }
    
    return data;
}

/**
  * @brief  读取温湿度数据
  * @param  temperature: 温度值(整数部分)
  * @param  humidity: 湿度值(整数部分)
  * @retval 0:成功 1:失败
  */
uint8_t DHT11_ReadData(uint8_t *temperature, uint8_t *humidity)
{
    uint8_t buf[5];
    uint8_t i;
    
    if (DHT11_Start() == 0) {
        // 读取40位数据
        for (i = 0; i < 5; i++) {
            buf[i] = DHT11_ReadByte();
        }
        
        // 设置为输入模式,释放总线
        DHT11_IO_IN();
        DHT11_DQ_OUT_HIGH();
        
        // 校验数据
        if (buf[4] == (buf[0] + buf[1] + buf[2] + buf[3])) {
            *humidity = buf[0];        // 湿度整数
            *temperature = buf[2];     // 温度整数
            return 0; // 读取成功
        }
    }
    
    // 设置为输入模式,释放总线
    DHT11_IO_IN();
    DHT11_DQ_OUT_HIGH();
    
    return 1; // 读取失败
}

3. 数据格式说明

DHT11输出40位数据:

8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和

注意:DHT11的小数部分通常为0,所以一般只使用整数部分。


使用示例

在主函数中使用

#include "main.h"
#include "dht11.h"

// 定义全局变量
uint8_t temperature = 0;
uint8_t humidity = 0;
uint8_t dht11_status = 0;

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    
    // 初始化DHT11
    DHT11_Init();
    
    while (1)
    {
        // 读取DHT11数据(至少间隔1秒)
        dht11_status = DHT11_ReadData(&temperature, &humidity);
        
        if (dht11_status == 0) {
            // 读取成功
            printf("温度: %d℃, 湿度: %d%%\r\n", temperature, humidity);
            
            // 判断是否超出范围
            if (temperature < 0 || temperature > 50) {
                printf("警告:温度超出测量范围!\r\n");
            }
            if (humidity < 20 || humidity > 90) {
                printf("警告:湿度超出测量范围!\r\n");
            }
        } else {
            // 读取失败
            printf("DHT11读取失败!\r\n");
        }
        
        HAL_Delay(2000); // 2秒读取一次
    }
}

通过串口输出结果

// 在main.c中添加串口输出
void Print_Sensor_Data(void)
{
    uint8_t temp, humi;
    char buffer[64];
    
    if (DHT11_ReadData(&temp, &humi) == 0) {
        sprintf(buffer, "温度: %d℃, 湿度: %d%%\r\n", temp, humi);
        HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), 1000);
        
        // 舒适度判断
        if (temp >= 18 && temp <= 26 && humi >= 40 && humi <= 60) {
            sprintf(buffer, "环境舒适\r\n");
            HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), 1000);
        }
    } else {
        sprintf(buffer, "传感器读取错误\r\n");
        HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), 1000);
    }
}

DHT11通信时序

通信过程

  1. 主机发送开始信号:拉低总线至少18ms,然后拉高20-40us
  2. DHT11响应:拉低总线80us,然后拉高80us
  3. 数据传输:每位数据以50us低电平开始,高电平持续时间决定数据位(26-28us为0,70us为1)
  4. 数据格式:40位数据 = 湿度(16bit) + 温度(16bit) + 校验和(8bit)

时序参数

  • 主机拉低:≥ 18ms
  • 主机拉高:20-40us
  • DHT11响应低电平:80us
  • DHT11响应高电平:80us
  • 数据位0:26-28us高电平
  • 数据位1:70us高电平

注意事项

  1. 电源稳定性:确保DHT11供电稳定,建议在VCC和GND之间加100nF电容
  2. 通信间隔:连续读取间隔至少1秒
  3. 线缆长度:信号线不宜过长,建议小于20米
  4. 环境因素:避免在结露环境下使用,会影响测量精度
  5. 校验和:务必进行校验和检查,确保数据正确性

这个驱动代码已经经过优化,包含了完整的错误处理机制,可以直接在STM32项目中使用。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值