#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h" // 引用此程式庫
#include "driver/gpio.h"
#include "esp_log.h"
// 將編譯階段的日誌等級上限設為5
#define CONFIG_LOG_MAXIMUM_LEVEL 5
#define LED_PIN GPIO_NUM_13
#define BUTTON_PIN GPIO_NUM_35
#define DEBOUNCE_TIME 70 // 消除彈跳時間
static const char *TAG = "SWITCH_LED";
static SemaphoreHandle_t xSemaphore;
// 中斷處理函式:只負責送出訊號
static void IRAM_ATTR isr_handler(void* arg) {
xSemaphoreGiveFromISR(xSemaphore, NULL);
}
void led_task(void* arg) {
bool led_state = false;
while (1) {
// 等待中斷訊號
if (xSemaphoreTake(xSemaphore, portMAX_DELAY)) {
vTaskDelay(pdMS_TO_TICKS(DEBOUNCE_TIME)); // 等待電位穩定
// 確認電位是否真的為低,確保只有「按下」動作有效
if (gpio_get_level(BUTTON_PIN) == 0) {
led_state = !led_state;
gpio_set_level(LED_PIN, led_state);
ESP_LOGI(TAG, "LED:%s", led_state ? "開" : "關");
}
}
}
}
void app_main(void) {
esp_log_level_set(TAG, ESP_LOG_VERBOSE);
xSemaphore = xSemaphoreCreateBinary();
// LED 配置
gpio_config_t led_conf = {
.pin_bit_mask = (1ULL << LED_PIN),
.mode = GPIO_MODE_OUTPUT,
};
gpio_config(&led_conf);
// 按鈕配置
gpio_config_t btn_conf = {
.pin_bit_mask = (1ULL << BUTTON_PIN),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.intr_type = GPIO_INTR_NEGEDGE, // 僅在下降沿(按下)觸發
};
gpio_config(&btn_conf);
gpio_install_isr_service(0); // 安裝中斷
gpio_isr_handler_add(BUTTON_PIN, isr_handler, NULL);
xTaskCreate(led_task, "led_task", 3000, NULL, 10, NULL);
}