抢占优先级和响应优先级
值越小优先级越高,抢占优先级高就可以的打断抢占优先级低的;但同一个抢占优先级,高响应优先级并不能打断低响应优先级;当然中断同时发生的响应优先级高的先执行。简单理解为: 抢占优先级能控制中断的绝对打断,同级抢断优先级没有打断的功能
分组配置是在寄存器SCB->AIRCR中配置:
SCB: System Control Block; AIRCR : Application Interrupt / Reset Control Register
; 常用寄存器解释
typedef struct
{
__IOM uint32_t ISER[8U];
uint32_t RESERVED0[24U];
__IOM uint32_t ICER[8U];
uint32_t RSERVED1[24U];
__IOM uint32_t ISPR[8U];
uint32_t RESERVED2[24U];
__IOM uint32_t ICPR[8U];
uint32_t RESERVED3[24U];
__IOM uint32_t IABR[8U];
uint32_t RESERVED4[56U];
__IOM uint8_t IP[240U];
uint32_t RESERVED5[644U];
__OM uint32_t STIR;
} NVIC_Type;
ISER[8]
ISER 全称是:Interrupt Set-Enable Registers,这是一个中断使能寄存器组。CM3 内核支持 256 个中断,这里用 8 个 32 位寄存器来控制(32 _8=256),但103系列的芯片只有60个所以只需要两个32位中断(2_32=64),也就是ISER[0]和ISER[1]
ICER
ICER[8]:全称是:Interrupt Clear-Enable Registers,是一个中断除能寄存器组。该寄存器组与 ISER 的作用恰好相反,是用来清除某个中断的使能的。
ISPR
ISPR[8]:全称是:Interrupt Set-Pending Registers,是一个中断挂起控制寄存器组。每个位对应的中断和 ISER 是一样的。
ICPR
ICPR[8]:全称是:Interrupt Clear-Pending Registers,是一个中断解挂控制寄存器组。其作用与 ISPR 相反,对应位也和 ISER 是一样的。
IABR
全称是:Interrupt Active Bit Registers,是一个中断激活标志位寄存器组。对应位所代表的中断和 ISER 一样,如果为 1,则表示该位所对应的中断正在被执行。这是一个 只读寄存器, 通过它可以知道当前在执行的中断是哪一个。
IP
IP[240]:全称是:Interrupt Priority Registers,是一个中断优先级控制的寄存器组。这个寄存器组相当重要!STM32 的中断分组与这个寄存器组密切相关。IP 寄存器组由 240 个 8bit 的寄存器组成,每个可屏蔽中断占用 8bit。想要设置某个序号的中断,最终是通过修改IP中某个序号8位的值。例如IP[37]=
程序设置中断过程
typedef struct
{
uint8_t NVIC_IRQChannel;
uint8_t NVIC_IRQChannelPreemptionPriority;
uint8_t NVIC_IRQChannelSubPriority;
FunctionalState NVIC_IRQChannelCmd;
} NVIC_InitTypeDef;
系统运行后先设置中断优先级分组。调用函数:
1.void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
整个系统执行过程中,只设置一次中断分组。
针对每个中断,设置对应的抢占优先级和响应优先级:
2.void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
③ 如果需要挂起/解挂,查看中断当前激活状态,分别调用相关函数即可。
库函数中的中断初始化函数分析
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));
assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
{
tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
tmppre = (0x4 - tmppriority);
tmpsub = tmpsub >> tmppriority;
tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
tmppriority = tmppriority << 0x04;
NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
else
{
NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
}
中断函数的命名,不能随意命名
参考:https://www.cnblogs.com/zzdbullet/p/9949742.html,https://blog.csdn.net/c_kongfei/article/details/124724844
在keil建立工程时,都会有一个启动文件,是对应每个硬件的启动文件例如 startup_stm32f10x_hd.s,这是一个汇编语言的文件。其中已经定义了不同中断触发后进入那个函数执行。其中很多以IRQ(Interupt ReQuest)有关的DCD定义, DCD表示定义一个字的空间(32位bit’),就是对应中断的执行函数名称。Cortex-M3使用了”向量表查表机制”。
Original: https://blog.csdn.net/weixin_43794311/article/details/128420515
Author: MAR-Sky
Title: STM32中断使用NVIC
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/793233/
转载文章受原作者版权保护。转载请注明原作者出处!