58里面的网站怎么建设,东莞网站设计服务,广州品牌网站建设公司,聊城做企业网站1、简介
STM32(Cortex-M3)中每个中断源都有两级优先级#xff1a;抢占式优先级#xff08;pre-emption priority#xff09;和子优先级#xff08;subpriority#xff09;#xff0c;子优先级也叫响应式优先级。
1.1 抢占式优先级
望文知义#xff0c;就是优先级高的…1、简介
STM32(Cortex-M3)中每个中断源都有两级优先级抢占式优先级pre-emption priority和子优先级subpriority子优先级也叫响应式优先级。
1.1 抢占式优先级
望文知义就是优先级高的可以抢占优先级的中断。
具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应即中断嵌套或者说高抢占式优先级的中断可以嵌套在低抢占式优先级的中断中。
1.2 子优先级响应式优先级
望文知义就是当两个抢占式优先级同时来时先处理响应式优先级高的谁优先级高先响应谁。
当两个中断源的抢占式优先级相同时这两个中断将没有嵌套关系当一个中断到来后如果正在处理另一个中断这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达则中断控制器根据他们的响应优先级高低来决定先处理哪一个如果他们的抢占式优先级和响应优先级都相等则根据他们在中断表中的排位顺序决定先处理哪一个。
总结下便是抢占式优先级响应优先级中断表中的排位顺序其中“”理解为比较的方向。
2、划分优先级
每个中断源都需要被指定这两种优先级如果用一个字节8位表示中断源将这8位划分成两部分用前几位表示抢占式优先级后几位表示响应式优先级可以有有8种分配方式如下
1. 所有8位用于指定响应优先级
2. 最高1位用于指定抢占式优先级最低7位用于指定响应优先级
3. 最高2位用于指定抢占式优先级最低6位用于指定响应优先级
4. 最高3位用于指定抢占式优先级最低5位用于指定响应优先级
5. 最高4位用于指定抢占式优先级最低4位用于指定响应优先级
6. 最高5位用于指定抢占式优先级最低3位用于指定响应优先级
7. 最高6位用于指定抢占式优先级最低2位用于指定响应优先级
8. 最高7位用于指定抢占式优先级最低1位用于指定响应优先级以上便是优先级分组的概念但是Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级因此STM32把指定中断优先级的寄存器位减少到4位这4个寄存器位的分组方式如下
第0组所有4位用于指定响应优先级
第1组最高1位用于指定抢占式优先级最低3位用于指定响应优先级
第2组最高2位用于指定抢占式优先级最低2位用于指定响应优先级
第3组最高3位用于指定抢占式优先级最低1位用于指定响应优先级
第4组所有4位用于指定抢占式优先级3、设置优先级分组模式
在程序初始化阶段使用固件库函数NVIC_PriorityGroupConfig先来对优先级分组模式。 NVIC_PriorityGroupConfig(u32 NVIC_PriorityGroup)函数的参数共有5种
NVIC_PriorityGroup_0 选择第0组
NVIC_PriorityGroup_1 选择第1组
NVIC_PriorityGroup_2 选择第2组
NVIC_PriorityGroup_3 选择第3组
NVIC_PriorityGroup_4 选择第4组源码定义在STM32F10x_FWLib\inc\misc.h中
#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*! 0 bits for pre-emption priority4 bits for subpriority */
#define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*! 1 bits for pre-emption priority3 bits for subpriority */
#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*! 2 bits for pre-emption priority2 bits for subpriority */
#define NVIC_PriorityGroup_3 ((uint32_t)0x400) /*! 3 bits for pre-emption priority1 bits for subpriority */
#define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*! 4 bits for pre-emption priority0 bits for subpriority */NVIC_PriorityGroupConfig在源码STM32F10x_FWLib\src\misc.c中 主要设置这个寄存器SCB-AIRCRSCB系统控制块的内存映射结构中的 AIRCR应用程序中断/重置控制寄存器
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{/* Check the parameters */assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));/* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */SCB-AIRCR AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}这其实也很好理解比如选择NVIC_PriorityGroup_1那么抢占式优先级便占一位也就是说可以有2个级别可以设置为0和1而响应优先级则占3位也就是说可以有2^3个选择可以设置为0~7总共来说就可以区别16种优先级多余16种优先级时再按照中断表中的排位顺序执行。
举个例子吧假如现在有4个外部中断还有一个EXTI9_5中断那么如果选择优先级分组为第1组那么抢占式优先级便只有两种5个中断就至少有3个在抢占式优先级上是相同的优先级上其他两个在令一优先级别。接着设置响应优先级可以有8种选择假如现在同时有两个抢占式优先级别相同的中断发生那么处理的顺序是谁的响应优先级高则谁优先进入中断另外这点是需要注意的如果此时进入这个中断之后又来了一个抢占式优先级相同但是响应优先级更高的中断这时也是不会打断已有的中断的
4、设置中断
以设置串口中断为例完整代码如下
void uart_init(u32 bound){GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;# a)使能USART1、GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); # b)引脚初始化//USART1_TX GPIOA.9 初始化GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; //复用为推免输出GPIO_Init(GPIOA, GPIO_InitStructure);//初始化GPIOA.9//USART1_RX GPIOA.10 初始化GPIO_InitStructure.GPIO_Pin GPIO_Pin_10;//PA10GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, GPIO_InitStructure);//初始化GPIOA.10 # c)配置中断优先级Usart1 NVICNVIC_InitStructure.NVIC_IRQChannel USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority3 ;//抢占式优先级为3NVIC_InitStructure.NVIC_IRQChannelSubPriority 3; //子优先级响应式优先级为3NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; //IRQ通道使能NVIC_Init(NVIC_InitStructure); //配置# d)USART初始化设置USART_InitStructure.USART_BaudRate bound; //串口波特率USART_InitStructure.USART_WordLength USART_WordLength_8b; //数据长度8位USART_InitStructure.USART_StopBits USART_StopBits_1; //停止位1位USART_InitStructure.USART_Parity USART_Parity_No; //无奇偶校验USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; //收发模式读写都使能# e) 初始化串口、使能串口中断、使能串口USART_Init(USART1, USART_InitStructure); //初始化串口1USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启串口中断USART_Cmd(USART1, ENABLE); //使能串口1
}5、中断处理函数
注意 USART_IT_IDLE 和 USART_IT_RXNE 区别
当接收到1个字节会产生 USART_IT_RXNE 中断
当接收到1帧数据会产生 USART_IT_IDLE 中断void USART1_IRQHandler(void)
{u8 Res;u8 clear 0;# a)if(USART_GetITStatus(USART1, USART_IT_RXNE) ! RESET) {Res USART_ReceiveData(USART1); //读取收到的数据TEST_RX_BUF[TEST_RX_STA]Res; //将数据放入缓存} else if(USART_GetITStatus(USART1, USART_IT_IDLE) ! RESET){clear USART2-SR;clear USART2-DR;clear clear;TEST_RX_BUF[0] TEST_RX_STA- 1;TEST_RX_STA 1;}
}