GPIO 中断通用配置指南

面向ARM Cortex-M 系列。

1. GPIO 中断核心原理

ARM 架构 MCU 的 GPIO 中断设计遵循 "分组复用 + 寄存器控制" 原则,不同厂商芯片的核心逻辑一致,仅寄存器命名和中断分组细节有差异。

1.1 中断分组与中断号分配

多数 ARM MCU 不会为每个 GPIO 引脚分配独立中断号,而是按 "GPIO 组 + 引脚范围" 分组复用中断号,常见分组方式有两种:

  • 按引脚范围分组:每组 GPIO(如 GPIO1、GPIO2)的低 16 个引脚(0~15)共用一个中断号,高 16 个引脚(16~31)共用另一个中断号(如 NXP RT1052、STM32F4)。
  • 按 GPIO 组分组:多个 GPIO 组(如 GPIO1+GPIO2、GPIO3+GPIO4)共用一个中断号(如 NXP RT1176 部分配置)。

无论哪种分组,中断触发后需通过 "中断状态寄存器" 判断具体是哪个引脚触发中断。

1.2 核心控制寄存器

每组 GPIO 的中断功能由 4 类核心寄存器控制,所有 ARM MCU 的寄存器逻辑一致,仅命名可能不同(如 "中断屏蔽寄存器" 可能命名为 GPIOx_IMR 或 GPIOx_IER):

寄存器类型 核心功能 操作逻辑
中断屏蔽寄存器 控制单个 GPIO 引脚是否允许触发中断 32 位寄存器,对应 32 个引脚;某位置 1 = 允许该引脚中断,置 0 = 禁止(复位默认 0)
中断状态寄存器 标记单个 GPIO 引脚是否发生中断 32 位寄存器,对应 32 个引脚;中断触发后硬件自动置 1,需软件写 1 清除(关键!)
中断触发配置寄存器 配置单个 GPIO 引脚的中断触发条件(电平 / 边沿触发) 每个引脚占用 1~2 位;常见配置:低电平、高电平、上升沿、下降沿、双边沿
中断清除寄存器 单独清除指定引脚的中断标志(部分 MCU 将此功能整合到 "中断状态寄存器") 写 1 清除对应引脚中断标志,与 "中断状态寄存器" 操作逻辑一致

2. 硬件设计原则

GPIO 中断的硬件设计需满足 :

  1. 电平匹配:确保 GPIO 引脚输入电平与 MCU 的 IO 电平一致。
  2. 上下拉配置
    • 若输入信号默认无电平(如悬空引脚),需配置 MCU 内部上拉 / 下拉电阻(推荐上拉),避免引脚电平漂浮导致误中断。
    • 若外部信号已自带上下拉(如传感器输出),则 MCU 内部上下拉可关闭,避免冲突。

3. 软件设计通用实现

GPIO 中断配置步骤

1. GPIO 引脚基础配置(输入 / 输出、中断触发方式)
复制代码
/**
 * @brief 配置GPIO引脚为中断输入模式
 * @param gpio_base: GPIO端口基地址(如GPIOA、GPIOB等)
 * @param pin: 引脚号(0~15/31,取决于芯片)
 * @param trig_mode: 触发方式(上升沿/下降沿/双边沿)
 */
void gpio_irq_pin_config(GPIO_TypeDef *gpio_base, uint32_t pin, uint8_t trig_mode) {
    // 1. 使能GPIO时钟(不同芯片时钟使能寄存器不同,需适配)
    // 示例:STM32F4使能GPIOA时钟
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
    // 示例:NXP RT1176使能GPIO7时钟
    // CCM->CCGR6 |= CCM_CCGR6_GPIO7(CCM_CCGR_ON);

    // 2. 配置引脚为输入模式
    gpio_base->MODER &= ~(0x3 << (pin * 2));  // 清除原有配置
    gpio_base->MODER |= (0x0 << (pin * 2));   // 00=输入模式

    // 3. 配置上拉/下拉(根据硬件需求,可选)
    gpio_base->PUPDR &= ~(0x3 << (pin * 2));
    gpio_base->PUPDR |= (0x1 << (pin * 2));   // 01=上拉(或02=下拉)

    // 4. 配置中断触发方式(边沿检测)
    // 注意:不同芯片寄存器名不同,以下为通用逻辑
    if (trig_mode & 0x01) {  // 上升沿触发
        gpio_base->RTSR |= (1 << pin);  // 上升沿触发使能
        gpio_base->FTSR &= ~(1 << pin); // 关闭下降沿(若需双边沿则不关闭)
    }
    if (trig_mode & 0x02) {  // 下降沿触发
        gpio_base->FTSR |= (1 << pin);  // 下降沿触发使能
        gpio_base->RTSR &= ~(1 << pin); // 关闭上升沿(若需双边沿则不关闭)
    }

    // 5. 清除引脚中断标志(避免初始状态触发)
    gpio_base->PR |= (1 << pin);  // 写1清除标志(多数ARM芯片逻辑)
}
2. 中断控制器(NVIC)配置
复制代码
/**
 * @brief 配置NVIC中断控制器(使能中断、设置优先级)
 * @param irq_n: 中断向量号(如GPIOA_IRQn、GPIO7_IRQn)
 * @param priority: 中断优先级(0~15,0为最高,受芯片位数限制)
 */
