STM32的DH11温湿度模块和LED灯的综合实训

直接附上代码,里面有详细的解释

c 复制代码
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "esp_rom_sys.h"
#include <stdlib.h>
#include <time.h>

// DHT11温湿度传感器读取相关定义
#define DHT11_OK 0
#define DHT11_ERROR -1

// 温湿度数据结构
typedef struct {
    int temperature;
    int humidity;
} dht11_data_t;

// 硬件引脚定义
#define DHT_PIN GPIO_NUM_4      // DHT11数据引脚
#define LED1_PIN GPIO_NUM_1     // LED1引脚
#define LED2_PIN GPIO_NUM_2     // LED2引脚
#define LED3_PIN GPIO_NUM_6     // LED3引脚(顺序:1/2/6/5)
#define LED4_PIN GPIO_NUM_5     // LED4引脚(顺序:1/2/6/5)

static const char *TAG = "LEDControlSystem";

// LED控制模式枚举
typedef enum {
    LED_MODE_FLOW = 0,        // 流水灯模式(25度以下)
    LED_MODE_BLINK,           // 同时闪烁模式(25-27度)
    LED_MODE_RANDOM,          // 随机亮着模式(27-29度)
    LED_MODE_FAST_BLINK       // 快速闪烁模式(29度以上)
} led_control_mode_t;

// 温度阈值定义
#define TEMP_THRESHOLD_25 26  // 25度阈值
#define TEMP_THRESHOLD_27 28  // 27度阈值  
#define TEMP_THRESHOLD_29 30  // 29度阈值

// 当前控制模式
static led_control_mode_t current_mode = LED_MODE_FLOW;

// LED初始化函数
static void init_leds(void) {
    gpio_config_t io_conf = {};
    // 禁用中断
    io_conf.intr_type = GPIO_INTR_DISABLE;
    // 设置为输出模式
    io_conf.mode = GPIO_MODE_OUTPUT;
    // 设置引脚掩码(包含4个LED)
    io_conf.pin_bit_mask = (1ULL << LED1_PIN) | (1ULL << LED2_PIN) | 
                          (1ULL << LED3_PIN) | (1ULL << LED4_PIN);
    // 禁用下拉
    io_conf.pull_down_en = 0;
    // 禁用上拉
    io_conf.pull_up_en = 0;
    // 配置GPIO
    gpio_config(&io_conf);
    
    // 初始状态:所有LED熄灭
    gpio_set_level(LED1_PIN, 0);
    gpio_set_level(LED2_PIN, 0);
    gpio_set_level(LED3_PIN, 0);
    gpio_set_level(LED4_PIN, 0);
    
    ESP_LOGI(TAG, "4个LED初始化完成,引脚:GPIO%d, GPIO%d, GPIO%d, GPIO%d", 
             LED1_PIN, LED2_PIN, LED3_PIN, LED4_PIN);
}

// LED控制函数 - 实现三种模式
static void control_leds(led_control_mode_t mode) {
    static int flow_index = 0;  // 流水灯索引
    static int blink_state = 0; // 闪烁状态
    
    switch (mode) {
        case LED_MODE_FLOW:
            // 流水灯模式:LED依次点亮
            gpio_set_level(LED1_PIN, (flow_index == 0) ? 1 : 0);
            gpio_set_level(LED2_PIN, (flow_index == 1) ? 1 : 0);
            gpio_set_level(LED3_PIN, (flow_index == 2) ? 1 : 0);
            gpio_set_level(LED4_PIN, (flow_index == 3) ? 1 : 0);
            
            flow_index = (flow_index + 1) % 4;  // 循环索引
            vTaskDelay(pdMS_TO_TICKS(300));     // 300ms延时
            break;
            
        case LED_MODE_BLINK:
            // 同时闪烁模式:所有LED同时闪烁
            gpio_set_level(LED1_PIN, blink_state);
            gpio_set_level(LED2_PIN, blink_state);
            gpio_set_level(LED3_PIN, blink_state);
            gpio_set_level(LED4_PIN, blink_state);
            
            blink_state = !blink_state;         // 切换状态
            vTaskDelay(pdMS_TO_TICKS(500));     // 500ms延时
            break;
            
        case LED_MODE_RANDOM:
            // 随机亮着模式:随机点亮LED
            gpio_set_level(LED1_PIN, rand() % 2);
            gpio_set_level(LED2_PIN, rand() % 2);
            gpio_set_level(LED3_PIN, rand() % 2);
            gpio_set_level(LED4_PIN, rand() % 2);
            
            vTaskDelay(pdMS_TO_TICKS(400));     // 400ms延时
            break;
            
        case LED_MODE_FAST_BLINK:
            // 快速闪烁模式:所有LED快速闪烁
            gpio_set_level(LED1_PIN, blink_state);
            gpio_set_level(LED2_PIN, blink_state);
            gpio_set_level(LED3_PIN, blink_state);
            gpio_set_level(LED4_PIN, blink_state);
            
            blink_state = !blink_state;         // 切换状态
            vTaskDelay(pdMS_TO_TICKS(100));     // 100ms延时(快速闪烁)
            break;
    }
}

