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);
}
相关推荐
平凡灵感码头15 小时前
基于 STM32 的智能门锁系统,系统界面设计
stm32·单片机·嵌入式硬件
Truffle7电子17 小时前
STM32理论 —— 存储、中断
stm32·嵌入式硬件·嵌入式·存储·中断
报错小能手17 小时前
linux学习笔记(32)网络编程——UDP
单片机·嵌入式硬件
XiangrongZ18 小时前
江协科技STM32课程笔记(四)—定时器TIM(输入捕获)
笔记·科技·stm32
xyx-3v19 小时前
SPI四种工作模式
stm32·单片机·嵌入式硬件·学习
qiuiuiu41319 小时前
正点原子RK3568学习日志6-驱动模块传参
linux·c语言·开发语言·单片机·学习
BreezeJuvenile20 小时前
实验二 呼吸灯功能实验
stm32·单片机·嵌入式系统·流水灯·实验
北京阿尔泰科技厂家1 天前
CPCIe-76F1G控制器:国产化高性能嵌入式解决方案
嵌入式硬件·控制器·工业自动化·数据采集卡·国产化控制器
Truffle7电子1 天前
STM32【H7】理论——通信
stm32·单片机·嵌入式硬件