void nvic_irq_config(IRQn_Type irq_n, uint32_t priority) {
    // 1. 清除中断挂起标志(若有)
    NVIC_ClearPendingIRQ(irq_n);

    // 2. 设置中断优先级(ARM Cortex-M使用抢占优先级+子优先级,需先配置分组)
    // 配置优先级分组(系统级,通常在main中初始化一次)
    // 示例:分组2(2位抢占优先级,2位子优先级)
    NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);

    // 设置抢占优先级和子优先级(此处简化为抢占优先级=priority,子优先级=0)
    NVIC_SetPriority(irq_n, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), priority, 0));

    // 3. 使能中断
    NVIC_EnableIRQ(irq_n);
}
3. 使能 GPIO 中断(连接 GPIO 与 NVIC)
复制代码
/**
 * @brief 使能指定GPIO引脚的中断(连接到NVIC)
 * @param gpio_base: GPIO端口基地址
 * @param pin: 引脚号
 */
void gpio_irq_enable(GPIO_TypeDef *gpio_base, uint32_t pin) {
    // 使能引脚级中断(不同芯片寄存器名可能为IMR/IE等)
    gpio_base->IMR |= (1 << pin);  // 中断屏蔽寄存器:允许引脚中断信号输出到NVIC
}

三、中断服务程序(ISR)实现

复制代码
/**
 * @brief GPIO中断服务函数(需与中断向量表绑定,函数名固定)
 * 注意:不同芯片的中断服务函数名不同(如GPIOA_IRQHandler、GPIO7_IRQHandler)
 */
void GPIOx_IRQHandler(void) {  // 替换为实际函数名(如GPIO7_IRQHandler)
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    GPIO_TypeDef *gpio_base = GPIO7;  // 替换为实际GPIO端口
    uint32_t pin = 0;  // 替换为实际引脚号

    // 1. 检查中断标志(确认是目标引脚触发)
    if (gpio_base->PR & (1 << pin)) {
        // 2. 清除中断标志(必须!否则会重复触发)
        gpio_base->PR |= (1 << pin);  // 写1清除

        // 3. 中断处理逻辑(简洁!避免耗时操作)
        // 示例1:直接执行简单处理(如翻转LED)
        // LED_GPIO->ODR ^= (1 << LED_PIN);

        // 示例2:通过信号量唤醒任务(推荐,适合复杂处理)
        if (gpio_irq_sem != NULL) {
            xSemaphoreGiveFromISR(gpio_irq_sem, &xHigherPriorityTaskWoken);
        }
    }

    // 4. 若使用FreeRTOS,且有高优先级任务被唤醒,请求任务切换
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
相关推荐
无垠的广袤8 小时前
【工业树莓派 CM0 NANO 单板计算机】本地部署 EMQX
linux·python·嵌入式硬件·物联网·树莓派·emqx·工业物联网
雲烟10 小时前
嵌入式设备EMC安规检测参考
网络·单片机·嵌入式硬件
泽虞10 小时前
《STM32单片机开发》p7
笔记·stm32·单片机·嵌入式硬件
田甲10 小时前
【STM32】 数码管驱动
stm32·单片机·嵌入式硬件
up向上up11 小时前
基于51单片机垃圾箱自动分类加料机快递物流分拣器系统设计
单片机·嵌入式硬件·51单片机
纳祥科技20 小时前
Switch快充方案,内置GaN,集成了多个独立芯片
单片机
单片机日志21 小时前
【单片机毕业设计】【mcugc-mcu826】基于单片机的智能风扇系统设计
stm32·单片机·嵌入式硬件·毕业设计·智能家居·课程设计·电子信息
松涛和鸣1 天前
从零开始理解 C 语言函数指针与回调机制
linux·c语言·开发语言·嵌入式硬件·排序算法
小曹要微笑1 天前
STM32F7 时钟树简讲(快速入门)
c语言·stm32·单片机·嵌入式硬件·算法
XINVRY-FPGA1 天前
XCVP1802-2MSILSVC4072 AMD Xilinx Versal Premium Adaptive SoC FPGA
人工智能·嵌入式硬件·fpga开发·数据挖掘·云计算·硬件工程·fpga