// DHT11温湿度传感器读取函数
static int read_dht11(dht11_data_t *data) {
    uint8_t bits[5] = {0};
    uint8_t cnt = 7;
    uint8_t idx = 0;
    
    // 主机发送开始信号
    gpio_set_direction(DHT_PIN, GPIO_MODE_OUTPUT);
    gpio_set_level(DHT_PIN, 0);
    esp_rom_delay_us(18000);  // 至少18ms低电平
    gpio_set_level(DHT_PIN, 1);
    esp_rom_delay_us(40);     // 20-40us高电平
    
    // 切换到输入模式等待DHT11响应
    gpio_set_direction(DHT_PIN, GPIO_MODE_INPUT);
    
    // 等待DHT11响应信号
    while (gpio_get_level(DHT_PIN) == 1) {
        esp_rom_delay_us(1);
    }
    while (gpio_get_level(DHT_PIN) == 0) {
        esp_rom_delay_us(1);
    }
    while (gpio_get_level(DHT_PIN) == 1) {
        esp_rom_delay_us(1);
    }
    
    // 读取40位数据
    for (int i = 0; i < 40; i++) {
        while (gpio_get_level(DHT_PIN) == 0) {
            esp_rom_delay_us(1);
        }
        
        uint32_t time = 0;
        while (gpio_get_level(DHT_PIN) == 1) {
            esp_rom_delay_us(1);
            time++;
            if (time > 100) break;
        }
        
        if (time > 28) {  // 高电平时间大于28us表示数据位1
            bits[idx] |= (1 << cnt);
        }
        
        if (cnt == 0) {
            cnt = 7;
            idx++;
        } else {
            cnt--;
        }
    }
    
    // 校验数据
    uint8_t sum = bits[0] + bits[1] + bits[2] + bits[3];
    if (sum != bits[4]) {
        return DHT11_ERROR;
    }
    
    data->humidity = bits[0];
    data->temperature = bits[2];
    
    return DHT11_OK;
}

// 根据温度切换LED模式
static void switch_mode_by_temperature(int temperature) {
    led_control_mode_t new_mode;
    
    // 根据温度阈值选择模式
    if (temperature < TEMP_THRESHOLD_25) {
        new_mode = LED_MODE_FLOW;        // 25度以下:流水灯
    } else if (temperature < TEMP_THRESHOLD_27) {
        new_mode = LED_MODE_BLINK;       // 25-27度:同时闪烁
    } else if (temperature < TEMP_THRESHOLD_29) {
        new_mode = LED_MODE_RANDOM;      // 27-29度:随机亮
    } else {
        new_mode = LED_MODE_FAST_BLINK;  // 29度以上:快速闪烁
    }
    
    // 如果模式发生变化,则更新并显示信息
    if (new_mode != current_mode) {
        current_mode = new_mode;
        
        // 显示当前模式信息
        switch (current_mode) {
            case LED_MODE_FLOW:
                ESP_LOGI(TAG, "🌡️ 温度 %d°C → 🎯 流水灯模式", temperature);
                break;
            case LED_MODE_BLINK:
                ESP_LOGI(TAG, "🌡️ 温度 %d°C → ✨ 同时闪烁模式", temperature);
                break;
            case LED_MODE_RANDOM:
                ESP_LOGI(TAG, "🌡️ 温度 %d°C → 🎲 随机亮着模式", temperature);
                break;
            case LED_MODE_FAST_BLINK:
                ESP_LOGI(TAG, "🌡️ 温度 %d°C → ⚡ 快速闪烁模式", temperature);
                break;
        }
    }
}

