中断(Interrupt)是一种非常重要和常用的机制,用于响应外部事件并执行特定的代码。当某个特定条件满足时(如 GPIO 引脚的信号状态发生变化),中断将会被触发,并执行与该中断相关联的 ISR(Interrupt Service Routine)函数。
要使用中断,必须先进行中断配置和初始化设置,然后注册 ISR 函数以便在中断触发时执行。以下是一些常用的 ESP32 IDF 中断 API 函数:
1. esp_intr_alloc()
用于分配一个可用的中断向量,并返回一个中断句柄(intr_handle_t)。函数原型如下:
esp_err_t esp_intr_alloc(int cpu_no, int intr_source, int flags, intr_handler_t intr_handler, void* arg, intr_handle_t* handle);
2. esp_intr_free()
用于释放中断句柄(intr_handle_t)所占用的资源。函数原型如下:
void esp_intr_free(intr_handle_t handle);
3. esp_intr_enable()
用于启用指定中断。函数原型如下:
void esp_intr_enable(intr_handle_t handle);
4. esp_intr_disable()
用于禁用指定中断。函数原型如下:
void esp_intr_disable(intr_handle_t handle);
通过使用这些 API 函数,我们可以很容易地配置和管理中断,并执行与中断相关联的处理函数。通常,我们可以将中断视为响应外部事件的一种重要机制,例如接收 GPS 定位数据、读取传感器数据或处理网络数据等。
下面是一个简单的示例,演示如何在 ESP32 上使用中断来处理 GPIO 引脚状态的变化。
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
// 中断处理函数 ISR
void IRAM_ATTR gpio_isr_handler(void* arg)
{
uint32_t gpio_num = (uint32_t)arg;
printf("GPIO[%d] Interrupt!!!!!!\n", gpio_num);
}
void app_main()
{
// 关闭 GPIO 中断
gpio_intr_disable(GPIO_NUM_27);
// 配置 GPIO 引脚为输入模式
gpio_set_direction(GPIO_NUM_27, GPIO_MODE_INPUT);
// 设置 GPIO 中断类型为上升沿触发
gpio_set_intr_type(GPIO_NUM_27, GPIO_INTR_POSEDGE);
// 通过 esp_intr_alloc() 函数分配中断向量
intr_handle_t handle;
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, ESP_INTR_FLAG_EDGE, gpio_isr_handler, (void*)GPIO_NUM_27, &handle);
// 通过 esp_intr_enable() 函数启用中断
esp_intr_enable(handle);
while(1) {
printf("hello world!\n");
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
在代码中,我们首先通过 gpio_intr_disable() 关闭 GPIO 中断,并使用 gpio_set_direction() 将 GPIO 设置为输入模式。然后,我们将 GPIO 中断类型设置为 GPIO_INTR_POSEDGE,指示中断在上升沿时触发。这样,在 GPIO 引脚状态发生变化时,中断将会被触发,并执行与中断相关联的处理函数(即 gpio_isr_handler)。
最后,我们使用 esp_intr_alloc() 分配中断向量并启动中断处理,通过 esp_intr_enable() 启用中断。在 while 循环中,我们通过 vTaskDelay() 函数暂停 1 秒钟,以便观察中断处理的效果。