基于STM32单片机模块练习——中断总结

基于STM32单片机模块练习——中断总结

基本概念

1.ARM cortex_m3 内核支持 256 个中断(16 个内核+240 外部)和可编程 256 级中断优先级的设置,与其相关的中断控制和中断优先级控制寄存器(NVIC、SYSTICK 等)也都属于cortex_m3 内核的部分。STM32 采用了 cortex_m3 内核,所以这部分仍旧保留使用,但 STM32并没有使用cortex_m3 内核全部的东西(如内存保护单元 MPU 等,只保留了NVIC、SYSTICK ),因此它的 NVIC 是cortex_m3 内核的 NVIC 的子集。
2.STM32 目前支持的中断共为 84 个(16 个内核+68 个外部(这是互联型的,而基础型的只支持60个)),和 16 级可编程中断优先级的设置(仅使用中断优先级设置 8bit 中的高 4 位)
3.以下主要对“外部中断通道”进行说明。
对于 cortex_m3 内核所支持的 240 个外部中断,我在这里使用了“中断通道”这个概念,因为尽管每个中断对应一个外围设备,但该外围设备通常具备若干个可以引起中断的中断源或中断事件。而该设备的所有的中断都只能通过该指定的“中断通道”向内核申请中断。因此,下面关于中断优先级的概念都是针对“中断通道”的。当该中断通道的优先级确定后,也就确定了该外围设备的中断优先级,并且该设备所能产生的所有类型的中断,都享有相同的通道中断优先级。至于该设备本身产生的多个中断的执行顺序,则取决于用户的中断服务程序。(用if elseif吗???)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
5. 基础型STM32 可以支持的 60 个外部中断通道,已经固定的分配给相应的外部设备。每个中断通道都具备自己的中断优先级控制字节 PRI_n(8 位,但在 STM32 中只使用 4 位,高 4 位有效),每 4 个通道的 8 位中断优先级控制字(PRI_n)构成一个 32 位的优先级寄存器(Priority Register)。68 个通道的优先级控制字至少构成 17 个 32 位的优先级寄存器,它们是 NVIC寄存器中的一个重要部分。
6.在这里插入图片描述
NVIC 结构体定义,来自固件库头文件:core_cm3.h

1 typedef struct {
2 __IO uint32_t ISER[8]; // 中断使能寄存器
3 uint32_t RESERVED0[24];
4 __IO uint32_t ICER[8]; // 中断清除寄存器
5 uint32_t RSERVED1[24];
6 __IO uint32_t ISPR[8]; // 中断使能悬起寄存器
7 uint32_t RESERVED2[24];
8 __IO uint32_t ICPR[8]; // 中断清除悬起寄存器
9 uint32_t RESERVED3[24];
10 __IO uint32_t IABR[8]; // 中断有效位寄存器
11 uint32_t RESERVED4[56];
12 __IO uint8_t IP[240]; // 中断优先级寄存器(8Bit wide)
13 uint32_t RESERVED5[644];
14 __O uint32_t STIR; // 软件触发中断寄存器
15 } NVIC_Type;

在配置中断的时候我们一般只用 ISER、ICER 和 IP 这三个寄存器,ISER 用来使能中断,ICER 用来失能中断,IP用来设置中断优先级。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

如果在你的系统中使用了 TIME2(中断通道 28)和 EXTI0(中断通道 6)两个中断,而 TIME2中断必须优先响应,而且当系统在执行 EXIT0 中断服务时也必须打断(抢先、嵌套), 就必须设置 TIME2 的抢先优先级比 EXTI0 的抢先优先级要高(数目小)。假定 EXTI0 为 2 号 抢先优先级,那么 TIME2 就必须设置成 0 或 1 号抢先优先级。这些工作需要在 AIRC 中的 PRIGROUP 设置完成,确定了整个系统所具有的优先级个数后,再分别对每个中断通道(设 备)进行设置。

中断编程的顺序

在这里插入图片描述
第一步的使能中断请求,只是使能某个具体外设的中断,相当于开启了小门,另外还需要使能内核的中断,这相当于一扇大门。
第二步配置中断优先级分组:

 /* 配置 NVIC 为优先级组 1 */
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//初始化 NVIC_InitTypeDef 结构体,配置中断优先级分组,
//设置抢占优先级和子优先级,使能中断请求。
//NVIC_InitTypeDef 结构体在固件库头文件 misc.h 中定义。
1 typedef struct {
2 uint8_t NVIC_IRQChannel; // 中断源
3 uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级
4 uint8_t NVIC_IRQChannelSubPriority; // 子优先级
5 FunctionalState NVIC_IRQChannelCmd; // (总)中断使能或者失能
6 } NVIC_InitTypeDef;

