STM32嵌入式中断体系全解析:从核心原理到串口/定时器中断实战
STM32中断体系解析与实战指南 本文系统讲解了STM32中断技术的核心原理和实战应用。首先介绍了中断的基本概念、执行流程和关键要素(中断源、信号、寄存器),并对比了异常与中断的区别。重点分析了STM32的两大中断控制器:EXTI(管理GPIO外部中断)和NVIC(负责全局中断优先级和嵌套)。通过串口中断和定时器中断的实战案例,详细展示了HAL库配置方法、非阻塞通信实现和回调函数使用技巧。文章还总
STM32嵌入式中断体系全解析:从核心原理到串口/定时器中断实战
前言
中断是嵌入式开发中实现实时性的核心技术,尤其是在STM32系列芯片开发中,中断体系贯穿串口通信、定时器计时、外部事件响应等关键场景。本文基于实战学习笔记,系统梳理STM32中断的核心原理、关键控制器、实战应用及编程注意事项,覆盖面试高频考点,助力开发者吃透中断技术。
一、中断核心基础(面试高频)
定义:中断是计算机系统中处理紧急事件的机制,当需要主机干预时,系统暂停当前程序转而执行中断服务程序,处理完成后恢复原程序运行。
1.1 中断核心要素与价值
- 核心要素:中断源(触发中断的信号来源)、中断信号;
- 核心价值:
- 提高计算机(单片机)系统效率。
- 维持系统可靠正常工作。
- 实现任务的实时响应,确保关键操作在规定时间内被执行;
- 关键寄存器:
- PC(程序计数器):存储下一条要执行指令的地址;
- SP(栈指针寄存器):存储栈顶地址,栈遵循“先进后出”原则;
- LR(链接寄存器):等效于PC,关联中断返回地址;
- XPSR:包含运算过程的状态变量(NZCV)。
1.2 中断执行流程(必背)
- 中断源触发中断信号;
- 硬件自动保护现场(将PC、寄存器等核心数据压栈);
- 执行中断服务程序(ISR);
- 恢复现场(将栈中数据出栈,还原原程序运行状态);
- 回到原程序继续执行。

1.3 关键概念区分
| 对比维度 | 详情说明 |
|---|---|
| 异常 vs 中断(面试题) | 异常是中断的子集(内核层面的中断); 异常:内核内部触发(如指令错误、系统调用); 普通中断:片上外设、外部硬件触发 |
| Linux vs RTOS 中断实时性 | Linux:多任务并行但实时性差,单核下低优先级任务可能被“饿死”; RTOS:核心优势是强实时性,保证任务在规定时间内响应/完成 |
| Linux(OS)多任务操作系统与RTOS(实时操作系统)的区别 (面试题) | 有软件与硬件上的区别。 硬件上:Linux为多核,“多个大脑”;而单片机mcu是单核,需要用RTOS才能实现近似于多任务并发的功能。 |
1.4 其他概念
按触发方式分为硬件中断和软件中断。
向量中断技术、IRQ
二、STM32中断核心控制器
STM32的中断管理依赖EXTI和NVIC两大核心控制器,二者协同完成中断的触发、优先级管理与执行。
按管理区域分:有片内中断(异常中断(内核里)、外设中断)、片外中断(外部中断),关系图如下:

2.1 EXTI(外部中断控制器)
EXTI专注于GPIO外部中断的管理,核心特性如下:
-
核心功能:管理外部中断的触发逻辑;
-
关键细节:
-
内置施密特触发器,用于判定高低电平(0/1);
-
触发方式:常用上升沿/下降沿触发,电平触发极少使用;
-
中断线规则:PA0~PA15对应16条中断线,同编号引脚(如PA0、PB0)共用一条中断线,无法同时使用;
-
选择器机制:从16条中断线中选择1条作为有效中断线。



