【ESP32】ESP-IDF开发 | 中断矩阵+按键输入中断例程
1. 简介
ESP32的中断是十分灵活的,依靠中断矩阵,ESP32可以将任一外部中断源单独分配到每个 CPU的任一外部中断上。
ESP32总共有71个外部中断源,每个CPU可以链接26个外部中断源,因此总共可以生成52个外部中断(双核)。 但是外部中断源中有4个是不能任意分配的,只能分配给指定的CPU,像上图的PRO_CPU或APP_CPU。
ESP32的每个CPU有32个中断,其中编号6、7、11、15、16、29为内部中断,其余都属于外部中断。具体的外部中断源和内部中断可以查看官方的参考手册。
2. 例程
例程中实现一个按键检测,只不过采用中断的方式去判断。
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "esp_log.h"#define TAG "app"static SemaphoreHandle_t sem;static void IRAM_ATTR gpio_isr_fn(void *args)
{if (sem) {/* 释放信号量 */xSemaphoreGiveFromISR(sem, NULL);}
}void app_main()
{gpio_config_t gpio_cfg = {0};gpio_cfg.mode = GPIO_MODE_INPUT;gpio_cfg.pull_down_en = GPIO_PULLDOWN_DISABLE;gpio_cfg.pull_up_en = GPIO_PULLUP_ENABLE; // 上拉gpio_cfg.intr_type = GPIO_INTR_POSEDGE; // 上升沿触发gpio_cfg.pin_bit_mask = (1 << GPIO_NUM_0);/* 初始化GPIO */gpio_config(&gpio_cfg);/* 注册二值信号量 */vSemaphoreCreateBinary(sem);xSemaphoreTake(sem, 0);/* 注册中断处理函数 */gpio_install_isr_service(0);gpio_isr_handler_add(GPIO_NUM_0, gpio_isr_fn, NULL);while (1) {/* 等待信号量 */if (pdTRUE == xSemaphoreTake(sem, portMAX_DELAY)) {ESP_LOGI(TAG, "Key pressed");}}
}
我使用的按键是连接到IO0上的,带外部上拉;因此GPIO设置成上升沿中断,这样当释放按键的时候才会触发中断。
使用gpio_install_isr_service函数注册GPIO的中断服务,可以传一个注册标志,一般保持默认,即0;接下来就可以使用gpio_isr_handler_add向服务注册中断处理函数,传入管脚号、处理函数和处理函数的参数。中断处理函数可以加一个IRAM_ATTR标志,这样这个函数会被放到内部SDRAM中运行,可以提高运行速度,凡是中断处理函数都可以考虑加这个标志。
以往为了调试我们喜欢在中断处理函数中调用printf,原则上是不允许的,但对于STM32单片机来说没啥影响;ESP32的话就千万不能这样写,会导致系统崩溃。所以这里我使用了二值信号量去实现,在中断处理函数中去释放信号量,在主循环中等待这个信号量,如果获取到了信号量才去打印log。