基于ARM开发板从零开始学习STM32 03-中断与异常

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/huolu0602/article/details/102617174

   

    STM32的内核很强大,它具有强大的异常响应系统。我们知道能够中断当前代码执行的事件有两种,一种是异常,另一种就是中断了。在32中,编号-3-6的中断向量定义为系统异常,编号为负的内核异常不能设置优先级,一般如复位、不可屏蔽中断、硬错误。从编号 7 开始的为外部中断,这些中断的优先级都是可以自行设置的。

   NVIC对于我们写过中断的人并不陌生,即中断控制器,它属于内核的器件,不可屏蔽中断和外部中断都由它来处理,而SYSTICK 不是由 NVIC 来控制的。

NVIC结构体成员

当我们要用NVIC来配置中断时,在库函数中找到一个NVIC_Init()函数,有一个NVIC_InitTypeDef类型的结构体,有四个成员:

NVIC_IRQChannel 需要配置的中断向量

NVIC_IRQChannelCmd 使能或关闭相应中断向量的中断响应

NVIC_IRQChannelPreemptionPriority 配置相应中断向量抢占优先级

NVIC_IRQChannelSubPriority 配置相应中断向量的响应优先级

1.抢占优先级与响应优先级

两种优先级都是一种属性,属性编号越小,优先级越高。抢占是指打断其他中断的属性,当出现嵌套中断情况下,优先级高的可以打断优先级低的中断。响应优先级指若两个中断相同或者是抢占优先级相同的情况下,响应优先级高的优先响应。

扫描二维码关注公众号,回复: 7568003 查看本文章

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 
 

猜你喜欢

转载自blog.csdn.net/huolu0602/article/details/102617174
今日推荐