-
2.2 NVIC(嵌套向量中断控制器)
NVIC是内核级中断控制器,负责全局中断的统筹管理:
- 核心功能:
- 中断管理功能:中断使能/禁用、中断优先级配置;
- 中断向量表:管理关联中断服务程序的地址;
- 中断嵌套:高优先级中断可打断低优先级中断,多中断同时触发时优先执行高优先级。
三、串口中断实战(HAL库)
串口通信是嵌入式开发的基础场景,串口中断(内部中断,无需配置EXTI)是实现非阻塞通信的关键。
3.1 串口中断配置要点(CubeMX)
- 串口属于内部中断,无需配置EXTI(EXTI仅管理GPIO外部中断);
- 核心配置项:串口参数(波特率、数据位、停止位等)、GPIO引脚、中断优先级与使能。
3.2 核心代码实现
(1)串口初始化+中断使能
// 串口参数初始化
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;//8bit数据位
huart1.Init.StopBits = UART_STOPBITS_1;//1个停止位
huart1.Init.Parity = UART_PARITY_NONE;//无奇偶校验
huart1.Init.Mode = UART_MODE_TX_RX;//收发模式
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;//无硬件流控
huart1.Init.OverSampling = UART_OVERSAMPLING_16;//16倍过采样
if (HAL_UART_Init(&huart1) != HAL_OK)//初始化校验
{
Error_Handler();//初始化失败进入错误处理
}
}
// GPIO+中断配置
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
__HAL_RCC_USART1_CLK_ENABLE();//串口使能
__HAL_RCC_GPIOA_CLK_ENABLE();//GPIOA时钟使能
// PA9(TX)、PA10(RX)配置
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;//收发引脚
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;//收发均是复用推挽输出(建议接收配置为浮空/上拉输入)
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;//高速传输
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;//开启复用功能
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 中断优先级配置+使能
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);//设置中断优先级
HAL_NVIC_EnableIRQ(USART1_IRQn);//使能中断
}
}
(2)非阻塞发送与回调函数
// 非阻塞发送函数:启动中断驱动的UART发送
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
{
if (huart->gState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U)) return HAL_ERROR;
huart->pTxBuffPtr = pData;
huart->TxXferSize = Size;
huart->TxXferCount = Size;
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_BUSY_TX;
__HAL_UART_ENABLE_IT(huart, UART_IT_TXE); // 使能TXE中断
/*
程序中也可以直接发送接着使能中断
HAL_UART_Transmit();
__HAL_UART_ENABLE_IT(huart, UART_IT_TXE);
*/
return HAL_OK;
}
return HAL_BUSY;
}
// 发送完成回调函数(弱函数,可重写)
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART1)//判断串口号
{
// 自定义逻辑:如计数、触发下一次发送等
}
}
3.3 串口中断注意事项
- 串口发送完成后会自动关闭中断,需手动重新使能;
HAL_UART_Transmit_IT为非阻塞函数,调用后立即返回,实际发送由中断逐字节完成;- 接收端建议将GPIO配置为浮空/上拉输入(而非复用推挽)。
四、定时器中断实战
定时器中断是实现精准计时、周期性任务的核心手段,STM32中主要包含SysTick(内核定时器)和TIM(片上外设定时器)两类。
4.1 SysTick(滴答定时器)
- 归属:Cortex-M4内核,24位递减定时器;
- 作用:产生1ms时基(默认),为RTOS提供“心跳”,也用于基础计时(如
HAL_Delay); HAL_Delay实现原理:
__weak void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
// 防0操作:保证Delay=0时也有最小延时
if (wait < HAL_MAX_DELAY) wait += (uint32_t)(uwTickFreq);
while((HAL_GetTick() - tickstart) < wait) {}
}
- 配置链路:
main()→HAL_Init()→HAL_InitTick()→HAL_SYSTICK_Config()。
4.2 TIM定时器(片上外设)
- 分类:高级定时器、通用定时器、基本定时器(按功能复杂度划分);
- 关键参数:16位计数器(0~65535)、预分频因子(PSC)、自动重装载值(ARR);
- 实战示例:1s定时中断+串口上报
- CubeMX配置:设置PSC和ARR实现1s定时,开启NVIC中断使能;
- 代码实现:
// 开启定时器 HAL_TIM_Base_Start_IT(&htim2); // 重写定时器中断回调函数 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM2) { // 1s触发一次,串口发送“我来了” HAL_UART_Transmit_IT(&huart1, (uint8_t*)"我来了", 5); } }
五、中断编程关键注意事项
5.1 关键字与数据类型
volatile:防止编译器优化,中断/定时器相关变量必须添加,确保每次读取都从内存获取;- 枚举类型:系统库常用
U/UL(如1U、2UL),减少CPU类型判断开销,提升效率:typedef enum { A = 1U, // 无符号1 B = 2UL, // 无符号长整型 C = B, // 继承B的值 D // 自动为前值+1(3) } Interrupt_State;
5.2 硬件与配置细节
- 中断线复用:如TIM1/TIM10共用一条中断线,需注意优先级冲突;
- TIM定时器总线挂载:分属APB1(低速)、APB2(高速),需参考芯片手册;
- 防御性编程:函数带返回值(便于错误追溯),串口通信需增加帧头/帧尾/校验(如和校验)。
5.3 回调函数设计
- HAL库中中断回调多为弱函数(
__weak),需在用户代码中重写; - EXTI中断可能共用回调函数,需在函数内判断触发引脚(如PA0/PB0)。
六、总结
中断是STM32嵌入式开发的核心,掌握中断体系需从三层入手:
- 原理层:吃透中断流程、异常/中断区分、RTOS实时性等基础概念(面试高频);
- 控制器层:理解EXTI(外部中断)和NVIC(内核中断)的分工与协同;
- 实战层:结合串口、定时器中断实战,掌握HAL库中断函数、回调重写、优先级配置等细节。
同时,编程中需注意volatile、防御性编程、中断嵌套等细节,才能保证中断程序的稳定性和实时性。
拓展思考(进阶方向)
- 串口硬件流控的应用场景与配置;
- EXTI中断线复用的解决方案;
- SysTick寄存器(CTRL/LOAD/VAL)的底层配置;
控制器层:理解EXTI(外部中断)和NVIC(内核中断)的分工与协同; - 实战层:结合串口、定时器中断实战,掌握HAL库中断函数、回调重写、优先级配置等细节。
更多推荐
所有评论(0)