1)NVIC_IROChannel:用来设置中断源,不同的中断中断源不一样,且不可写错,即使写错了程序也不会报错,只会导致不响应中断。具体的成员配置可参考 stm32f10x.h 头文件里面的 IRQn_Type 结构体定义,这个结构体包含了所有的中断源。
2)NVIC_IRQChannelPreemptionPriority:抢占优先级,具体的值要根据优先级分组来确定,具体参考优先级分组真值表 。
3)NVIC_IRQChannelSubPriority:子优先级,具体的值要根据优先级分组来确定,具体参考优先级分组真值表 。
4)NVIC_IRQChannelCmd:中断使能(ENABLE)或者失能(DISABLE)。操作的是 NVIC_ISER 和 NVIC_ICER 这两个寄存器。

编写中断服务函数
在启动文件 startup_stm32f10x_hd.s 中我们预先为每个中断都写了一个中断服务函数,只是这些中断函数都是为空,为的只是初始化中断向量表。实际的中断服务函数都需要我们重新编写,为了方便管理我们把中断服务函数统一写在 stm32f10x_it.c 这个库文件中。关于中断服务函数的函数名必须跟启动文件里面预先设置的一样,如果写错,系统就在中断向量表中找不到中断服务函数的入口,直接跳转到启动文件里面预先写好的空函数,并且在里面无限循环,实现不了中断。

中断优先级的确定和嵌套规则

ARM cortex_m3(STM32)规定:
a.只能高抢先优先级的中断可以打断低抢先优先级的中断服务,构成中断嵌套。
b.当 2(n)个相同抢先优先级的中断出现,它们之间不能构成中断嵌套,但 STM32 首先响应子优先级高的中断。
c. 当 2(n)个相同抢先优先级和相同子优先级的中断出现,STM32 首先响应中断通道所对应的中断向量地址低的那个中断。

具体一点: 0 号抢先优先级的中断,可以打断任何中断抢先优先级为非 0 号的中断;1 号抢先优先级的中断,可以打断任何中断抢先优先级为 2、3、4 号的中断;……;构成中断嵌套。
如果两个中断的抢先优先级相同,谁先出现,就先响应谁,不构成嵌套。如果一起出现(或挂在那里等待),就看它们 2个谁的子优先级高,如果子优先级也相同,就看它们的中断向量位置了。

上电 Reset 后,寄存器 AIRC 中 PRIGROUP[10:8]的值为 0(编号 0),因此此时系统使用 16 个抢先优先级,无子优先级。另外由于所有外部中断通道的优先级控制字 PRI_n 也都是 0,所以根据上面的定义可以得出,此时 68 个外部中断通道的抢先优先级都是 0 号,没有子优先级的区分。故此时不会发生任何的中断嵌套行为,谁也不能打断当前正在执行的中断服务。当多个中断出现后,则看它们的中断向量地址:地址越低,中断级别越高,STM32优先响应。

注意:此时内部中断的抢先优先级也都是 0 号,由于它们的中断向量地址比外部中断向 量地址都低,所以它们的优先级比外部中断通道高,但如果此时正在执行一个外部中断服务,它们也必须排队等待,只是可以插队,当正在执行的中断完成后,它们可以优先得到执行。

中断控制

1.对于 STM32 讲,外部中断通道位置 28(35 号优先级)是给外部设备 TIME2 的,但 TIME2本身能够引起中断的中断源或事件有好多个,比如更新事件(上溢/下溢)、输入捕获、输出匹配、DMA 申请等。所有 TIME2 的中断事件都是通过一个 TIME2 的中断通道向 STM32 内核提出中断申请,那么 STM32 中如何处理和控制 TIME2 和它众多的、不同的、中断申请呢?
2.cortex_m3 内核对于每一个外部中断通道都有相应的控制字和控制位,用于单独的和总的控制该中断通道。它们包括有:
■ 中断优先级控制字:PRI_n(上面提到的)
■ 中断允许设置位:在 ISER 寄存器中
■ 中断允许清除位:在 ICER 寄存器中
■ 中断悬挂 Pending(排队等待)位置位:在 ISPR 寄存器中(类似于置中断通道标志位)
■ 中断悬挂 Pending(排队等待)位清除:在 ICPR 寄存器中(用于清除中断通道标志位)
■ 正在被服务(活动)的中断(Active)标志位:在 IABR 寄存器中,(只读,可以知道当前内核正在处理哪个中断通道)

