#include <driver/gpio.h> #include <esp_task_wdt.h> #include <freertos/FreeRTOS.h> #include <freertos/queue.h> #include <freertos/semphr.h> #include <freertos/task.h> #include <math.h> #include "sdkconfig.h" #define MIN_DELAY 500 #define BUTTON_GPIO GPIO_NUM_14 #define BLINK_GPIO GPIO_NUM_13 static char *TAG = "SMART-WATER"; //二值信號量可以在某個特殊的中斷發送時,讓任務解除阻塞,相當於讓任務與中斷同步。 //這樣,可以讓中斷事件處理量大的工作在同步任務中完成,中斷服務例程(ISR)中只是快速處理少部分工作。 static xSemaphoreHandle semaphore_handle = NULL; //任務處理函數 void led_task(void* arg) { bool x = false; while (true) { //獲取信號量,portMAX_DELAY標識一直等待,可以設置具體的時鍾滴答次數 xSemaphoreTake(semaphore_handle, portMAX_DELAY); x = !x; gpio_set_level(BLINK_GPIO, x); } } //按鈕中斷處理 void IRAM_ATTR button_isr_handler(void* arg) { int last_time = 0; //獲取系統當前運行的時鍾節拍數,此函數用於在中斷服務程序里面調用, 如果在任務里面調用的話, //需要使用函數 xTaskGetTickCount,這兩個函數切不可混用 int now = xTaskGetTickCountFromISR(); if (now - last_time > MIN_DELAY) { int ignored = pdFALSE; //通過釋放信號量來使任務解除阻塞 xSemaphoreGiveFromISR(semaphore_handle, &ignored); last_time = now; } } void app_main(void) { gpio_pad_select_gpio(BLINK_GPIO); gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); gpio_pad_select_gpio(BUTTON_GPIO); gpio_set_direction(BUTTON_GPIO, GPIO_MODE_INPUT); //上拉 gpio_set_pull_mode(BUTTON_GPIO, GPIO_PULLUP_ONLY); //設置電平下降沿觸發中斷 gpio_set_intr_type(BUTTON_GPIO, GPIO_INTR_NEGEDGE); //創建一個二進制信號量 semaphore_handle = xSemaphoreCreateBinary(); //創建任務,param1:任務入口函數,無限循環 param2:任務名稱 //param3:指定任務堆棧的大小 ,堆棧能保護變量的數目,不是字節數。棧空間 大小為usStackDepth*4(bytes)。 //param4:指針用於作為一個參數傳向創建的任務 param5:任務運行時的優先級 param6:用於傳遞一個處理——引用創建的任務 xTaskCreate(led_task, "led_task", 2048, NULL, 10, NULL); //第一個處理器核安裝中斷處理程序 gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1); //添加中斷處理函數 gpio_isr_handler_add(BUTTON_GPIO, button_isr_handler, NULL); }