HAL 中断
三明治
不是 所有 HAL 库外设中断都 100 % 遵循同一套“三明治”模板,但 90 % 以上 都符合下面这套 “3 层套路” 的变体:
- 向量入口(IRQHandler)
- HAL 通用处理函数(HAL_XXX_IRQHandler)
- 用户弱定义回调函数(HAL_XXX_Callback)
只要记住 “先看 stm32f1xx_it.c 模板,再查 HAL 手册有无 *_IRQHandler 和 *_Callback”,基本不会踩坑。
典型“三明治”成员(完全一致)
外设 | IRQHandler | 通用处理 | 常用回调 |
---|---|---|---|
TIMx | TIMx_IRQHandler | HAL_TIM_IRQHandler | HAL_TIM_PeriodElapsedCallback |
USARTx | USARTx_IRQHandler | HAL_UART_IRQHandler | HAL_UART_RxCpltCallback / TxCpltCallback |
SPIx | SPIx_IRQHandler | HAL_SPI_IRQHandler | HAL_SPI_TxRxCpltCallback |
ADC | ADCx_IRQHandler | HAL_ADC_IRQHandler | HAL_ADC_ConvCpltCallback |
DMA | DMAx_Streamx_IRQHandler | HAL_DMA_IRQHandler | HAL_DMA_XferCpltCallback |
稍微不同但仍“三件套”
- EXTI:
EXTIx_IRQHandler
→HAL_GPIO_EXTI_IRQHandler
→HAL_GPIO_EXTI_Callback
- RTC Alarm:
RTC_IRQHandler
→HAL_RTC_AlarmIRQHandler
→HAL_RTC_AlarmAEventCallback
例外情况(不按套路)
外设/场景 | 为什么不一样 |
---|---|
SysTick | 直接进 SysTick_Handler() ,没有 HAL_SysTick_IRQHandler ,回调是 HAL_IncTick() |
独立看门狗 IWDG | 只有 IWDG_IRQHandler ,HAL 没有专门处理函数,需要自己清 SR |
部分外设早期库 | 如 USB FS Device 旧库使用 USB_LP_CAN1_RX0_IRQHandler ,但新版 HAL 统一为 HAL_PCD_IRQHandler |
示例
1️⃣ 第 1 层:中断向量入口
在 stm32f1xx_it.c
里添加(CubeMX 已生成框架,只需填一行):
void TIM6_IRQHandler(void)
{HAL_TIM_IRQHandler(&htim6); /* ← 把中断交给 HAL 处理 */
}
2️⃣ 第 2 层:HAL 的通用处理
HAL_TIM_IRQHandler(&htim6)
会自动:
- 判断是哪一个中断源(Update、Capture、Compare…)
- 清掉对应的中断标志位
- 调用对应的 用户回调函数
3️⃣ 第 3 层:用户回调函数
在任意 .c
文件里实现(名字必须一模一样):
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if (htim->Instance == TIM6) /* 确认是 TIM6 产生的中断 */{/* 这里写你的业务代码 */HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); /* 例如翻转 LED */}
}