[百问网 7Day物联网智能家居实战训练]Day4 中断
一般流程:
正常情况下,微处理器根据代码内容,按顺序执行指令。
中断流程:
行过程中,如果遇到其它紧急的事件需要处理,则先暂停当前任务,执行紧急事件,待紧急事件处理完后,再恢复到刚才暂停的地方继续执行。
紧急事件就叫做中断或异常
|
异常 |
CPU内部产生的紧急事件 |
|
中断 |
来自CPU外部的片上外设产生的紧急事件 |

中断种类:

中断优先级:

中断和复位控制寄存器的Bits[10:8]PRIGROUP)将优先级分组。
分组决定可编程中断的PRI_n的Bits[7:0]的高低位分配,从而影响抢占优先和子优先级的级数

|
优先级分组 |
抢占优先级范围 |
子优先级范围 |
|
0~7 |
0~32 |
0~8 |
可编程中断,需指定抢占优先级和子优先级。
抢占优先级:决定是否可以产生中断嵌套,子优先级决定中断响应顺序,
两种优先级一样:则看中断在中断异常表中的位置,越靠前越先响应。
抢占优先级高(值小):中断可以中断抢占优先级低(值大)的中断处理函数,进而执行高优先级的中断处理函数,执行完毕后再继续执行被中断的低优先级的处理函数。
抢占优先级相同:即这两个中断将没有嵌套关系。当一个中断到来后,若CPU正在处理另一个中断,则这个后到来的中断就要等到前一个中断处理函数处理完毕后才能被处理,当这两个中断同时到达,则中断控制器会根据它们的子优先级决定先处理哪个。
两个中断的优先级都设置为一样:
谁先触发,就谁先执行;
同时触发,根据中断异常表的位置(靠前)来决定谁先执行。
HAL库启动文件“startup_stm32f103xb.s”,可以看到定义的中断向量表
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_IRQHandler ; Tamper
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line 0
DCD EXTI1_IRQHandler ; EXTI Line 1
DCD EXTI2_IRQHandler ; EXTI Line 2
DCD EXTI3_IRQHandler ; EXTI Line 3
DCD EXTI4_IRQHandler ; EXTI Line 4
DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1
DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2
DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3
DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4
DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5
DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6
DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7
DCD ADC1_2_IRQHandler ; ADC1_2
DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX
DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0
DCD CAN1_RX1_IRQHandler ; CAN1 RX1
DCD CAN1_SCE_IRQHandler ; CAN1 SCE
DCD EXTI9_5_IRQHandler ; EXTI Line 9..5
DCD TIM1_BRK_IRQHandler ; TIM1 Break
DCD TIM1_UP_IRQHandler ; TIM1 Update
DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3
DCD EXTI15_10_IRQHandler ; EXTI Line 15..10
DCD RTC_Alarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
__Vectors_End
可以看到第2~16行,为10个系统异常,剩下的全为外部中断。同时这里还定义了所有的中断处理函数名字,当外设产生中断时,则跳到中断向量表中对应中断处理函数位置,比如发生RTC中断事件,则跳到22行
执行“RTC_IRQHandler()”函数内容。STM32F103的异常和中断,基于Cortex-M3修改而来,前面的系统异常部分几乎没有变化,外部中断则
对应不同的外设。
同样,STM32F103也继承了Cortex-M3的中断优先级规则,因为中断少了很多,中断优先级也用不了那么多,只使用了PRI_n的Bits[7:0]中的Bits[7:4]设置优先级,因此优先级分组

可见STM32F103系列有16级可编程优先级,STM32F103不使用PRIGROUP来命名分组,而采用
NVIC_PRIORITYGROUP_x 的 方 式 命 名 , 即 NVIC_PRIORITYGROUP_0 对 应 PRIGROUP 为 7 , 在
“stm32f1xx_hal_cortex.h”有相关定义
#define NVIC_PRIORITYGROUP_0 0x00000007U /*!< 0 bits for pre-emption priority
4 bits for subpriority */
#define NVIC_PRIORITYGROUP_1 0x00000006U /*!< 1 bits for pre-emption priority
3 bits for subpriority */
#define NVIC_PRIORITYGROUP_2 0x00000005U /*!< 2 bits for pre-emption priority
2 bits for subpriority */
#define NVIC_PRIORITYGROUP_3 0x00000004U /*!< 3 bits for pre-emption priority
1 bits for subpriority */
#define NVIC_PRIORITYGROUP_4 0x00000003U /*!< 4 bits for pre-emption priority
0 bits for subpriority */
中断优先级分组:只会设置一次,它针对的是系统中所有的中断。后续设置某个中断的中断优先级
时,只需要在这个组规定的抢占优先级数和子优先级级数范围内分配优先级级数。后续代码中,不应该再修
改中断优先级分组,否则导致中断顺序不按预期触发。将设置中断优先级分组放在了“HAL_Init()”里,如代码段 10.2.3 的第5行,调用“HAL_NVIC_SetPriorityGrouping()”函数设置中断优先级.
HAL_StatusTypeDef HAL_Init(void)
{
...
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
...
}
这里默认设置的优先级分组为NVIC_PRIORITYGROUP_4,则后续使用“HAL_NVIC_SetPriority()”函
数设置优先级时,抢占优先级的范围是0~15,子优先级的值只能选择0。
“HAL_NVIC_SetPriority()”函数需要传入三个参数,参数IRQn是中断号,如表 10.2.1 所示的中断号。
后两个是抢占优先级级数和子优先级级数,注意结合中断分组设置范围。
/**
* @brief Sets the priority of an interrupt.
* @param IRQn: External interrupt number.
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xx.h))
* @param PreemptPriority: The preemption priority for the IRQn channel.
* This parameter can be a value between 0 and 15
* A lower priority value indicates a higher priority
* @param SubPriority: the subpriority level for the IRQ channel.
* This parameter can be a value between 0 and 15
* A lower priority value indicates a higher priority.
* @retval None
*/
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
{
uint32_t prioritygroup = 0x00U;
/* Check the parameters */
assert_param(IS_NVIC_SUB_PRIORITY(SubPriority));
assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));
prioritygroup = NVIC_GetPriorityGrouping();
NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority));
}
GPIO中断:

中断优先级分组
根据中断优先级分组,确定抢占优先级级数和子优先级级数。
实现:
1.先使用“HAL_NVIC_SetPriorityGrouping()”函数设置中断优先级分组,
2.再使用“HAL_NVIC_SetPriority()”函数设置不同中断的抢占优先级级数和子优先级级数。
|
中断A,B抢占优先级别 |
中断发生时间 |
执行 |
|
A比B高 |
同时 |
中断A优先执行 |
|
一样 |
同时 |
子优先级高的中断先执行 |
|
A比B高 |
B先发生,随后A发生 |
暂停中断B,先执行中断A,A执行完后,再回来执行中断B,最后执行主程序。【中断嵌套】 |
|
中断A,B抢占优先级别 |
中断A,B子优先级 |
执行 |
|
一样 |
A>B |
中断B先发生,随后A也发生, 中断A将等待中断B执行完后,才会执行中断A。【子终端不能嵌套】 |
|
一样 |
一样 |
两个中断同时发生,那么根 据前面表 10.2.1 顺序,排在前面的先执行。 |

总结中断是否会优先执行依据:首先是抢占先式优先级等级,其次是子优先级等级,只有抢占优先级才
可能出现中断嵌套。



代码初始化


浙公网安备 33010602011771号