按键控制LED灯-ESP32中断处理
#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); }