【快速上手ESP32(基于ESP-IDF&VSCode)】02-GPIO外部中断

ESP32的中断

ESP32的中断矩阵是一个关键组件,它负责将外部中断源单独映射到每个CPU的外部中断上。其主要功能和特点如下:

  1. 中断源映射:中断矩阵能够接受多个外部中断源作为输入,然后将这些中断源映射到CPU的外部中断上。这种映射关系允许CPU及时响应并处理来自不同外设的中断信号。
  2. 多CPU支持:ESP32通常具有多个CPU核心,中断矩阵可以为每个CPU生成相应的外部中断。这意味着不同的CPU可以并行处理来自不同外设的中断,提高了系统的整体性能。
  3. 屏蔽与查询功能:中断矩阵还提供了屏蔽CPU的NMI(非屏蔽中断)类型中断的功能,这有助于确保关键中断信号能够得到优先处理。此外,它还可以查询外部中断源当前的中断状态,为系统调试和故障排查提供了便利。

在ESP32的实际应用中,中断矩阵的作用不可忽视。它使得CPU能够高效地处理来自各种外设的中断信号,从而实现对系统资源的有效利用和响应速度的提升。通过合理地配置中断矩阵,开发人员可以优化系统的性能,提高系统的稳定性和可靠性。

以上描述来自文心一言。

简单来说就是ESP32通过中断矩阵,在外部中断这块很强。每个CPU可以有32个中断,而ESP32是双核的,因此理论上可以处理64个中断。

【STM32F103】中断系统&外部中断_stm32f103能设置多少个io中断-CSDN博客文章浏览阅读1.2k次,点赞20次,收藏17次。说到中断就离不开嵌套向量中断控制器(NVIC),NVIC控制整个芯片的中断相关问题,NVIC属于是内核里面的一个外设,因此与其说是STM32F103的中断系统,倒不如说是Cortex-M3(STM32F103的内核)的中断系统。Cortex-M3内核支持256个中断,其中16个内部中断,240个外部中断。以及256级中断优先级的设置。而STM32可支持85个中断,其中16个内部中断,68个外部中断。以及16级中断优先级的设置。_stm32f103能设置多少个io中断https://blog.csdn.net/m0_63235356/article/details/134875381?spm=1001.2014.3001.5501而在之前STM32的介绍外部中断的文章中我们可以得知,STM32只有16个外部中断通道,因此同时只能有16个外部中断。

虽然我个人觉得外部中断实际运用中大概率不会同时使用那么多,但是我单方面宣布,在外部中断这方面ESP32完胜STM32。

其实在硬件层面的设计我们可以不需要知道的很清楚,我们只需要知道怎么使用即可。

库函数

外部中断相关的函数,在编程指南中和GPIO是在同一个地方的。

GPIO & RTC GPIO - ESP32 - --- ESP-IDF 编程指南 latest 文档 (espressif.com)https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/peripherals/gpio.html我们按照网站中的顺序依次看看和中断相关的函数。

设置中断触发的类型,这个实际上可以在初始化GPIO的时候就设置好。

常用的就是上升沿或者是下降沿。

这个不用多说,就是启用GPIO的中断(实测的时候,没有使用这个函数貌似也可以,之前忘记加上这个结果依旧可以进入中断,但是最好就是加上)。

有使能也有失能。

这个函数,给所有GPIO注册一个中断处理函数,但是我实测之后发现并不好使,它只被触发了一次,可能后续还有什么需要操作的地方,但是我没找到解决方法。

因此我们就不使用这个函数去注册中断处理函数了

我们使用下面两个函数去注册。

首先我们使用这个函数去配置中断。并且也看到了,这个函数和上面那个是冲突的。

可填的参数有下面几个,我们根据实际需求选择。

配置完中断之后,我们还需要绑定一个中断处理函数。

使用上面的函数,先填入我们的GPIO口,再填入中断函数的名字,最后一个参数是传给中断函数的参数,我们给个NULL就行。

关于中断处理函数,我们名字可以随便起,然后返回值为void,参数列表可以给个void*的形参。

另外可以在返回值后面,函数名前面加个IRAM_ATTR。不加也可以。

如果需要使用IRAM_ATTR,那么需要包含头文件。

cpp 复制代码
#include "esp_attr.h"

下面是文心一言的介绍。

在ESP-IDF(Espressif IoT Development Framework)中,IRAM_ATTR是一个宏定义,用于将特定的函数或变量指定为在IRAM(指令RAM)中运行或存储。IRAM是ESP32等芯片内部的一块特殊RAM区域,它主要用于存储那些需要在RAM中直接执行的代码,以加快代码执行速度并减少从Flash加载代码所消耗的时间。

