当前位置: 首页 > news >正文

EXTI配置流程

一、EXTI 配置流程(HAL,F1 专用要点)

  1. 开时钟

    • 对应 GPIO 端口:__HAL_RCC_GPIOx_CLK_ENABLE()

    • AFIO 时钟(F1 必须):__HAL_RCC_AFIO_CLK_ENABLE()(HAL 在配置 EXTI 线时用 AFIO->EXTICR 做端口映射)

  2. 配置引脚为外部中断模式(GPIO_Init)

    • Mode 选一个:

      • GPIO_MODE_IT_RISING(上升沿)

      • GPIO_MODE_IT_FALLING(下降沿)

      • GPIO_MODE_IT_RISING_FALLING(双边沿)

    • PullGPIO_PULLUP/GPIO_PULLDOWN/GPIO_NOPULL(根据电路)

    • Pin:对应的 GPIO_PIN_x

    F1 HAL 中,调用 HAL_GPIO_Init() 且 Mode 为 IT_xxx 时,会自动完成 EXTI 线与端口的 AFIO 映射(前提是 AFIO 时钟已开)。

  3. NVIC 配置(中断优先级与使能)

    • 找到该引脚对应的 EXTI IRQ 号(见下表)

    • HAL_NVIC_SetPriority(IRQn, preempt, sub)HAL_NVIC_EnableIRQ(IRQn)

  4. 编写 IRQHandler 与回调

    • 在对应的 EXTIxx_IRQHandler() 中调用:
      HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_x);

    • 实现回调(弱符号,可在用户文件中重写):

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {if (GPIO_Pin == GPIO_PIN_x) { /* 你的处理 */ }
}

清除中断标志:已在 HAL_GPIO_EXTI_IRQHandler() 内完成;若手动操作可用 __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_x)

5.(可选)释放调试引脚

  • 若用到 PA15 / PB3 / PB4 做 EXTI,需要关闭 JTAG(保留 SWD):
    __HAL_AFIO_REMAP_SWJ_NOJTAG();

6.设置优先级分组

HAL_Init()中的  /* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);

EXTI 线号与 IRQ 对应关系(记住这张表)

EXTI 线触发引脚范围对应 NVIC 中断名
0Px0EXTI0_IRQn
1Px1EXTI1_IRQn
2Px2EXTI2_IRQn
3Px3EXTI3_IRQn
4Px4EXTI4_IRQn
5~9Px5…Px9EXTI9_5_IRQn(共享)
10~15Px10…Px15EXTI15_10_IRQn(共享)

同一时刻 一个 EXTI 线只能映射到一个端口的某一脚(比如 EXTI13 只能选 PC13 或 PA13 或 PB13 中的一个)。

例子:使用中断的方法,按下 KEY1 翻转 LED1 状态,而 LED2 一直保持 500ms 的频率闪烁。

如果采用中断法,由于软件消抖需要在中断服务函数加入延时函数,这种做法一般是不被允许的。

exti.c:

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "stm32f1xx_hal.h"   // 建议显式包含,确保 HAL API 与宏可用/*** @brief  外部中断初始化:PA0 -> EXTI0,下降沿触发,上拉输入* @note   F1 系列使用 AFIO 完成 EXTI 端口映射,所以必须打开 AFIO 时钟。*         这里选择“下降沿触发”,常见接法是按键按下把 PA0 拉低。*/
void exti_init(void)
{GPIO_InitTypeDef gpio_initstruct;/* 1) 开启相关时钟:- GPIOA:因为我们要用 PA0- AFIO :F1 通过 AFIO->EXTICR 做 EXTI 端口映射(HAL 初始化 IT 模式时会用到)*/__HAL_RCC_GPIOA_CLK_ENABLE();     // 使能 GPIOA 时钟__HAL_RCC_AFIO_CLK_ENABLE();      // ⚠ F1 必须打开 AFIO 时钟/* 2) 配置 PA0 为“外部中断输入-下降沿触发”,并上拉HAL_GPIO_Init 在 Mode=GPIO_MODE_IT_xxx 时,会自动完成“EXTI0 线 <- PA0”的 AFIO 映射与 EXTI 边沿配置。*/gpio_initstruct.Pin  = GPIO_PIN_0;            // 选择 PA0gpio_initstruct.Mode = GPIO_MODE_IT_FALLING;  // 外部中断:下降沿触发gpio_initstruct.Pull = GPIO_PULLUP;           // 上拉:空闲=高,按下=低// 输入模式下 Speed 无意义,不设置也行,这里保持默认HAL_GPIO_Init(GPIOA, &gpio_initstruct);/* (可选)3) 先清一下挂起位,避免上电毛刺导致的误进中断 */__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);/* 4) 配置 NVIC:打开 EXTI0 的中断入口,并设置优先级- EXTI0_IRQn:专门对应“线0”的中断入口- 优先级:根据你的系统统一规划。下面示例:抢占优先级=2,子优先级=0- 默认 HAL_Init() 会设置优先级分组为 4(4 bits preemption,0 bits sub)*/HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0);HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}/*** @brief  EXTI0 中断入口(硬件向量表指到这里)* @note   这里不要直接清标志;统一交给 HAL 去做:*         HAL_TIM/GPIO 的 IRQHandler 会完成:读取/确认/清除挂起位,*         最后再回调 HAL_GPIO_EXTI_Callback() 交给用户层处理。*/
void EXTI0_IRQHandler(void)
{/* 把“这根线”的中断交给 HAL 做通用处理(含清旗标、调用回调) */HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}/*** @brief  HAL 的 GPIO EXTI 通用回调* @param  GPIO_Pin: 指示到底是哪一根 EXTI 线触发(例如 GPIO_PIN_0)* @note   任何 EXTI 线(0..15)若经 HAL 处理,最终都会走到这个回调;*         用户可依据 GPIO_Pin 做分发。**         这里做了“简单阻塞式消抖”:delay_ms(20) 后再次确认按下再翻转 LED。*         这种办法直观,但会阻塞中断(不推荐在复杂系统中使用)。*         更优雅的做法是:在回调里“暂时屏蔽这根 EXTI 线”,启动一个 20ms 的*         定时器(软定时或硬件定时器),定时到期后在主循环/定时器回调中再读脚、*         处理业务,并重新使能 EXTI —— 这样就是“非阻塞消抖”。*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if (GPIO_Pin == GPIO_PIN_0)  // 只处理 PA0 的情形{/* === 简单阻塞式消抖(与原代码一致):等待20ms再确认 ===注意:1) 若你的 delay_ms() 基于 SysTick,在中断上下文中可能不可用或影响系统节拍;通常建议用“关中断的简单忙等延时”,或避免在 ISR 中做延时。2) 阻塞式延时会延长中断占用时间,可能影响系统实时性。*/delay_ms(20);/* 再次确认仍为“按下”(低电平),才认为有效触发 */if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET){/* 用户业务:翻转 LED(示例) */led1_toggle();}}
}