因此,与 TIME2 中断通道相关的,在 NVIC 中有 13 个 bits,它们是 PRI_28(IP[28]), 的 8 个 bits(只用高 4 位);加上中断通道允许,中断通道清除(相当禁止中断),中断通道 Pending 置位(我的理解是中断请求发生了,但当前有其它中断服务在执行,你的中断级别 又不能打断别人,所以 Pending 等待,这个应该由硬件自动置位的),中断 Pending 位清除 (可以通过软件将本次中断请求、且尚处在 Pending 状态,取消掉),正在被服务的中断 (Active)标志位,各 1 个 bit。 上面的控制字和控制位都是分布在 NVIC的寄存器组中的,可惜在 STM32 手册中竟然不 给出任何的解释和说明。

3.作为外围设备 TIME2 本身也包括更具体的,管理自己不同中断的中断控制器(位),它们主要是自身各个不同类型中断的允许控制位,和各自相应的中断标志位(这个在 STM32 的手册中有详细的说明了)。
4.在弄清楚 2、3 两点的基础上,我们可以全程、全面和综合的来了解 TIME2 的中断过程,以及如何控制的。
a.初始化过程
首先要设置寄存器 AIRC 中 PRIGROUP 的值,规定系统中的抢先优先级和子优先级的个数(在 4 个 bits 中占用的位数); 设置 TIME2 本身的寄存器,允许相应的中断,如允许 UIE(TIME2_DIER 的第[0]位) 设置 TIME2 中断通道的抢先优先级和子优先级(IP[28],在 NVIC 寄存器组中) 设置允许 TIME2 中断通道(在 NVIC 寄存器组的 ISER 寄存器中的一位)。
b. 中断响应过程
当 TIME2 的 UIE 条件成立(更新,上溢或下溢),硬件将 TIME2 本身寄存器中 UIE 中断标志置位,然后通过 TIME2 中断通道向内核申请中断服务。
此时内核硬件将 TIME2 中断通道的 Pending 标志置位(相当于中断通道标志置位),表示 TIME2 有中断申请。 如果当前有中断在处理,TIME2 的中断级别不够高,那么就保持 Pending 标志,当然用户可以在软件中通过写 ICPR 寄存器中相应的位把本次中断清除掉。 当内核有空,开始响应 TIME2 的中断,进入 TIME2 的中断服务。此时硬件将 IABR 寄存器中相应的标志位置位,表示 TIME2 中断正在被处理。同时硬件清除 TIME2 的 Pending 标志位。
c.执行 TIME2 的中断服务程序
所有 TIME2 的中断事件,都是在一个 TIME2 中断服务程序中完成的,所以进入中断程序后,中断程序需要首先判断是哪个 TIME2 的具体事件的中断,然后转移到相应的服务代码段去。 注意不要忘了把该具体中断事件的中断标志位清除掉,硬件是不会自动清除 TIME2 寄存器中具体的中断标志位的。
如果 TIME2 本身的中断事件多于 2 个,那么它们服务的先后次序就由用户编写的中断服务决定了。换句话说,对于 TIME2 本身的多个中断的优先级,系统是不能设置的。所以用户在编写服务程序时,应该根据实际的情况和要求,通过软件的方式,将重要的中断优先处理掉。 当然你也可以每次中断服务只处理其中的一个,然后再次进入中断,处理下一个。
d.中断返回
内核执行完中断服务后,便进入中断返回过程,在这个过程中需要: 硬件将 IABR 寄存器中相应的标志位清0,表示该中断处理完成。如果 TIME2 本身还有中断标志位置位,表示 TIME2 还有中断在申请,则重新将 TIME2的 Pending 标志置为 1,等待再次进入 TIME2 的中断服务。

以上中断过程在《ARM Cortex-M3 权威指南》中有详细描述,并配合时序图说明,可以参考。

上述两点弄清楚后,就可以在 ST 提供的函数库的帮助下,正确的设置和使用 STM32 的中断系统了。

了解更深入的东西,或者直接对寄存器操作(新手没必要看)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值