#define KEY1_PIN 4   // 红色:上升沿触发
#define KEY2_PIN 11  // 绿色:下降沿触发
#define KEY3_PIN 2   // 蓝色:跳变沿触发
#define KEY4_PIN 35  // 黄色:低电平触发
#define KEY5_PIN 19  // 黑色:退出

#define RISING_EVENT  1
#define FALLING_EVENT 2
#define CHANGE_EVENT  4
#define LOW_EVENT     8
#define CLEAR_EVENT   16
#define ALL_EVENT     31  //RISING_EVENT | FALLING_EVENT | CHANGE_EVENT | LOW_EVENT | CLEAR_EVENT

TaskHandle_t xKeyHandler = NULL;  // 按键驱动任务句柄

// 上升沿触发中断服务函数
void IRAM_ATTR ISR_RISING(){
  xTaskNotifyFromISR(xKeyHandler, RISING_EVENT, eSetBits, NULL);
}

// 下降沿触发中断服务函数
void IRAM_ATTR ISR_FALLING(){
  xTaskNotifyFromISR(xKeyHandler, FALLING_EVENT, eSetBits, NULL);
}

// 跳变沿触发中断服务函数
void IRAM_ATTR ISR_CHANGE(){
  xTaskNotifyFromISR(xKeyHandler, CHANGE_EVENT, eSetBits, NULL);
}

// 低电平触发中断服务函数
void IRAM_ATTR ISR_LOW(){
  xTaskNotifyFromISR(xKeyHandler, LOW_EVENT, eSetBits, NULL);
}

// 下降沿触发,删除所有中断
void IRAM_ATTR ISR_CLEAN(){
  xTaskNotifyFromISR(xKeyHandler, CLEAR_EVENT, eSetBits, NULL);
}

// 键盘驱动线程
void key_driver_entry(void *params){
  pinMode(KEY1_PIN, INPUT_PULLDOWN);    // 上升沿触发,所以必须下拉
  pinMode(KEY2_PIN, INPUT_PULLUP);      // 下降沿触发,所以必须上拉
  pinMode(KEY3_PIN, INPUT);             // 跳变沿触发,用哪种拉无所谓
  pinMode(KEY4_PIN, INPUT_PULLUP);      // 低电平触发,所以必须上拉
  pinMode(KEY5_PIN, INPUT_PULLUP);      // 下降沿触发,电阻上拉
  // 安装中断
  attachInterrupt(KEY1_PIN, ISR_RISING, RISING);
  attachInterrupt(KEY2_PIN, ISR_FALLING, FALLING);
  attachInterrupt(KEY3_PIN, ISR_CHANGE, CHANGE);
  attachInterrupt(KEY4_PIN, ISR_LOW, LOW);
  attachInterrupt(KEY5_PIN, ISR_CLEAN, FALLING);

  // 初始化按键情况
  printf("红色按键情况:%d\n", digitalRead(KEY1_PIN));
  printf("绿色按键情况:%d\n", digitalRead(KEY2_PIN));
  printf("蓝色按键情况:%d\n", digitalRead(KEY3_PIN));
  printf("黄色按键情况:%d\n", digitalRead(KEY4_PIN));

  uint32_t events = 0;
  while(1){
    // 接收任务通知前,先清空所有位,接收后也清空所有位
    if (xTaskNotifyWait(UINT32_MAX, UINT32_MAX, &events, portMAX_DELAY) == pdTRUE){
      if(events>0){
        // 当收到任务通知后,等待10ms,如果该按键在查看电平状态,则表示真的触发了,真机中可以调整这个值达到去抖目的
        delay(50);
        if((events & RISING_EVENT) > 0){
          // 上升沿按键可能被触发
          if(digitalRead(KEY1_PIN)==HIGH){
            printf("您按下了红色按键!\n");
          }
        }else if((events & FALLING_EVENT) > 0){
          if(digitalRead(KEY2_PIN)==LOW){
            printf("您按下了绿色按键!\n");
          }
        }else if((events & CHANGE_EVENT) > 0){
            printf("您按下了蓝色按键!\n");
        }else if((events & LOW_EVENT) > 0){
          if(digitalRead(KEY4_PIN)==LOW){
            printf("黄色按键被按下!\n");
          }
        }else if((events & CLEAR_EVENT) > 0){
          if(digitalRead(KEY5_PIN)==LOW){
            printf("终结所有按键中断!\n");
            //卸载中断
            detachInterrupt(KEY1_PIN);
            detachInterrupt(KEY2_PIN);
            detachInterrupt(KEY3_PIN);
            detachInterrupt(KEY4_PIN);
            detachInterrupt(KEY5_PIN);
          }
        }
      }
      xTaskNotifyStateClear(NULL);    // 清空所有状态
    }
    events = 0;
    delay(1);
  }
  vTaskDelete(NULL);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Hello, ESP32-S3!");

  xTaskCreate(key_driver_entry, "KD", 10240, NULL, 1, &xKeyHandler);
  vTaskDelete(NULL);
}
void loop() {
}
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
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
btn3:1.l
btn3:2.l
btn3:1.r
btn3:2.r
btn4:1.l
btn4:2.l
btn4:1.r
btn4:2.r
btn5:1.l
btn5:2.l
btn5:1.r
btn5:2.r