按键控制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);

}
原文地址:https://www.cnblogs.com/kerwincui/p/13937824.html