EXTI 中断实现流程(HAL,代码实现流程)

  1. 开时钟
    __HAL_RCC_GPIOx_CLK_ENABLE() 打开目标端口;
    F1 额外__HAL_RCC_AFIO_CLK_ENABLE() 打开 AFIO 时钟(EXTI 端口映射要用)。

  2. GPIO 配置为 EXTI 模式
    GPIO_InitTypeDef.Mode = GPIO_MODE_IT_FALLING / RISING / RISING_FALLING
    GPIO_InitTypeDef.Pull = GPIO_PULLUP / PULLDOWN / NOPULL
    HAL_GPIO_Init()同时完成 AFIO 的 EXTICR 映射(把 EXTI 线挂到对应端口的那根脚上)以及触发边沿设置。

  3. NVIC 配置
    根据线号选择 IRQ:

    • 0..4 → EXTI0_IRQn..EXTI4_IRQn(独占入口)

    • 5..9 → EXTI9_5_IRQn(共享入口)

    • 10..15 → EXTI15_10_IRQn(共享入口)
      HAL_NVIC_SetPriority() + HAL_NVIC_EnableIRQ() 使能。

  4. 触发时序
    引脚满足设定边沿 → EXTI 寄存器置挂起位(PR) → NVIC 进对应 IRQ。

  5. IRQ 入口
    EXTIxx_IRQHandler()调用 HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_x),把通用操作交给 HAL。

  6. HAL IRQ Handler 做的事

    • 读取并清除 EXTI 挂起位;

    • 调用弱符号回调 HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

  7. 用户回调
    HAL_GPIO_EXTI_Callback() 里根据 GPIO_Pin 判断来源并处理业务(比如翻转 LED、发送消息、唤醒任务等)。

  8. 返回
    中断退出。如果需要“非阻塞消抖”,建议在回调里屏蔽该线、启动 X ms 定时器,到期后在线程上下文再读取脚并恢复中断。

http://www.dtcms.com/a/334843.html

相关文章:

  • Day15 Docker
  • 软件I2C实现(2):I2C协议实现
  • 小迪安全v2023学习笔记(六十三讲)—— JS加密断点调试
  • Linux-Vim编辑器最简美化配置
  • CSS 核心知识点全解析:从基础到实战应用
  • 【每日一题】Day 4
  • 解决 Microsoft Edge 显示“由你的组织管理”问题
  • 17.4 合并购物车
  • Linux怎么查看服务器开放和启用的端口
  • linux top指令
  • 一种命令行版的网络调试助手
  • 一周学会Matplotlib3 Python 数据可视化-绘制绘制甘特图
  • EXTI外部中断的执行逻辑|以对射式红外传感器计次为例
  • 广东省省考备考(第七十八天8.16)——资料分析、判断推理(强化训练)
  • 力扣(最小覆盖子串)
  • Hana IDE 安装吧报错
  • 【数据分析】比较SparCC、Pearson和Spearman相关性估计方法在合成组学数据上的表现
  • Reading Coach-微软推出的免费AI阅读教练
  • linux I2C核心、总线与设备驱动
  • 扫地机器人(2025蓝桥杯省A组 H题)
  • [系统架构设计师]系统架构设计基础知识(七)
  • Conda创建py3.10环境(股票),并且安装程序包的命令
  • 《设计模式》装饰模式
  • python日志新姿势,Loguru库的应用
  • 后台管理系统-3-vue3之左侧菜单栏和头部导航栏的静态搭建
  • VUE+SPRINGBOOT从0-1打造前后端-前后台系统-用户管理
  • 力扣(LeetCode) ——142. 环形链表 II(C语言)
  • [Python]PTA:实验2-3-1-for 求1到100的和
  • ComfyUI-3D-Pack:3D创作的AI神器
  • 深度强化学习是否违背样本独立原则?