ESP32点灯,执行快速闪烁LED延时结束后,再执行灯开灯关不起作用,贴上代码希望大家指正

我目的为了让一个LED通过闪烁快慢来显示程序运行的多种状态,专门封装了led_ctl库。由于自带的延时函数会造成程序阻塞,需要led闪烁的代码就放在FreeRTOS任务里面,简单的灯开灯关和电平反转放在任务外面需要就直接调用,但是任务里面一段快速闪烁LED的代码(电平反转间隔20ms)在while循环执行5000ms后,灯开灯关函数就不起作用了,20ms改为50ms就正常,一直找不到原因贴上代码希望大家指正

main.c

#include FreeRTOS.h>
#include 
#include 
#include 

#include "led_ctl.h"

void app_main(void)
{
    // 初始化(低电平触发)
    led_Init();

    // 灯开(正常执行,延时5000ms)
    led_on();
    vTaskDelay(5000 / portTICK_PERIOD_MS);

    // 闪灯(反转电平每20ms一次,延时5000ms)
    led_ctl(LED_GYRO_CALIBRATION);
    vTaskDelay(5000 / portTICK_PERIOD_MS);

    // 灯开(不起作用,延时5000ms)
    led_on();
    vTaskDelay(5000 / portTICK_PERIOD_MS);

    // 灯关(不起作用,延时5000ms)
    led_off();
    vTaskDelay(5000 / portTICK_PERIOD_MS);
}

led_ctl.h

#ifndef _LED_CTL_H_
#define _LED_CTL_H_

#define LED_STATUS_PIN GPIO_NUM_2

typedef enum
{
    LED_IDLE,
    LED_WL_DISCONNECT,
    LED_GYRO_CALIBRATION,
    LED_FLIGHT
} led_status_e;

bool led_isInit(void);
void led_Init(void);
void led_on(void);
void led_off(void);
void led_reverse(void);
void led_ctl(led_status_e ledStatus);

#endif

led_ctl.c

#include FreeRTOS.h>
#include 
#include 

#include "led_ctl.h"

static bool isInit = false;
static uint32_t led_ctl_val;
static uint32_t led_status_level;

static void led_ctl_task(void *args)
{
    while (true)
    {
        switch (led_ctl_val)
        {
        case 0:
            led_off();
            led_ctl_val = -1;
            break;
        case 1:
            led_status_level = 1;
            led_reverse();
            vTaskDelay(200 / portTICK_PERIOD_MS);
            led_reverse();
            vTaskDelay(200 / portTICK_PERIOD_MS);
            break;
        case 2:
            led_status_level = 1;
            led_reverse();
            vTaskDelay(20 / portTICK_PERIOD_MS);
            led_reverse();
            vTaskDelay(20 / portTICK_PERIOD_MS);
            break;
        case 3:
            led_status_level = 1;
            led_reverse();
            vTaskDelay(20 / portTICK_PERIOD_MS);
            led_reverse();
            vTaskDelay(1980 / portTICK_PERIOD_MS);
            break;

        default:
            vTaskDelay(10 / portTICK_PERIOD_MS);
            break;
        }
    }

    vTaskDelete(NULL);
}

bool led_isInit(void)
{
    return isInit;
}

void led_Init(void)
{
    led_ctl_val = -1;
    led_status_level = 1;
    gpio_set_direction(LED_STATUS_PIN, GPIO_MODE_OUTPUT);
    gpio_set_level(LED_STATUS_PIN, led_status_level);
    if (isInit == false)
    {
        xTaskCreatePinnedToCore(led_ctl_task, "led_ctl_task", 2048, NULL, 0, NULL, 0);
        isInit = true;
    }
}

void led_on(void)
{
    led_ctl_val = -1;
    led_status_level = 0;
    gpio_set_level(LED_STATUS_PIN, led_status_level);
}

void led_off(void)
{
    led_ctl_val = -1;
    led_status_level = 1;
    gpio_set_level(LED_STATUS_PIN, led_status_level);
}

void led_reverse(void)
{
    if (led_status_level == 0)
    {
        led_status_level = 1;
    }
    else
    {
        led_status_level = 0;
    }
    gpio_set_level(LED_STATUS_PIN, led_status_level);
}

void led_ctl(led_status_e ledStatus)
{
    switch (ledStatus)
    {
    case LED_IDLE:
        led_ctl_val = 0;
        break;
    case LED_WL_DISCONNECT:
        led_ctl_val = 1;
        break;
    case LED_GYRO_CALIBRATION:
        led_ctl_val = 2;
        break;
    case LED_FLIGHT:
        led_ctl_val = 3;
        break;

    default:
        break;
    }
}

和代码应该没有多少关系,闪烁的原理也是开和关的动作,你在闪烁之后再去使用开灯的方法之前先调用关灯的方法,用来重置状态,然后再去执行开灯方法,试一试吧。