直接附上代码,里面有详细的解释
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);
}
}