[ESP-IDF] GPIO端口中断
esp32 中断demo如下:
#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
const gpio_num_t gpio01 = 18;
const gpio_num_t gpio02 = 17;
static bool sta = true;
static QueueHandle_t gpioEventQueue = NULL;
static void IRAM_ATTR intrHandler(void* arg) {
uint32_t gpio_num = (uint32_t)arg;
xQueueSendFromISR(gpioEventQueue, &gpio_num, NULL);
}
static void gpioTaskExample(void* arg) {
int ioNum = (int)arg;
while (true) {
if (xQueueReceive(gpioEventQueue, &ioNum, portMAX_DELAY)) {
int a = gpio_get_level(ioNum);
if (a == 1) {
sta = !sta;
printf("GPIO[%d] intrrupted, level: %d\n", ioNum, gpio_get_level(ioNum));
}
}
}
}
void app_main(void) {
// gpio_config_t gpio18 = {
// .pin_bit_mask = 1ull << 18,
// .mode = GPIO_MODE_INPUT_OUTPUT,
// .intr_type = GPIO_INTR_ANYEDGE,
// .pull_down_en = 1,
// };
// gpio_config(&gpio18);
// 设置输入模式
gpio_set_direction(gpio01, GPIO_MODE_INPUT);
// GPIO设置中断触发类型
gpio_set_intr_type(gpio01, GPIO_INTR_ANYEDGE);
// 下降沿监听
gpio_pulldown_en(gpio01);
// 设置输出高电平
gpio_set_level(gpio01, 1);
gpio_set_direction(gpio02, GPIO_MODE_OUTPUT);
gpio_set_level(gpio02, 1);
// 创建一个新的队列实例,并返回一个句柄,通过该句柄可以引用新队列。
gpioEventQueue = xQueueCreate(10, sizeof(uint32_t));
// 创建一个新任务并将其添加到准备运行的任务列表中。
xTaskCreate(gpioTaskExample, "ExampleTask", 2048, NULL, 10, NULL);
/*
安装 GPIO 驱动程序的 ETS_GPIO_INTR_SOURCE ISR 处理程序服务,该服务允许每个引脚的 GPIO 中断处理程序。
此函数与 gpio_isr_register() 不兼容 - 如果使用该函数,则为所有 GPIO 中断注册单个全局 ISR。
如果使用此函数,则 ISR 服务将提供全局 GPIO ISR,并通过 gpio_isr_handler_add() 函数注册单个引脚处理程序。
*/
gpio_install_isr_service(0);
/*
为相应的 GPIO 引脚添加 ISR 处理程序。
使用 gpio_install_isr_service() 安装驱动程序的 GPIO ISR 处理程序服务后调用此函数。
引脚 ISR 处理程序不再需要使用 IRAM_ATTR 声明,除非在 gpio_install_isr_service() 中分配 ISR 时传递 ESP_INTR_FLAG_IRAM 标志。
此 ISR 处理程序将从 ISR 调用。因此,存在堆栈大小限制(可在 menuconfig 中配置为“ISR 堆栈大小”)。与全局 GPIO 中断处理程序相比,此限制较小,因为间接级别更高。
*/
gpio_isr_handler_add(gpio01, intrHandler, (void*)18);
printf("finished\n");
while (1) {
printf("mian function is running!%d \n", sta);
gpio_set_level(gpio02, sta);
// 延时
vTaskDelay(750 / portTICK_PERIOD_MS);
}
}
ESP32 GPIO 可能无法正确触发中断。
描述:
如果多个 GPIO 管脚配置了沿中断,则 ESP32 硬件可能⽆法正确触发中断。
解决方案原文: