258 lines
6.8 KiB
C
258 lines
6.8 KiB
C
#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;
|
||
}
|
||
}
|