4、stm32异常与中断

1、异常和中断的概念

bash 复制代码
在 ARM Cortex-M 架构中,异常(Exception) 是指导致处理器暂停当前正常程序流、转而执行特定处理程序
(异常服务例程,Exception Handler)的事件。异常分为两类:

(1)系统异常(System Exceptions):由处理器内核产生,用于处理内部事件,如复位(Reset)、
	不可屏蔽中断(NMI)、硬故障(HardFault)、内存管理故障(MemManage)、总线故障(BusFault)、
	使用故障(UsageFault)、系统调用(SVC)、PendSV、SysTick 等。
(2)外部中断(Interrupts):由片上外设(如 EXTI、TIM、USART、ADC 等)或外部引脚触发,属于可屏蔽中断,
	通过 NVIC(Nested Vectored Interrupt Controller)进行管理。

2、中断响应与中断优先级NVIC

bash 复制代码
(1)中断响应流程
当中断条件满足且未被屏蔽时,处理器执行以下操作:
	完成当前指令(部分指令如 multi-cycle load/store 会提前终止);
	自动保存上下文:将 R0--R3、R12、LR、PC 和 xPSR 共 8 个寄存器压入当前栈(MSP 或 PSP);
	根据中断号从向量表中取出对应异常服务例程(ISR)入口地址;
跳转至 ISR 执行;
	ISR 执行完毕后,执行异常返回指令(如 BX LR),硬件自动恢复上下文并返回原程序断点继续执行。
	该过程由硬件自动完成,具有低延迟、高确定性的特点。

(2)中断优先级机制
	Cortex-M 处理器通过 NVIC(Nested Vectored Interrupt Controller) 实现可嵌套、可配置的中断优先级管理。
	每个异常/中断具有一个 8 位优先级字段,但实际可用位数由芯片实现决定(如 STM32F1 为 4 位有效)。
优先级分为两个逻辑部分:
	抢占优先级(Preemption Priority):决定是否允许高优先级中断嵌套打断正在执行的低优先级 ISR。数值越小,优先级越高。
	子优先级(Subpriority / Response Priority):当多个中断具有相同抢占优先级且同时挂起时,
	用于确定响应顺序,但不支持相互嵌套。
中断挂起概念:
	外设已经"举手申请"了中断(比如按键按下、定时器溢出);
	但因为某些原因(如当前在执行更高优先级的中断,或全局中断被关闭),CPU 还没来得及响应;
	此时,该中断就被 标记为"挂起",等待后续处理。
整体按照:抢占优先级>子优先级>IRQ编号

3、EXIT扩展中断与事件控制器

bash 复制代码
(1)事件的概念
	当检测到触发信号时,直接告知其他外设进行事件的响应而不经过中断
(2)中断
	中断则包括中断响应与事件触发,EXIT检测到触发信号,向NVIC报告中断进行裁决,之后进行事件响应

4、EXIT与NVIC搭配使用

bash 复制代码
(1)当STM32的EXTI监测到GPIO或内部外设满足配置的边沿或电平触发条件,且其中断屏蔽位已使能时
(2)EXTI硬件会自动置位挂起寄存器,并向NVIC发出中断请求。
(3)NVIC根据该中断的优先级、当前CPU执行状态及屏蔽标志进行仲裁:若优先级足够高且未被屏蔽,则在当前指令完成后触发中断响应。
(4)Cortex-M内核自动保存上下文、从向量表获取对应ISR地址,并跳转执行。
(5)用户必须在ISR中手动清除EXTI_PR挂起位(写1清零),否则将导致重复进入中断。
(6)执行完毕后,通过异常返回指令自动恢复上下文,继续主程序。
(7)若中断发生时CPU正处理更高优先级任务,该中断将保持挂起状态,待条件满足后仍会被可靠处理,确保不丢失。

5、代码使用

bash 复制代码
STM32Cube中配置:
(1)RCC使用外部晶振,CLOCK中选择PLL,频率设置72M
(2)SYS中配置程序使用Serial wire
(3)GPIO中断事件的配置(上升、下降)
(4)NVIC优先级分组,中断线使能

查看外部中断/事件控制器章节获取不同引脚对应的EXIT线,

通过PA0按键控制PB0的亮灭

bash 复制代码
GPIO配置:
void MX_GPIO_Init(void)
{

	  GPIO_InitTypeDef GPIO_InitStruct = {0};
	
	  /* GPIO Ports Clock Enable */
	  __HAL_RCC_GPIOB_CLK_ENABLE();
	  __HAL_RCC_GPIOA_CLK_ENABLE();
	
	  
	  /*配置按键PA0中断 */
	  GPIO_InitStruct.Pin = GPIO_PIN_0;
	  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
	  GPIO_InitStruct.Pull = GPIO_NOPULL;
	  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	  HAL_NVIC_SetPriority(EXTI0_IRQn, 12, 0);
	  HAL_NVIC_EnableIRQ(EXTI0_IRQn);
	  
	  // 配置LED灯PB0
	  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	  GPIO_InitStruct.Pull = GPIO_NOPULL;
	  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
	  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
  
}

中断程序配置:

bash 复制代码
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_0)  // 判断是 PA0 触发(EXTI0)
    {
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); // PB0 = 低电平
		HAL_Delay(500);
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); 
    }
}
bash 复制代码
个人总结:
对于STM32有多条EXTI总线,都是调用HAL_GPIO_EXTI_Callback触发中断,在回调内部通过GPIO判断属于哪条总线。
对于同一总线则根据优先级
相关推荐
BreezeJuvenile3 小时前
通用定时器_测量PWM方波的周期和占空比案例
stm32·单片机·学习·通用定时器·pwm输入·测量占空比
进阶的猪3 小时前
stm32f407 RCC时钟配置
stm32·单片机·嵌入式硬件
ArrebolJiuZhou4 小时前
02arm指令集(一)——LDR,MOV,STR的使用
linux·网络·单片机
小刘爱玩单片机5 小时前
【stm32简单外设篇】- 三色LED
c语言·stm32·单片机·嵌入式硬件
d111111111d5 小时前
STM32平衡车测试,定时中断读取速度
笔记·stm32·单片机·嵌入式硬件·学习·模块测试
Dillon Dong6 小时前
从C到Simulink:什么是MATLAB_MEX_FILE 宏,如何阻挡STM32 HAL 头文件
c语言·stm32·matlab
Darken036 小时前
基于STM32---编码器测速(利用GPIO模拟脉冲信号)
人工智能·stm32·串口助手·gpio模拟编码器
电子工程师-C518 小时前
基于51单片机的交通灯远程控制系统
单片机·嵌入式硬件·51单片机
国科安芯8 小时前
低轨卫星边缘计算节点的抗辐照MCU选型分析
人工智能·单片机·嵌入式硬件·架构·边缘计算·安全威胁分析·安全性测试