中断点灯--外部中断代码执行流程

中断点灯

#include "exti.h"
#include "sys.h"
#include "delay.h"
#include "led.h"

void exti_init(void)
{
    GPIO_InitTypeDef gpio_initstruct;
    //打开时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();                   //使能GPIO时钟
    //调用GPIO初始化函数
    gpio_initstruct.Pin = GPIO_PIN_0;               //设置AFIO
    gpio_initstruct.Mode = GPIO_MODE_IT_FALLING;    //设置EXTI,下降沿触发
    gpio_initstruct.Pull = GPIO_PULLUP;             //设置GPIO输入模式
    gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &gpio_initstruct);
    //设置NVIC
    HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0);         //设置优先级,EXTI0_IRQn就是PA0的中断线
    HAL_NVIC_EnableIRQ(EXTI0_IRQn);                 //使能中断
}

//中断服务函数,中断服务函数没有任何的返回值和传入的参数
void EXTI0_IRQHandler(void)                         //中断服务函数的名字是在启动文件中写好的,找到对应的中断线即可。
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);           //调用公共服务函数
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)      //在回调函数中写代码
{
    delay_ms(20);
    if(GPIO_Pin == GPIO_PIN_0)
    {
        if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET)
        {
            led1_toggle();
        }
    }
}

STM32 HAL 外部中断(EXTI)代码执行流程总结

一、整体流程概览

PA0 下降沿

EXTI 硬件检测触发

EXTI0 中断线置位

NVIC 判断并响应中断

CPU 跳转到 EXTI0_IRQHandler

HAL_GPIO_EXTI_IRQHandler

HAL_GPIO_EXTI_Callback

执行用户代码(LED 翻转)


二、初始化阶段(exti_init)

1. 使能 GPIO 时钟

__HAL_RCC_GPIOA_CLK_ENABLE();
  • GPIO 属于外设,必须先打开时钟
  • 否则后续 GPIO 配置无效

2. 配置 PA0 为外部中断输入

gpio_initstruct.Pin   = GPIO_PIN_0;
gpio_initstruct.Mode  = GPIO_MODE_IT_FALLING;
gpio_initstruct.Pull  = GPIO_PULLUP;
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &gpio_initstruct);

作用说明:

  • GPIO_MODE_IT_FALLING
    • 将 PA0 连接到 EXTI0
    • 配置为下降沿触发中断
  • GPIO_PULLUP
    • 默认高电平
    • 按键按下拉低,形成下降沿

3. 配置 NVIC

HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
  • 设置 EXTI0 中断优先级
  • 允许 EXTI0 中断进入 CPU
  • 若未使能 NVIC,中断不会被响应

三、中断触发阶段(硬件行为)

  1. 按键按下,PA0 电平由高变低
  2. EXTI 检测到下降沿
  3. EXTI0 中断标志位被置位
  4. 向 NVIC 发送中断请求

四、中断响应阶段(ISR)

1. NVIC 响应中断

  • 判断中断是否使能
  • 判断优先级
  • CPU 暂停主程序,进入中断服务函数

2. 执行中断服务函数

void EXTI0_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}

作用:

  • 调用 HAL 提供的通用 EXTI 中断处理函数

3. HAL_GPIO_EXTI_IRQHandler 内部逻辑

  • 判断 EXTI0 是否触发
  • 清除 EXTI0 中断标志位
  • 调用用户回调函数

五、回调函数阶段(用户代码)

HAL_GPIO_EXTI_Callback

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    delay_ms(20);  // 按键消抖

    if (GPIO_Pin == GPIO_PIN_0)
    {
        if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
        {
            led1_toggle();
        }
    }
}

说明:

  • 所有 EXTI 中断都会进入该回调函数
  • 通过 GPIO_Pin 判断具体触发源
  • 延时 + 再次读取引脚电平实现按键消抖
  • 执行 LED 翻转操作

六、关键点总结

  • EXTI:负责检测引脚电平变化
  • NVIC:决定中断是否进入 CPU
  • ISR(中断服务函数):清中断标志并分发回调
  • 回调函数:编写用户业务逻辑的地方

七、一句话总结

STM32 外部中断的本质是:
硬件检测 → NVIC 仲裁 → CPU 跳转 → 清标志 → 执行回调函数。

posted @ 2026-01-24 21:37  wind_one  阅读(0)  评论(0)    收藏  举报