4. 外部中断

任务说明

本案例目标:在MCU上配置一个GPIO引脚为外部中断输入,连接一个按键,当按键按下时触发下降沿中断,在中断服务函数中翻转一个LED的亮灭状态。通过该案例掌握外部中断的初始化流程、中断服务函数编写方法以及中断触发条件的验证方式。

硬件连接

MCU STM32F103 PA0 PC13 KEY GND 10kΩ → 3.3V 330Ω LED GND 3.3V EXTI0

按键一端接PA0,另一端接GND,PA0通过10kΩ上拉电阻接3.3V。LED正极通过330Ω限流电阻接PC13,负极接GND。按键未按下时PA0为高电平,按下时PA0被拉低,产生下降沿。

代码实现


#include "stm32f1xx_hal.h"

/* 按键引脚 PA0,LED引脚 PC13 */
#define KEY_PIN       GPIO_PIN_0
#define KEY_PORT      GPIOA
#define LED_PIN       GPIO_PIN_13
#define LED_PORT      GPIOC

void Error_Handler(void);

/* 中断服务函数声明 */
void EXTI0_IRQHandler(void);

int main(void)
{
    HAL_Init();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();

    /* 配置PA0为外部中断输入,下降沿触发 */
    GPIO_InitTypeDef gpio_key = {0};
    gpio_key.Pin   = KEY_PIN;
    gpio_key.Mode  = GPIO_MODE_IT_FALLING;
    gpio_key.Pull  = GPIO_PULLUP;
    HAL_GPIO_Init(KEY_PORT, &gpio_key);

    /* 配置PC13为推挽输出 */
    GPIO_InitTypeDef gpio_led = {0};
    gpio_led.Pin   = LED_PIN;
    gpio_led.Mode  = GPIO_MODE_OUTPUT_PP;
    gpio_led.Pull  = GPIO_NOPULL;
    gpio_led.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(LED_PORT, &gpio_led);

    /* 初始LED灭 */
    HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET);

    /* 配置EXTI0中断优先级并使能 */
    HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0);
    HAL_NVIC_EnableIRQ(EXTI0_IRQn);

    while (1)
    {
        /* 主循环无任务,等待中断 */
    }
}

/* EXTI0中断服务函数:翻转LED */
void EXTI0_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(KEY_PIN);
}

/* HAL库回调函数,在HAL_GPIO_EXTI_IRQHandler中被调用 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == KEY_PIN)
    {
        HAL_GPIO_TogglePin(LED_PORT, LED_PIN);
    }
}

代码说明

代码基于STM32 HAL库。在main中,首先使能GPIOA和GPIOC时钟,然后将PA0配置为GPIO_MODE_IT_FALLING模式(下降沿触发外部中断),并使能内部上拉。PC13配置为推挽输出。中断优先级设为2并使能EXTI0中断。

当按键按下时,PA0从高电平变为低电平,触发EXTI0中断,CPU跳转到EXTI0_IRQHandler。该函数调用HAL库的HAL_GPIO_EXTI_IRQHandler,HAL库在清除中断标志后调用回调函数HAL_GPIO_EXTI_Callback。在回调中判断中断引脚是否为KEY_PIN,若是则翻转LED状态。

验证方法

编译与烧录:使用STM32CubeIDE或Keil MDK创建工程,将上述代码复制到main.c中,编译生成hex文件后烧录到开发板。

测试步骤:

  1. 上电后观察LED应为熄灭状态(PC13输出高电平)。
  2. 按下按键并松开,观察LED状态是否翻转(灭→亮)。
  3. 再次按下并松开,LED应再次翻转(亮→灭)。

判定标准:每次按下并松开按键,LED状态翻转一次。若LED状态不变化,检查按键接线是否正确、PA0是否确实被拉低,以及中断是否被正确触发(可在回调中设置断点调试)。

注意事项:按键按下时可能产生机械抖动,导致一次按下触发多次中断。本案例为演示最小实现,未做消抖处理。若需消抖,可在回调中加入延时或使用定时器消抖,但这不是本案例的必要内容。