STM32关于优先级设定的理解 NVIC_SetPriority()

本文介绍STM32中Systick模块的初始化配置及如何通过NVIC设置中断优先级。重点讲解了NVIC_SetPriority函数的使用方法,并解释了如何计算占先优先级。
Systick模块初始化配置函数(Systick_config)中设定模块中断优先级的函数为:

NVIC_SetPriority((SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);

 

参数SysTick_IRQn为systick基址,这个没什么好说的

 

关键在参数 (1<<__NVIC_PRIO_BITS) - 1);这个参数即占先优先级值,其中—NVIC_PRIO_BITS是stm32.h中的宏定义,库函数默认为4,表示用4位表示占先优先级,因为m3内核只有4位用来表示占先优先级和响应优先级,那么响应优先级就剩下0位了,也就是没有响应优先级之分,

按照上式计算若NVIC_PRIO_BITS为4则占先优先级为15,即最低优先级值

依次可类推,即 (1<<__NVIC_PRIO_BITS) - 1);表示的是可用的最低优先级(1<<4为16,—1为15),将后面那个红色的1改为其他值即可改变此模块占先优先级

<think>我们正在讨论的是GD32微控制器平台上的中断优先级设置函数。在STM32 HAL库中,我们通常使用`HAL_NVIC_SetPriority`函数来设置中断优先级。然而,GD32的库可能有所不同。根据引用[3],我们看到了一个函数`__NVIC_SetPriority`,它是ARM Cortex-M内核提供的标准函数,位于core_cmX.h(X代表内核版本)文件中。在GD32中,我们同样可以使用这个标准函数,因为GD32也是基于ARM Cortex-M内核的。 在GD32的标准外设库(类似于STM32的标准库)或者GD32的HAL库(如果提供的话)中,设置中断优先级的函数通常也是直接调用CMSIS(Cortex Microcontroller Software Interface Standard)提供的函数。具体来说,我们可以使用`NVIC_SetPriority`函数(注意:不是`__NVIC_SetPriority`,因为CMSIS提供了封装好的函数,通常去掉了前面的下划线)。 在CMSIS中,设置中断优先级的标准函数是: ```c void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority); ``` 这个函数有两个参数: - `IRQn`:中断号,定义在芯片特定的头文件中(如gd32f30x.h)。 - `priority`:优先级,具体的数值范围取决于优先级分组设置和优先级位数。 另外,引用[2]提到了优先级分组,在设置中断优先级之前,我们通常需要设置优先级分组。在CMSIS中,设置优先级分组的函数是: ```c void NVIC_SetPriorityGrouping(uint32_t PriorityGroup); ``` 在GD32中,我们可以这样使用: 步骤: 1. 包含必要的头文件,通常是`gd32f30x.h`(根据具体型号而定)和`core_cm4.h`(根据内核而定)。 2. 设置优先级分组(如果需要改变默认分组)。 3. 使用`NVIC_SetPriority`设置具体中断的优先级。 示例代码: ```c #include "gd32f30x.h" #include "core_cm4.h" // 对于Cortex-M4内核,如果是M3则包含core_cm3.h // 设置优先级分组,例如分组2(表示2位抢占优先级,2位子优先级) // 注意:GD32优先级分组与STM32相同,都是使用ARM的NVIC分组方式 NVIC_SetPriorityGrouping(2); // 设置某个中断的优先级,例如EXTI0中断,设置抢占优先级为1,子优先级为2 // 注意:在分组2的情况下,抢占优先级和子优先级各占2位,所以优先级值范围0-3 // 我们需要将抢占优先级和子优先级组合成一个字节,具体方法如下: // 优先级 = (抢占优先级 << (优先级分组中抢占优先级所占的位数)) | 子优先级 // 但是,CMSIS的NVIC_SetPriority函数要求传入的优先级是已经根据分组调整好的数值吗? // 实际上,NVIC_SetPriority函数内部会根据优先级分组自动调整。但是,我们通常使用另一个函数来组合抢占优先级和子优先级: // uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority); // 然后使用NVIC_SetPriority设置。 // 因此,推荐的做法是: uint32_t prioritygroup = NVIC_GetPriorityGrouping(); // 获取当前优先级分组 uint32_t priority = NVIC_EncodePriority(prioritygroup, 1, 2); NVIC_SetPriority(EXTI0_IRQn, priority); // 或者,如果我们已经知道分组,也可以手动计算,但建议使用上述标准方法。 ``` 但是,请注意,在GD32的标准外设库(类似STM32的标准库)中,可能提供了自己的函数。例如,在GD32的标准库中,设置中断优先级的函数可能是: ```c void nvic_priority_group_set(uint32_t nvic_prigroup); void nvic_irq_priority_set(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority); ``` 具体函数名需要参考GD32的标准库文档。然而,由于GD32的库与STM32的库在函数命名上可能相似,我们也可以参考GD32提供的例程。 总结: 1. 在GD32中,如果使用CMSIS,则直接使用`NVIC_SetPriority`函数。 2. 如果使用GD32的标准外设库,则查找类似`nvic_irq_priority_set`的函数(具体以GD32官方库为准)。 因此,对于用户的问题,在GD32的HAL库中,如果存在HAL库,那么它可能提供了与STM32 HAL库类似的函数`HAL_NVIC_SetPriority`。但是,如果GD32的HAL库没有提供这个函数,那么我们可以直接使用CMSIS的`NVIC_SetPriority`函数。 根据GD32的官方资料,GD32的HAL库(如果提供)应该与STM32的HAL库高度兼容。因此,建议检查GD32 HAL库的头文件和库文件,看是否有`HAL_NVIC_SetPriority`函数。如果没有,则使用上述CMSIS函数。 另外,引用[3]中展示的`__NVIC_SetPriority`函数是CMSIS底层函数,一般我们不直接使用,而是使用封装好的`NVIC_SetPriority`。 所以,替代方法: 方法1:使用CMSIS标准函数(推荐) - `NVIC_SetPriorityGrouping` 设置分组 - `NVIC_SetPriority` 设置具体中断优先级 方法2:如果GD32提供了标准外设库,则使用库函数(具体函数名需参考GD32标准外设库手册)。 注意:优先级数值的范围取决于优先级分组和芯片实际支持的优先级位数(例如,GD32F30x支持4位优先级,即16级优先级)。 示例(使用CMSIS): ```c // 设置优先级分组为2(2位抢占优先级,2位子优先级NVIC_SetPriorityGrouping(2); // 设置EXTI0中断的抢占优先级为1,子优先级为2 // 使用NVIC_EncodePriority组合优先级 uint32_t group_priority = 1; // 抢占优先级 uint32_t sub_priority = 2; // 子优先级 uint32_t priority = NVIC_EncodePriority(NVIC_GetPriorityGrouping(), group_priority, sub_priority); NVIC_SetPriority(EXTI0_IRQn, priority); ``` 最后,记得在设置完优先级后,还需要使能中断: ```c NVIC_EnableIRQ(EXTI0_IRQn); ``` 这样,我们就完成了在GD32上设置中断优先级的操作。 相关问题: 1. 如何理解ARM Cortex-M的中断优先级分组? 2. 在GD32中如何使能外部中断? 3. GD32的中断优先级设置与STM32有什么不同? 4. 如何配置GD32的中断向量表?</think>在GD32微控制器平台上,HAL_NVIC_SetPriority函数的等效实现主要基于ARM Cortex-M内核的CMSIS标准接口。以下是具体解决方案: ### 1. GD32中设置中断优先级的核心函数 在GD32开发中,**直接使用CMSIS标准接口**替代HAL_NVIC_SetPriority: ```c #include "gd32f30x.h" // GD32标准库头文件 // 设置中断优先级 void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { // 内核寄存器直接操作 if ((int32_t)IRQn >= 0) { NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & 0xFFUL); } // 系统异常处理 else { SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & 0xFFUL); } } ``` ### 2. 完整使用流程 ```c // 1. 设置优先级分组(4位优先级NVIC_SetPriorityGrouping(0); // 2. 配置具体外设中断优先级 // 示例:配置USART0中断优先级为2 NVIC_SetPriority(USART0_IRQn, 2); // 3. 使能中断 nvic_irq_enable(USART0_IRQn, 0, 0); // GD32专用使能函数 ``` ### 3. 关键技术细节 1. **优先级位宽** GD32的Cortex-M内核通常使用**4位优先级**(通过`__NVIC_PRIO_BITS`定义),优先级范围0-15(数值越低优先级越高) 2. **优先级分组配置** 使用CMSIS标准函数配置分组: ```c void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) { uint32_t reg_value; reg_value = SCB->AIRCR; // 读取寄存器 reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); reg_value = (0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | (PriorityGroup << SCB_AIRCR_PRIGROUP_Pos); SCB->AIRCR = reg_value; } ``` 3. **GD32专用函数** 对于外设中断使能,需使用GD32标准库函数: ```c // 使能中断 void nvic_irq_enable(uint8_t nvic_irq, uint8_t preempt_priority, uint8_t sub_priority) { uint32_t temp_priority = (preempt_priority << (8U - __NVIC_PRIO_BITS)) | sub_priority; NVIC_SetPriority(nvic_irq, temp_priority); NVIC_EnableIRQ(nvic_irq); } ``` ### 4. 与STM32 HAL库的区别 | 功能 | STM32 HAL库 | GD32实现方案 | |--------------|--------------------------|----------------------------| | 优先级设置 | `HAL_NVIC_SetPriority()` | `NVIC_SetPriority()` | | 中断使能 | `HAL_NVIC_EnableIRQ()` | `nvic_irq_enable()` | | 优先级分组 | `HAL_NVIC_SetPriorityGrouping()` | `NVIC_SetPriorityGrouping()` | | 依赖库 | stm32fXxx_hal_cortex.c | CMSIS core_cmX.h | > **重要提示**:GD32优先级数值计算方式与STM32相同,均遵循公式: > $$\text{实际优先级} = \text{priority} \times 2^{(8 - \text{__NVIC_PRIO_BITS})}$$ ### 5. 调试建议 1. 验证优先级配置: ```c uint32_t current_priority = NVIC_GetPriority(USART0_IRQn); printf("USART0当前优先级: %lu\n", current_priority >> (8 - __NVIC_PRIO_BITS)); ``` 2. 检查GD32固件库版本(V1.0.4+开始全面支持CMSIS标准) 3. 确保包含正确的设备头文件: ```c #include "gd32f30x.h" // 设备外设寄存器定义 #include "core_cm4.h" // Cortex-M4内核寄存器 ``` --- ### 相关问题 1. GD32中如何实现中断嵌套? 2. 如何配置GD32的SysTick中断优先级? 3. GD32STM32NVIC配置上有哪些兼容性差异? 4. 如何验证GD32中断优先级配置是否生效?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值