4. 外部中断
任务说明
本案例目标:在MCU上配置一个GPIO引脚为外部中断输入,连接一个按键,当按键按下时触发下降沿中断,在中断服务函数中翻转一个LED的亮灭状态。通过该案例掌握外部中断的初始化流程、中断服务函数编写方法以及中断触发条件的验证方式。
硬件连接
按键一端接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文件后烧录到开发板。
测试步骤:
- 上电后观察LED应为熄灭状态(PC13输出高电平)。
- 按下按键并松开,观察LED状态是否翻转(灭→亮)。
- 再次按下并松开,LED应再次翻转(亮→灭)。
判定标准:每次按下并松开按键,LED状态翻转一次。若LED状态不变化,检查按键接线是否正确、PA0是否确实被拉低,以及中断是否被正确触发(可在回调中设置断点调试)。
注意事项:按键按下时可能产生机械抖动,导致一次按下触发多次中断。本案例为演示最小实现,未做消抖处理。若需消抖,可在回调中加入延时或使用定时器消抖,但这不是本案例的必要内容。