void app_main(void) {
    ESP_LOGI(TAG, "四路LED温度控制系统启动");
    ESP_LOGI(TAG, "LED引脚:GPIO%d, GPIO%d, GPIO%d, GPIO%d", 
             LED1_PIN, LED2_PIN, LED3_PIN, LED4_PIN);
    ESP_LOGI(TAG, "DHT11引脚:GPIO%d", DHT_PIN);
    ESP_LOGI(TAG, "温度控制模式:");
    ESP_LOGI(TAG, "  <25°C: 🎯 流水灯模式");
    ESP_LOGI(TAG, "25-27°C: ✨ 同时闪烁模式");
    ESP_LOGI(TAG, "27-29°C: 🎲 随机亮着模式");
    ESP_LOGI(TAG, " >29°C: ⚡ 快速闪烁模式");
    
    // 初始化随机数种子
    srand((unsigned int)esp_timer_get_time());
    
    // 初始化LED
    init_leds();
    
    // 温湿度读取和显示控制变量
    static int temp_humid_counter = 0;
    static int last_temperature = -1;  // 上次温度值,初始为-1表示未读取
    static int last_humidity = -1;     // 上次湿度值
    
    while (1) {
        // 每半秒(5次循环)读取一次温湿度
        if (temp_humid_counter >= 5) {  // 5次循环约0.5秒
            dht11_data_t data;
            if (read_dht11(&data) == DHT11_OK) {
                // 只有当温度或湿度发生变化时才更新显示
                if (data.temperature != last_temperature || data.humidity != last_humidity) {
                    ESP_LOGI(TAG, "🌡️ 温度: %d°C, 💧 湿度: %d%%", 
                             data.temperature, data.humidity);
                    
                    // 更新上次值
                    last_temperature = data.temperature;
                    last_humidity = data.humidity;
                }
                
                // 根据温度切换LED模式
                switch_mode_by_temperature(data.temperature);
            } else {
                ESP_LOGW(TAG, "❌ DHT11读取失败");
            }
            temp_humid_counter = 0;
        }
        temp_humid_counter++;
        
        // 控制LED显示当前模式
        control_leds(current_mode);
    }
}
相关推荐
Python小老六16 小时前
STM32 Flash:扇区、页、块
stm32·单片机·嵌入式硬件
普中科技18 小时前
【普中DSP28335开发攻略】-- 第 16 章 定时器中断实验
单片机·嵌入式硬件·定时器·dsp28335·普中科技
雅欣鱼子酱18 小时前
电流检测的电路设计与选型——分流电阻法
stm32·单片机·嵌入式硬件·芯片·电子元器件·电流检测芯片
DIY机器人工房20 小时前
嵌入式面试题:看你学习了自动控制原理这门课,讲一下欠驱动系统?
stm32·单片机·学习·嵌入式·自动控制原理
从零点21 小时前
STM32通过SPI进行W25Q128(外部flash)读写操作
stm32·单片机·嵌入式硬件
深圳元器猫1 天前
航顺HK32L08X:国产超低功耗MCU新标杆
单片机·mcu
the sun341 天前
单片机简单介绍
单片机·嵌入式硬件·51单片机
d111111111d1 天前
STM32外设学习-I2C通信(代码)--MPU6050--笔记
笔记·stm32·单片机·嵌入式硬件·学习
贝塔实验室1 天前
Altium Designer 6.0 初学教程-在Altium Designer 中对PCB 进行板层设置及内电层进行分割
嵌入式硬件·fpga开发·编辑器·硬件工程·信息与通信·信号处理·pcb工艺
Jerry丶Li1 天前
三十二、STM32的USART(串口收发文本数据包)
stm32·单片机·嵌入式硬件