STM32的内核很强大,它具有强大的异常响应系统。我们知道能够中断当前代码执行的事件有两种,一种是异常,另一种就是中断了。在32中,编号-3-6的中断向量定义为系统异常,编号为负的内核异常不能设置优先级,一般如复位、不可屏蔽中断、硬错误。从编号 7 开始的为外部中断,这些中断的优先级都是可以自行设置的。
NVIC对于我们写过中断的人并不陌生,即中断控制器,它属于内核的器件,不可屏蔽中断和外部中断都由它来处理,而SYSTICK 不是由 NVIC 来控制的。
NVIC结构体成员
当我们要用NVIC来配置中断时,在库函数中找到一个NVIC_Init()函数,有一个NVIC_InitTypeDef类型的结构体,有四个成员:
NVIC_IRQChannel 需要配置的中断向量
NVIC_IRQChannelCmd 使能或关闭相应中断向量的中断响应
NVIC_IRQChannelPreemptionPriority 配置相应中断向量抢占优先级
NVIC_IRQChannelSubPriority 配置相应中断向量的响应优先级
1.抢占优先级与响应优先级
两种优先级都是一种属性,属性编号越小,优先级越高。抢占是指打断其他中断的属性,当出现嵌套中断情况下,优先级高的可以打断优先级低的中断。响应优先级指若两个中断相同或者是抢占优先级相同的情况下,响应优先级高的优先响应。
2.NVIC的优先级组
配置优先级时,需要注意中断的种类数量问题,NVIC只能配置16种中断向量的优先级,即抢占优先级和响应优先级的个数是由一个4位数来决定的,将这4位数的位数分配成抢占优先级和响应优先级,一共提供了5组分配方式:
第 0 组: 所有 4 位用来配置抢占优先级,即 NVIC 配置的 2 4 =16 种中断向量都是只有抢占属性,没有响应属性。
第 1 组:最高 1 位用来配置抢占优先级,低 3 位用来配置响应优先级。表示有 2 1 =2 种级别的抢占优先级(0 级,1 级),有 2 3 =8 种响应优先级,即在 16种中断向量之中,有 8 种中断,其抢占优先级都为 0 级,而它们的响应优先级分别为 0~7,其余 8 种中断向量的抢占优先级则都为 1 级,响应优先级别分别为 0~7。
第 2 组:2 位用来配置抢占优先级,2 位用来配置响应优先级。即 2^2 =4 种抢占优先级,2^2 =4 种响应优先级。
第 3 组:高 3 位用来配置抢占优先级,最低 1 位用来配置响应优先级。即有 8 种抢占优先级,2 种响应 2 优先级。
第 4 组:所有 4 位用来配置响应优先级。即 16 种中断向量具有都不相同的响应优先级。要配置这些优先级组,可以采用库函数 NVIC_PriorityGroupConfig() ,可输入的参数为 NVIC_PriorityGroup_0 ~ NVIC_PriorityGroup_4 ,分别为以上介绍的 5 种分配组。
下面以配置一个外部中断为例:
1. 使能 EXTIx 线的时钟和第二功能 AFIO 时钟
2. 配置 EXTIx 线的中断优先级
3. 配置 EXTI 中断线 I/O
4. 选定要配置为 EXTI 的 I/O 口线和 I/O 口的工作模式
5. EXTI 中断线工作模式配置
NVIC初始化配置
NVIC_Configuration() ,这是用户编写的用来配置 NVIC 控制器的函数。
EXTI初始化配置
配置好 NVIC 后,还要对 GPIO进行初始化,这部分和按键轮询的设置类似。
编写中断服务函数
进入中断后,调用库函数 EXTI_GetITStatus() 来重新检查是否产生了 EXTI_Line 中断,操作完毕后,调用EXTI_ClearITPendingBit() 清除中断标置位再退出中断服务函数。
外部中断是我们比较常用的,我们还有常用的有定时器中断,UART中断。
关于定时器,SysTick 一般只用于系统时钟的计时,32的定时器外设功能也是很强大的,STM32一共有8个16位定时器,TIM6、TIM7是基本定时器,TIM2-5为通用定时器,TIM1和TIM8为高级定时器。这些定时器使 STM32 具有定时、信号的频率测量、信号的 PWM 测量、PWM输出、三相六步电机控制及编码器接口等强大的功能。
基本定时器:这两个定时器只具备最基本的定时功能,就是累加的时钟脉冲数超过预定值时,能触发中断或触发 DMA 请求。由于在芯片内部与 DAC 外设相连,可通过触发输出驱动 DAC。也可以作为其它通用定时器的时钟基准。
通用定时器:除了基本的定时,它主要用在测量输入脉冲的频率、脉冲宽与输出 PWM 脉冲的场合,还具有编码器的接口。
高级定时器:具有基本、通用定时器的所有功能,还具有三相六步电机的接口,刹车功能及用于 PWM 驱动电路的死区时间控制等,使得它非常适合于电机的控制。
下面介绍一下普通通用定时器中断的例子。
对定时器的配置:
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Period = Period;
TIM_TimeBaseStructure.TIM_Prescaler=(7200-1);
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
对中断的配置:
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //响应优先级为3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
使能TIM外设:
TIM_Cmd(TIM3, ENABLE);
定时器中断函数:
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检测中断是否发生
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );//清除中断标志位
switch(STEP)
{
case 1:IsLed1On(YES);STEP=2;break;
case 2:IsLed2On(YES);STEP=3;break;
case 3:IsLed3On(YES);STEP=4;break;
case 4:IsLed4On(YES);STEP=5;break;
case 5:IsLed1On(NO);STEP=6;break;
case 6:IsLed2On(NO);STEP=7;break;
case 7:IsLed3On(NO);STEP=8;break;
case 8:IsLed4On(NO);STEP=1;break;
}
}
工程示例代码已上传到网盘,需要的各位可以免费自行下载运行链接:https://pan.baidu.com/s/1zDthYy2yXMQPTQzKSYyEXQ&shfl=sharepset
提取码:rakl