STM32中断优先级原理及应用

STM32中断优先级配置详解

在STM32微控制器中,中断优先级的配置对于系统的稳定性和可靠性至关重要。正确地配置中断优先级可以确保重要中断的及时响应,提高系统的性能。本文将介绍STM32中断优先级配置的方法,帮助初学者轻松上手。

1. 中断优先级的原理

中断优先级分为抢占优先级子优先级两部分,用于确定中断的响应顺序和执行顺序。抢占优先级用于确定中断的响应优先级,而子优先级用于确定中断的实际执行优先级。当多个中断同时触发时,系统会优先处理抢占优先级较高的中断,而在相同抢占优先级的情况下,会根据子优先级来确定中断的执行顺序。

NVIC的中断优先级由优先级寄存器NVIC_IPRx的4位决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队

STM32中断优先级原理及应用_第1张图片

比如如果选择分组1,那么抢占优先级只能选择0,1二个值,响应优先级只能在0-7中取值。值越小优先级越高。简单的说,就是设置中断优先级时先设置分组,然后设置抢占优先级和响应优先级。

2. 配置方法

以下是配置中断优先级的步骤:

步骤 1:选择中断优先级分组

优先级设置的位数和分配方式由中断优先级分组决定,这是通过SCB_AIRCR寄存器来配置的。

通过设置SCB_AIRCR寄存器的10-8位来确定中断的优先级分组。

STM32中断优先级原理及应用_第2张图片

 程序中设置优先级的调用函数

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

 代码中对分组的定义:

#define NVIC_PriorityGroup_0         ((uint32_t)0x700) /*!< 0 bits for pre-emption priority
                                                            4 bits for subpriority */
#define NVIC_PriorityGroup_1         ((uint32_t)0x600) /*!< 1 bits for pre-emption priority
                                                            3 bits for subpriority */
#define NVIC_PriorityGroup_2         ((uint32_t)0x500) /*!< 2 bits for pre-emption priority
                                                            2 bits for subpriority */
#define NVIC_PriorityGroup_3         ((uint32_t)0x400) /*!< 3 bits for pre-emption priority
                                                            1 bits for subpriority */
#define NVIC_PriorityGroup_4         ((uint32_t)0x300) /*!< 4 bits for pre-emption priority
                                                            0 bits for subpriority */
步骤 2:确定中断的优先级

根据中断的重要性和响应时序,确定中断的抢占优先级和响应优先级。一般情况下,抢占优先级用于区分不同中断的响应顺序,而响应优先级则用于同一抢占优先级下的中断执行顺序。

NVIC_IPRx寄存器是一组32位的寄存器,其中的每个8位对应一个中断优先级。例如,NVIC_IPR0寄存器的高4位(bit 7-4)对应中断0的抢占优先级和响应优先级,低4位(bit 3-0)是无效位。根据分组来解释每个中断的抢占优先级和响应优先级。

STM32中断优先级原理及应用_第3张图片

	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //响应优先级

3.完整中断程序

#include "stm32f4xx.h"

void EXTI0_IRQHandler(void)
{
    // 中断处理代码
    // ...
    EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志位
}

void EXTI_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    EXTI_InitTypeDef EXTI_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;

    // 使能外部中断时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

    // 配置GPIO引脚
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    // 配置外部中断线
    EXTI_ClearITPendingBit(EXTI_Line0);
    EXTI_InitStruct.EXTI_Line = EXTI_Line0;
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStruct);

    // 配置中断优先级
    NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01; // 抢占优先级
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01; // 子优先级
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
}

int main(void)
{
    // 初始化外部中断
    EXTI_Config();

    while (1)
    {
        // 主循环代码
        // ...
    }
}

你可能感兴趣的:(STM32,stm32,单片机,嵌入式硬件,中断优先级)