3. 外部中断控制LED
任务目标
使用STM32微控制器(以STM32F103系列为例),通过按键触发外部中断,在中断回调函数中翻转LED的亮灭状态。本案例聚焦于外部中断线的配置流程、中断优先级设置以及HAL库回调函数的实现机制。
硬件连接与前置条件
- 按键PA0连接至GND(按下为低电平),外部中断线0
- LED接PC13(正极接PC13,负极经限流电阻接GND)
- 使用STM32CubeMX生成初始化代码,或手动配置以下GPIO与NVIC
- 开发环境:STM32CubeIDE或Keil MDK + HAL库
核心实现
以下代码基于STM32CubeMX生成的工程,在用户代码区添加中断回调与LED翻转逻辑。PA0配置为上拉输入,下降沿触发外部中断;PC13配置为推挽输出。
/* main.c - 用户代码区(USER CODE BEGIN/END之间) */
/* 在main函数中,MX_GPIO_Init()之后添加: */
HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0); /* 设置抢占优先级为2,子优先级为0 */
HAL_NVIC_EnableIRQ(EXTI0_IRQn); /* 使能EXTI0中断 */
/* 中断服务函数 - 放在stm32f1xx_it.c中 */
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
/* 回调函数 - 放在main.c用户代码区 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_0)
{
/* 按键按下(下降沿触发),翻转LED状态 */
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
}
}
/* GPIO初始化 - CubeMX生成的MX_GPIO_Init()中关键配置 */
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* 使能时钟 */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/* PC13 - LED输出 */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* PA0 - 按键输入,上拉,下降沿触发 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
中断优先级说明
STM32F103使用NVIC中断控制器,优先级分为抢占优先级和子优先级。通过HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0)设置抢占优先级为2、子优先级为0。数值越小优先级越高。若系统中存在多个中断,需根据实时性要求分配优先级。本例中仅使用一个外部中断,优先级设置主要演示API用法。
运行与验证
- 编译并烧录代码至STM32开发板
- 上电后LED初始为熄灭状态(PC13输出低电平)
- 每次按下按键PA0(按下并释放),LED状态应翻转一次
- 使用调试器在回调函数处设置断点,按下按键可观察到程序进入中断回调
通过条件:每按一次按键,LED亮灭状态切换一次,且无抖动导致的多次翻转(若出现抖动,需在硬件上加RC滤波或在软件中做消抖处理)。
常见问题
- 按键无响应:检查PA0是否配置为上拉输入,按键另一端是否接GND;确认NVIC已使能
- LED状态翻转异常:检查PC13引脚连接是否正确,部分开发板LED低电平点亮,需调整初始电平逻辑
- 中断误触发:机械按键存在抖动,可在回调中加10~20ms延时消抖,或使用定时器辅助消抖