使用IRAM_ATTR宏定义可以确保相关的代码或数据被放置在IRAM中。这对于时间关键的代码部分尤为重要,因为这些代码需要尽可能快地执行,以便及时响应中断或执行其他关键任务。通过将这部分代码放在IRAM中,可以减少CPU访问Flash所带来的延迟,因为直接从RAM中读取和执行代码通常比从Flash中读取要快得多。

例如,某些中断服务程序(ISR)需要快速响应中断事件,因此它们应该被放置在IRAM中以确保快速执行。同样,一些需要在RAM中运行的库函数或应用程序代码也可以使用IRAM_ATTR来指定它们的存储位置。

需要注意的是,IRAM的容量有限,因此应该谨慎使用IRAM_ATTR,确保只将真正需要快速执行的代码放置在IRAM中,以避免浪费宝贵的RAM资源。在ESP-IDF的文档和参考手册中,通常会详细说明IRAM的大小和使用限制,以便开发者能够正确地使用它。

那么有了上面的函数之后,我们就可以实现一下按键控制LED的亮灭。

完整代码

cpp 复制代码
#include "driver/gpio.h"
#include <unistd.h>
#include "esp_attr.h"

void Z_Init_LED_GPIO(void){
    gpio_config_t init;
    init.intr_type = GPIO_INTR_DISABLE;             // 失能中断;
    init.mode = GPIO_MODE_OUTPUT | GPIO_MODE_INPUT; // 输出模式和输入
    init.pin_bit_mask = (1ULL << 18);               // GPIO18
    init.pull_down_en = GPIO_PULLDOWN_DISABLE;      // 失能下拉模式
    init.pull_up_en = GPIO_PULLUP_ENABLE;           // 使能上拉模式
    gpio_config(&init);
}

void IRAM_ATTR IT_Function(void *arg){
    //消抖处理
    if(gpio_get_level(10)==1){
        usleep(10);
        if(gpio_get_level(10)==1){
            //执行的代码写这里
            gpio_set_level(18,!gpio_get_level(18));
        }
    }
}

void Z_Init_IT_GPIO(void){
    gpio_config_t init;
    init.intr_type = GPIO_INTR_POSEDGE;        // 开启上升沿中断;
    init.mode = GPIO_MODE_INPUT;               // 输入模式
    init.pin_bit_mask = (1ULL << 10);          // GPIO10
    init.pull_down_en = GPIO_PULLDOWN_DISABLE; // 失能下拉模式
    init.pull_up_en = GPIO_PULLUP_ENABLE;      // 使能上拉模式
    gpio_config(&init);

    gpio_install_isr_service(ESP_INTR_FLAG_EDGE);                   // 安装 GPIO 中断服务程序(边沿触发)
    gpio_isr_handler_add(GPIO_NUM_10, IT_Function, NULL);           // 分配中断处理程序

    gpio_intr_enable(GPIO_NUM_10);
}

void app_main(void){
    Z_Init_LED_GPIO();
    Z_Init_IT_GPIO();

    while (1){
        sleep(1);
    }
}

需要注意的是最好不要在中断函数里执行太久,避免使用延时函数(上面代码为了消抖没办法才用的)和打印日志。

相关推荐
一起搞IT吧15 小时前
嵌入式ARM SOC开发中文专题分享一:ARM SOC外围资源介绍
arm开发·嵌入式硬件
研华嵌入式16 小时前
如何在高通跃龙QCS6490 Arm架构上使用Windows 11 IoT企业版?
arm开发·windows·嵌入式硬件
矢志不移79216 小时前
裸机开发 时钟配置,EPIT
单片机·嵌入式硬件
清风66666617 小时前
基于STM32的APP遥控视频水泵小车设计
stm32·单片机·mongodb·毕业设计·音视频·课程设计
CAE虚拟与现实19 小时前
VSCode中的下载VSIX是指什么?
ide·vscode·编辑器
物随心转20 小时前
RTC驱动原理
嵌入式硬件
BAGAE20 小时前
MODBUS 通信协议详细介绍
linux·嵌入式硬件·物联网·硬件架构·iot·嵌入式实时数据库·rtdbs
风_峰21 小时前
Petalinux相关配置——ZYNQ通过eMMC启动
嵌入式硬件·ubuntu·fpga开发
风_峰21 小时前
【ZYNQ开发篇】Petalinux和电脑端的静态ip地址配置
网络·嵌入式硬件·tcp/ip·ubuntu·fpga开发
路边闲人221 小时前
vscode启用GEMINI CODE ASSIST插件
ide·vscode·gemini