你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32中断系统

[复制链接]
STMCU小助手 发布时间:2022-6-29 17:00
    STM32 中断非常强大,几乎每个外设都可以产生中断,因此这里我们单独使用一章来介绍它,为后面介绍外设中断做铺垫。学习本章可以参考《STM32F10x中文参考手册》 -9 中断和事件章节, 《Cortex M3 权威指南(中文)》 -chpt08 NVIC与中断控制章节。
7 F' Y  l7 l2 X" _/ H
中断概念
    在学习 51 单片机时,我们就接触过中断,中断其实就是当 CPU 执行程序时,由于发生了某种随机的事件(外部或内部),引起 CPU 暂时中断正在运行的程序,转去执行一段特殊的服务程序(中断服务子程序或中断处理程序),以处理该事件,该事件处理完后又返回被中断的程序继续执行,这一过程就称为中断,引发中断的称为中断源。比如:看电视时突然门铃响,那么门铃响就相当于中断源。
    有些中断还能够被其他高优先级的中断所中断,那么这种情况又叫做中断的嵌套,中断示意图如图。

5 R. j8 a: |8 F% Z7 I0 o5 V4 k( p$ c
微信图片_20220628182512.jpg

' m5 t" ]% z/ C2 g# R+ @" U
    Crotex-M3 内核支持 256 个中断,其中包含了 16 个内核中断和 240 个外部中断。但 STM32 并没有使用 M3 内核的全部东西,而是只用了它的一部分。
    STM32F10x 芯片有 84 个中断通道,包括 16 个内核中断和 68 个可屏蔽中断,对于STM32F103系列芯片只有60个可屏蔽中断, 在 STM32F107 系列才有 68 个。
    除了个别异常的优先级被定死外,其它异常的优先级都是可编程的。这些中断通道已按照不同优先级顺序固定分配给相应的外部设备。从 STM32F10x 中文参考手册的中断向量表可以知道具体分配到那些外设,这里只截取一部分,如需了解更详细可参考《STM32F10x 中文参考手册》-9 中断和事件章节内容,中断向量表如图。
微信图片_20220628182509.jpg
微信图片_20220628182505.jpg
微信图片_20220628182502.jpg
微信图片_20220628182459.jpg
6 B% p- ?; S8 f  ]' M4 g) ~% E
NVIC介绍
    NVIC 英文全称是 Nested Vectored Interrupt Controller,中文意思就是嵌套向量中断控制器,它属于 M3 内核的一个外设,控制着芯片的中断相关功能。
    由于 ARM 给 NVIC 预留了非常多的功能, 但对于使用 M3 内核设计芯片的公司可能就不需要这么多功能,于是就需要在 NVIC 上裁剪。ST 公司的 STM32F103芯片内部中断数量就是 NVIC 裁剪后的结果。
    上面说到 NVIC 控制着芯片的中断相关功能, 那么肯定有很多对应的寄存器,在固件库 core_cm3.h 文件内定义了一个 NVIC 结构体,里面定义了相关寄存器,如下:
  1. typedef struct
    * d0 J7 d( E- c" R5 E+ _* g
  2. {" w3 m5 l+ H% N* ?2 l) S
  3. __IO uint32_t ISER[8]; //中断使能寄存器* }9 X/ v: I  H
  4. uint32_t RESERVED0[24];
    2 C$ r) Y; Z" m+ j" b  Q- w
  5. __IO uint32_t ICER[8]; //中断清除寄存器
    5 I. Q7 R6 h8 F- U4 Y1 X! H
  6. uint32_t RSERVED1[24];
    - `- e% c, y" E  v. T5 ^" Z
  7. __IO uint32_t ISPR[8]; //中断使能悬起寄存器, J" j/ O4 H4 k' x4 o8 Z3 j
  8. uint32_t RESERVED2[24];
    3 v1 \: [- @$ a0 Z; }# U/ h. M
  9. __IO uint32_t ICPR[8]; //中断清除悬起寄存器
    . x. u2 Y, ~, u6 w8 l: x
  10. uint32_t RESERVED3[24];2 A4 l8 o2 i8 \" v! l3 h
  11. __IO uint32_t IABR[8]; //中断有效位寄存器
    3 ?0 Q3 R; B+ e7 ~# F+ m& r
  12. uint32_t RESERVED4[56];
    # g$ C4 o+ o7 Y8 ^$ g
  13. __IO uint8_t IP[240]; //中断优先级寄存器
    " N, B; V4 y$ [( Q9 E& s
  14. uint32_t RESERVED5[644];
    ! K( ]. R0 I/ D1 w( z
  15. __O uint32_t STIR; //软件触发中断寄存器3 Y. A: p3 l8 ^, b
  16. } NVIC_Type;
复制代码
; l1 [- Z) T  z3 h) _* N
    在配置中断时,我们通常使用的只有 ISER、 ICER 和 IP 这三个寄存器,
2 }8 Q7 ^1 ]4 c$ E" K7 w( e) K" W
ISER是中断使能寄存器,ICER是中断清除寄存器,IP 是中断优先级寄存器。
在固件库 core_cm3.h文件后面,还提供了一些对 NVIC 操作的库函数,这些
函数都是遵循 CMSIS 标准, 所以只要是基于 Cortex-M3 内核的芯片都可以用这些函数来操作 NVIC,只不过我们很少这样做,甚至不使用这些函数,因为在后面我们会有更简单的办法来配置中断。至于这些函数内容,大家如果有兴趣的话,可以打开我们库函数版本任意程序,找到 core_cm3.h 文件查看即可。

2 X' i; }; W/ E$ A+ M, G1 C. B
中断优先级
    前面说了 STM32F103 芯片支持 60 个可屏蔽中断通道,每个中断通道都具备自己的中断优先级控制字节(8 位,理论上每个外部中断优先级可以设置为0-255,数值越小,优先级越高。但是 STM32F103 中只使用 4 位,高4位有效),用于表达优先级的高 4 位又被分组成抢占式优先级和响应优先级, 通常也把响应优先级称为“亚优先级”或“副优先级”,每个中断源都需要被指定这两种优先级。
    高抢占式优先级的中断事件会打断当前的主程序或者中断程序运行, 俗称中断嵌套。在抢占式优先级相同的情况下,高响应优先级的中断优先被响应。
    当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理那一个,越靠前的先执行。
    STM32F103 中指定中断优先级的寄存器位有 4 位,这 4 位的分组方式如图。
% w/ \- O; O; L% ~
微信图片_20220628182454.jpg
1 O% v! N& ?) E7 F3 i6 r: x3 M  c1 ~
第0 组:所有 4 位用于指定响应优先级
第1 组:最高 1 位用于指定抢占式优先级,最低 3 位用于指定响应优先级
第2 组:最高 2 位用于指定抢占式优先级,最低 2 位用于指定响应优先级
第3 组:最高 3 位用于指定抢占式优先级,最低 1 位用于指定响应优先级
第4 组:所有 4 位用于指定抢占式优先级
    设置优先级分组可调用库函数 NVIC_PriorityGroupConfig()实现,有关NVIC 中断相关的库函数都在库文件 misc.c 和 misc.h 中,所以当使用到中断时 , 一 定 要 记 得 把 misc.c 和 misc.h 添 加 到 工 程 组 中 。
NVIC_PriorityGroupConfig()函数代码如下:
  1. void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)" f. N- x% B) B( m: R1 e
  2. {
    : B& s" R& e- j: ^
  3. /* Check the parameters */
    3 g) i& K  D/ p; s
  4. assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));- l: }: ^& t. q0 F5 _
  5. /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup1 f7 y( @% K3 K7 i
  6. value */0 i2 C2 k. y, s; l) Q. K* {
  7. SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;3 L9 ?/ e3 e! \% @
  8. }
复制代码

$ X  H% V# j( u* d7 t( }9 Y% K
   NVIC_PriorityGroupConfig 函数带一个形参用于中断优先级分组,该值范围可以是 NVIC_PriorityGroup_0-NVIC_PriorityGroup_4,对应优先级与占用的位数信息如下:
) Z4 y; y1 }+ k) Q
微信图片_20220628182449.jpg

+ m- U( ~: h" ^" i8 _! z$ U1 Q
    函数内最终将分组值给 SCB->AIRCR,说明控制中断优先级寄存器是内核外设 SCB的 AIRCR 寄存器的PRIGROUP[10:8]位。
4 O. D& z$ {$ \# K9 w
中断配置
    前面讲解了那么多中断知识, 如果大家不理解也没有关系, 我们会应用即可,等到后面 STM32 熟练了,再回过头深入了解自然就会明白。要使用中断我们就需要先配置它,通常都需经过这几步:
(1)使能外设某个中断,这个具体是由外设相关中断使能位来控制,比如
定时器有溢出中断,这个可由定时器的控制寄存器中相应中断使能位来控制。
(2)设置中断优先级分组,初始化 NVIC_InitTypeDef 结构体,设置抢占
优先级和响应优先级,使能中断请求。
    NVIC_InitTypeDef 结构体如下:
  1. typedef struct% @5 W9 R/ B' }/ T9 m2 t1 K/ }
  2. {
    4 b3 w9 m0 j. ~4 l% O8 e- X
  3.   uint8_t NVIC_IRQChannel; //中断源
    7 l  l3 _# x7 S
  4.   uint8_t NVIC_IRQChannelPreemptionPriority; //抢占优先级8 N3 D' Y. |. j4 ]. O
  5.   uint8_t NVIC_IRQChannelSubPriority; //响应优先级
    % {8 B5 ?- h2 s! S! b/ I
  6.   FunctionalState NVIC_IRQChannelCmd; //中断使能或失能  H# j% y$ A) }8 y* y" C
  7. } NVIC_InitTypeDef;
复制代码

( u( @# x% V2 P9 W0 T4 p, j+ H- P
    下面我们对 NVIC_InitTypeDef 结构体成员进行一下简单介绍。
1.NVIC_IRQChannel:中断源的设置,不同的外设中断,中断源不一样,自
然名字也不一样,所以名字不能写错,否则不会进入中断。中断源放在stm32f10x.h 文件的 IRQn_Type结构体内,由于内容太多,这里就不复制所有中断源,只截取一部分,如下:
  1. typedef enum IRQn
      u; `& ^, W; r# U' b. g
  2. {! X1 q; G" {: S# V( L
  3.   //Cortex-M3 处理器异常编号
    7 G- t* F/ z6 f0 [' A" P' f3 n* m# A
  4.   NonMaskableInt_IRQn = -14,( U( D; U3 F% `5 T, l0 C
  5.   MemoryManagement_IRQn = -12,
    - K/ K; Q0 s4 u: `, ~: V
  6.   BusFault_IRQn = -11,8 C8 Y' z4 m6 u) b8 c1 b. p  O- r
  7.   UsageFault_IRQn = -10,# y( n( S) q2 O( f( S; @
  8.   SVCall_IRQn = -5,3 e4 F" |; T$ r) D- f- M- e
  9.   DebugMonitor_IRQn = -4,, X' o0 m" P7 p3 ]* j( K8 s6 R) R
  10.   PendSV_IRQn = -2,
    ; d6 O# R& y# }/ |
  11.   SysTick_IRQn = -1,$ q' X8 H2 u- F1 v3 O; t. g& _2 i
  12.   //STM32 外部中断编号) d( J* n+ r/ q: v6 D
  13.   WWDG_IRQn = 0,  m4 |+ o! e2 ?: y1 w" \, N! F
  14.   PVD_IRQn = 1,/ |3 m8 m8 X) `) i9 O; m; y, f! S
  15.   TAMP_STAMP_IRQn = 2,4 `% D- t, H2 W7 b) O) u- Q6 F
  16.   // 限于篇幅,中间部分代码省略,具体的可查看库文件 stm32f10x.h
    . M2 a6 ^& G% L. l
  17.   DMA2_Channel2_IRQn = 57,- `/ ?* x, d; S/ Y" d( q; e4 ^' V0 u
  18.   DMA2_Channel3_IRQn = 58,' A# e8 k8 @# o5 W( v# ^3 P/ B
  19.   DMA2_Channel4_5_IRQn = 59
      C: V5 i( i& i! X
  20. }IRQn_Type;
复制代码
1 f( I! d9 U# P3 H: g
2.NVIC_IRQChannelPreemptionPriority:抢占优先级,具体的值要根据优先级分组来确定,可以参考前面中断优先级分组内容。
3.NVIC_IRQChannelSubPriority:响应优先级,具体的值要根据优先级分组
来确定,可以参考前面中断优先级分组内容。
4.NVIC_IRQChannelCmd:中断使能/失能设置,使能配置为 ENABLE,失能配置为 DISABLE。
(3)编写中断服务函数
    配置好中断后如果有触发,即会进入中断服务函数,那么中断服务函数也有固定的函数名,可以在 startup_stm32f10x_hd.s 启动文件查看,启动文件提供的只是一个中断服务函数名,具体实现什么功能还需要我们自己编写,可以将中断服务函数放在 stm32f10x_it.c 文件内,也可以放在自己的应用程序中。通常我们把中断函数放在应用程序中。这里提醒一下大家,不要任意修改中断服务函数名,因为启动文件内中断服务函数名已经固定,如果要修改,你还必须在启动文件内把原中断函数修改。

( j+ @6 ^  S$ r1 J
赞 收藏 评论0 发布时间:2022-6-29 17:00

举报

0个回答

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版