【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。