#define KEY_PIN 20
#define LED_PIN 14
#define WAR_PIN 39
SemaphoreHandle_t led = NULL;         // 二进制信号量
volatile TickType_t keyDeounce = 0;   // 按下按钮的时间
TimerHandle_t timer = NULL;           // 定时器句柄

// 定时器回调函数
void vTimerCallback( TimerHandle_t xTimer ){
  digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}

void led_task(void *param_t){
  pinMode(LED_PIN, OUTPUT);
  pinMode(WAR_PIN, OUTPUT);
  while(1){
    // 这种去抖方式是很Low的,正确的方式要使用定时器。
    if((xSemaphoreTake(led, 1000) == pdTRUE) && ((xTaskGetTickCount() - keyDeounce) < 200)){
      // 创建定时器并启动他
      if(timer == NULL){
        timer = xTimerCreate("Timer_LED",       // 定时器的名字
                              2000,             // 调用间隔时间
                              pdFALSE,          // 只运行一次
                              NULL,             // 定时器标识符,相当于参数
                              vTimerCallback);
      }
      if(xTimerIsTimerActive(timer) == pdFALSE){
        xTimerStart(timer,0);
        // printf("按了开关...\n");
      }else{
        // printf("迷瞪中...\n");
        digitalWrite(WAR_PIN, !digitalRead(WAR_PIN));
      }
      vTaskDelay(500);
    }
  }
}

// 中断服务函数
void IRAM_ATTR ISR() {
  keyDeounce = xTaskGetTickCountFromISR();    // 记录下按下的时间,用于放抖动,正式开发中不要这样写,有Bug
  xSemaphoreGiveFromISR(led, NULL);
}

void setup() {
  Serial.begin(115200);
  led = xSemaphoreCreateBinary();           //创建二进制信号量
  xTaskCreate(led_task, "LED-DSP", 1024, NULL, 1, NULL);
  // 安装中断
  pinMode(KEY_PIN, INPUT_PULLUP);
  attachInterrupt(KEY_PIN, ISR, FALLING);
}

void loop() {
  delay(10);
}
esp:0
esp:1
esp:2
esp:3
esp:4
esp:5
esp:6
esp:7
esp:8
esp:9
esp:10
esp:11
esp:12
esp:13
esp:14
esp:15
esp:16
esp:17
esp:18
esp:19
esp:20
esp:21
esp:35
esp:36
esp:37
esp:38
esp:39
esp:40
esp:41
esp:42
esp:45
esp:46
esp:47
esp:48
esp:3V3.1
esp:3V3.2
esp:RST
esp:5V
esp:GND.1
esp:GND.2
esp:TX
esp:RX
esp:GND.3
esp:GND.4
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
led1:A
led1:C
led2:A
led2:C