第一次提交:完成了网关的单路485数据采集,还有以太网链接和MQTT配置,实现数据上报和命令下发,差一个断网储存

This commit is contained in:
Wang Beihong
2026-02-01 18:31:06 +08:00
commit b284cb4953
35 changed files with 4338 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
idf_component_register(SRCS "STATUS_LED.c"
INCLUDE_DIRS "include"
REQUIRES driver log
)

View File

@@ -0,0 +1,257 @@
#include <stdio.h>
#include "STATUS_LED.h"
static const char *TAG = "status_led";
// LED 引脚定义
#define STATUS_LED_1_PIN (GPIO_NUM_8)
#define STATUS_LED_2_PIN (GPIO_NUM_18)
// LED 控制结构体
typedef struct {
gpio_num_t pin;
led_state_t state;
int blink_period_ms;
bool current_level; // 实际输出电平
TaskHandle_t task_handle;
bool task_running;
} status_led_t;
static status_led_t led1 = {.pin = STATUS_LED_1_PIN, .state = LED_OFF, .task_running = false};
static status_led_t led2 = {.pin = STATUS_LED_2_PIN, .state = LED_OFF, .task_running = false};
/**
* @brief LED控制任务
*
* @param param 指向LED结构体的指针
*/
static void led_control_task(void *param)
{
status_led_t *led = (status_led_t *)param;
while(led->task_running) {
switch(led->state) {
case LED_OFF:
gpio_set_level(led->pin, 1); // 低电平点亮,所以高电平关闭
vTaskDelay(100 / portTICK_PERIOD_MS); // 延迟100ms后再次检查状态
break;
case LED_ON:
gpio_set_level(led->pin, 0); // 低电平点亮
vTaskDelay(100 / portTICK_PERIOD_MS); // 延迟100ms后再次检查状态
break;
case LED_BLINK_SLOW:
led->current_level = !led->current_level;
gpio_set_level(led->pin, !led->current_level); // 反转输出以适应低电平点亮
vTaskDelay(500 / portTICK_PERIOD_MS); // 慢闪周期500ms
break;
case LED_BLINK_FAST:
led->current_level = !led->current_level;
gpio_set_level(led->pin, !led->current_level); // 反转输出以适应低电平点亮
vTaskDelay(100 / portTICK_PERIOD_MS); // 快闪周期100ms
break;
case LED_HEARTBEAT:
// 心跳模式:快速亮两次,然后长灭
gpio_set_level(led->pin, 0); // 点亮
vTaskDelay(100 / portTICK_PERIOD_MS);
gpio_set_level(led->pin, 1); // 熄灭
vTaskDelay(100 / portTICK_PERIOD_MS);
gpio_set_level(led->pin, 0); // 点亮
vTaskDelay(100 / portTICK_PERIOD_MS);
gpio_set_level(led->pin, 1); // 熄灭
vTaskDelay(800 / portTICK_PERIOD_MS); // 间隔800ms
break;
default:
gpio_set_level(led->pin, 1); // 默认关闭
vTaskDelay(100 / portTICK_PERIOD_MS);
break;
}
}
// 任务结束前关闭LED高电平关闭
gpio_set_level(led->pin, 1);
vTaskDelete(NULL);
}
/**
* @brief 初始化GPIO引脚为输出模式
*
* @param led_pin LED使用的GPIO引脚
*/
static void init_gpio_pin(gpio_num_t led_pin)
{
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << led_pin);
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
// 初始状态设为高电平LED熄灭适用于低电平点亮的LED
gpio_set_level(led_pin, 1);
}
/**
* @brief 初始化状态LED
*
* 配置两个LED引脚为输出模式并设置初始状态
*/
void status_led_init(void)
{
init_gpio_pin(STATUS_LED_1_PIN);
init_gpio_pin(STATUS_LED_2_PIN);
// 启动LED控制任务
led1.task_running = true;
xTaskCreate(led_control_task, "led1_control", 2048, &led1, 5, &led1.task_handle);
led2.task_running = true;
xTaskCreate(led_control_task, "led2_control", 2048, &led2, 5, &led2.task_handle);
ESP_LOGI(TAG, "Status LEDs initialized on pins GPIO%d and GPIO%d",
STATUS_LED_1_PIN, STATUS_LED_2_PIN);
}
/**
* @brief 控制指定LED的状态
*
* @param led_num LED编号 (1 或 2)
* @param state LED状态 (0=关闭, 1=开启)
*/
void status_led_set(uint8_t led_num, uint8_t state)
{
status_led_t *led = NULL;
if (led_num == 1) {
led = &led1;
} else if (led_num == 2) {
led = &led2;
} else {
ESP_LOGE(TAG, "Invalid LED number: %d", led_num);
return;
}
if (state == 1) {
led->state = LED_ON;
} else {
led->state = LED_OFF;
}
ESP_LOGD(TAG, "LED %d set to %s", led_num, state ? "ON" : "OFF");
}
/**
* @brief 切换指定LED的状态
*
* @param led_num LED编号 (1 或 2)
*/
void status_led_toggle(uint8_t led_num)
{
status_led_t *led = NULL;
if (led_num == 1) {
led = &led1;
} else if (led_num == 2) {
led = &led2;
} else {
ESP_LOGE(TAG, "Invalid LED number: %d", led_num);
return;
}
if (led->state == LED_ON) {
led->state = LED_OFF;
} else if (led->state == LED_OFF) {
led->state = LED_ON;
}
ESP_LOGD(TAG, "LED %d toggled", led_num);
}
/**
* @brief 设置LED为闪烁模式
*
* @param led_num LED编号 (1 或 2)
* @param mode 闪烁模式 (0=慢闪, 1=快闪, 2=心跳)
*/
void status_led_blink_mode(uint8_t led_num, uint8_t mode)
{
status_led_t *led = NULL;
if (led_num == 1) {
led = &led1;
} else if (led_num == 2) {
led = &led2;
} else {
ESP_LOGE(TAG, "Invalid LED number: %d", led_num);
return;
}
switch(mode) {
case 0: // 慢闪
led->state = LED_BLINK_SLOW;
break;
case 1: // 快闪
led->state = LED_BLINK_FAST;
break;
case 2: // 心跳
led->state = LED_HEARTBEAT;
break;
default:
ESP_LOGE(TAG, "Invalid blink mode: %d", mode);
return;
}
ESP_LOGD(TAG, "LED %d set to blink mode %d", led_num, mode);
}
/**
* @brief 销毁LED控制任务
*
* @param led_num LED编号 (1 或 2)
*/
void status_led_deinit(uint8_t led_num)
{
status_led_t *led = NULL;
if (led_num == 1) {
led = &led1;
} else if (led_num == 2) {
led = &led2;
} else {
ESP_LOGE(TAG, "Invalid LED number: %d", led_num);
return;
}
if (led->task_running) {
led->task_running = false;
if (led->task_handle) {
vTaskDelete(led->task_handle);
led->task_handle = NULL;
}
gpio_set_level(led->pin, 1); // 关闭LED高电平关闭
}
}
/**
* @brief 获取LED当前状态
*
* @param led_num LED编号 (1 或 2)
* @return 当前LED状态
*/
led_state_t status_led_get_state(uint8_t led_num)
{
if (led_num == 1) {
return led1.state;
} else if (led_num == 2) {
return led2.state;
} else {
ESP_LOGE(TAG, "Invalid LED number: %d", led_num);
return LED_OFF;
}
}

View File

@@ -0,0 +1,63 @@
#ifndef STATUS_LED_H
#define STATUS_LED_H
#include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
// LED 状态枚举
typedef enum {
LED_OFF = 0,
LED_ON = 1,
LED_BLINK_SLOW,
LED_BLINK_FAST,
LED_HEARTBEAT
} led_state_t;
/**
* @brief 初始化状态LED
*
* 配置两个LED引脚为输出模式并启动控制任务
*/
void status_led_init(void);
/**
* @brief 控制指定LED的状态
*
* @param led_num LED编号 (1 或 2)
* @param state LED状态 (0=关闭, 1=开启)
*/
void status_led_set(uint8_t led_num, uint8_t state);
/**
* @brief 切换指定LED的状态
*
* @param led_num LED编号 (1 或 2)
*/
void status_led_toggle(uint8_t led_num);
/**
* @brief 设置LED为闪烁模式
*
* @param led_num LED编号 (1 或 2)
* @param mode 闪烁模式 (0=慢闪, 1=快闪, 2=心跳)
*/
void status_led_blink_mode(uint8_t led_num, uint8_t mode);
/**
* @brief 销毁LED控制任务
*
* @param led_num LED编号 (1 或 2)
*/
void status_led_deinit(uint8_t led_num);
/**
* @brief 获取LED当前状态
*
* @param led_num LED编号 (1 或 2)
* @return 当前LED状态
*/
led_state_t status_led_get_state(uint8_t led_num);
#endif // STATUS_LED_H