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

【经验分享】STM32 NVIC中断优先级管理

[复制链接]
STMCU小助手 发布时间:2022-5-9 19:00
前言
$ y0 n+ j; X0 w$ z- {& G- c使用中断前,需了解中断优先级管理,0 T" x4 _" r% o& u
CM3 内核支持 256 个中断,其中包含了 16 个内核中断和 240 个外部中断,并且具有 256! t" x0 @; s' D  H8 w: H
级的可编程中断设置。但 STM32 并没有使用 CM3 内核的全部东西,而是只用了它的一部分。
6 T. c- L3 v' o+ r$ n- hSTM32 有 84 个中断,包括 16 个内核中断和 68 个可屏蔽中断,具有 16 级可编程的中断优先级。: D' q: C. B( A
而我们常用的就是这 68 个可屏蔽中断,但是 STM32 的 68 个可屏蔽中断,在 STM32F103 系列6 }: J) q% B  q- K) Y: I- a
上面,又只有 60 个(在 107 系列才有 68 个)。因为我们开发板选择的芯片是 STM32F103 系列
# J3 b, a; ?6 g( H' \5 s. a" _2 q的所以我们就只针对 STM32F103 系列这 60 个可屏蔽中断进行介绍。/ S: D+ c, b" ]. ^5 p! P

) N  T+ ~* A! c+ _/ ^( d" w一、STM32 NVIC 中断优先级管理, n2 P; o' y' B+ }# W! U
在 MDK 内,与 NVIC 相关的寄存器,MDK 为其定义了如下的结构体:* l) {1 {9 q$ ~) e

$ e1 O$ }0 i! \& [) y
  1. typedef struct1 O5 u$ b# v' h, t* l
  2. {
    2 Y' f8 D7 s4 |
  3. __IO uint32_t ISER[8]; /*!< Interrupt Set Enable Register /
    ! l7 f' h9 N& q' J! ]% y) w+ V6 \
  4. uint32_t RESERVED0[24];% u; a/ z$ C2 {; l
  5. __IO uint32_t ICER[8]; /!< Interrupt Clear Enable Register /% z& M# }$ `/ h4 V
  6. uint32_t RSERVED1[24];
    " a1 Q$ t# O: \- a
  7. __IO uint32_t ISPR[8]; /!< Interrupt Set Pending Register /6 [1 ^- K0 q1 b9 }# U. S
  8. uint32_t RESERVED2[24];5 T# D" {0 Q8 m, d) k6 A" N6 d
  9. __IO uint32_t ICPR[8]; /!< Interrupt Clear Pending Register /& \. O7 ]& Z& b6 g4 t' b3 Y5 N  o
  10. uint32_t RESERVED3[24];
    . m5 L: f' [$ d- @
  11. __IO uint32_t IABR[8]; /!< Interrupt Active bit Register /
    ; H- H2 Z5 r# X. a+ ~: V( R
  12. uint32_t RESERVED4[56];5 h! h/ _0 R: A- H
  13. __IO uint8_t IP[240]; /!< Interrupt Priority Register, 8Bit wide /7 T, X, p* Q. Z. H: j! ~" n
  14. uint32_t RESERVED5[644];8 n  @2 A) [' k1 K! P) e) @
  15. __O uint32_t STIR; /!< Software Trigger Interrupt Register */& x$ j" Z7 R6 E5 p5 `
  16. } NVIC_Type;
复制代码

& [3 J1 }3 V8 K: Q( [& ~7 HISER[8]: 中断使能寄存器组,使能某个中断,必须设置相应的 ISER 位为 1,使该中断被使能,配合中断分组、屏蔽、IO 口映射等设置。
6 D. F5 U4 w4 jICER[8]: 中断除能寄存器组,用来清除某个中断的使能。$ Y# N" f/ M4 H: n2 [+ o/ ?
ISPR[8]: 中断挂起控制寄存器组,通过置 1,可以将正在进行的中断挂起,而执行同级或更高级别的中断。写 0 是无效的。
5 ?5 o+ ]- S" h1 {* m  ~ICPR[8]: 中断解挂控制寄存器组,通过设置 1,可以将挂起的中断接挂。写 0 无效。( L: W5 j* d1 Q5 Z
IABR[8]: 中断激活标志位寄存器组
! h, H3 c: Y4 G8 c# Z& \- u8 oIP[240]: 中断优先级控制的寄存器组,由 240 个 8bit 的寄存器组成,每个可屏蔽中断占用 8bit,240 个可屏蔽中断。只用了高 4 位,这 4 位,又分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。而这两个优先级各占几个位又要根据 SCB->AIRCR 中的中断分组设置来决定。1 o. |- l* N5 g# x' ]* z5 \

' G% y7 }4 G) l9 p  ^# W( D二、STM32 的中断分组+ L, C6 Q) @* e) B. M
STM32 将中断分为 5 个组,组 0~4。该分组的设置是由 SCB->AIRCR 寄存器的 bit10~8 来定义的。6 A' l. y' v! O4 T
@LL}[U520I)BX@M1XM7(RFR.png % n" L7 p, h' Q/ q% H
& v" N  A, V0 Z. @5 p- S
每个中断,你可以设置抢占优先级为 0~7,响应优先级为 1 或 0。抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。- u0 w# [  t# I0 Z7 n1 Z
7 x' g1 h) e5 ]+ U( K& _
这里需要注意两点:第一,如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;第二,高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。+ h- `( w) F9 v" I; |7 x/ x6 B# l$ p

! W" L; J' C& P" s; @' r. ?2 o中断优先级分组函数 NVIC_PriorityGroupConfig3 A) R/ [5 ?! i
  I' n# {6 X, q: k
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
% i" T7 A, u! T
& `* }& W! `5 m, T8 ~这个函数的作用是对中断的优先级进行分组,这个函数在系统中只能被调用一次,一旦分
0 d& X! B# l/ D* J组确定就最好不要更改。
! t/ Y. j9 [# I; T+ u! }# X6 k6 O
  1. void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
    + j  S/ W9 n  y! t: f; V& y
  2. {2 k1 O$ b% d, X* I# Z
  3. assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
    & X( C. S# D9 F' p. z) M4 x  H
  4. SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
    " `) B! V+ B4 D6 @- C  h0 [+ u7 m
  5. }* {" u0 {- U' Y9 p
  6. 8 R0 w: Q3 _& @
  7. #define IS_NVIC_PRIORITY_GROUP(GROUP)
      a3 m$ c. `1 l
  8. (((GROUP) == NVIC_PriorityGroup_0) ||
    , q- ~; I5 H  g7 f8 u" x. X4 z& i
  9. ((GROUP) == NVIC_PriorityGroup_1) ||
    + l! D" ]- c% ~' }3 ?5 x0 J# g
  10. ((GROUP) == NVIC_PriorityGroup_2) ||0 ^) B2 q* n+ V6 i6 ~
  11. ((GROUP) == NVIC_PriorityGroup_3) ||
    # U* F5 x4 f4 o/ w# E% L; k: Y
  12. ((GROUP) == NVIC_PriorityGroup_4))0 n+ `- a: ]: `& e& f" g
复制代码

4 [3 U+ e+ W7 J. Y分组范围为 0-4
' v2 v& ]4 L  Y( W, F- }6 a% K+ I1 U9 y9 z( y
中断初始化函数 NVIC_Init
$ C2 E0 k- U/ n
% H# Y' ~( I4 y( P. [% s2 X5 A
  1. void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
复制代码
- d/ H% A5 s* L, Q( m8 e, A
NVIC_InitTypeDef 是一个结构体
, b+ n/ F/ A6 x2 z% {( d( }% j  N& ]; b6 Z: G6 I
  1. typedef struct+ e! f/ Y. b& |* a9 X
  2. {
    # R) T; K8 ~- m0 ]5 m' U- h
  3. uint8_t NVIC_IRQChannel;9 ~5 i. m- F- G* r: B9 a  |% B5 t
  4. uint8_t NVIC_IRQChannelPreemptionPriority;
    ) x) B1 I3 t: m, S$ _
  5. uint8_t NVIC_IRQChannelSubPriority;
    ' l4 ]: ^2 |. `
  6. FunctionalState NVIC_IRQChannelCmd;
    7 n( D5 V9 }5 v6 m) p/ _9 E
  7. } NVIC_InitTypeDef;
复制代码

6 X! `$ r- w) m# g+ sNVIC_InitTypeDef 结构体中间有三个成员变量,这三个成员变量的作用是:7 i& D& }" l0 Z5 b( y% F
NVIC_IRQChannel:定义初始化的是哪个中断,这个我们可以在 stm32f10x.h 中找到每个中断对应的名字。8 l$ |3 {' r+ L; V* S
例如 USART1_IRQn。0 K0 u* ?6 I& D) B  }& O
NVIC_IRQChannelPreemptionPriority:定义这个中断的抢占优先级别。
* }% I" x/ _( }* P4 p% iNVIC_IRQChannelSubPriority:定义这个中断的子优先级别。
5 c! i9 i) E: _/ x# P, ~NVIC_IRQChannelCmd:该中断是否使能。: E9 r$ k; H& g; l: U) ]
7 Z; N) m/ K! ?0 Z# t
中断优先级设置的步骤:
8 t. M% T) o( z! G5 }+ |

' y0 M. s/ `5 e系统运行开始的时候设置中断分组。确定组号,也就是确定抢占优先级和子优先级的8 q+ U5 Z' L) ]/ i
分配位数。调用函数为 NVIC_PriorityGroupConfig();
6 s2 K- R6 a3 R; u+ h! i设置所用到的中断的中断优先级别。对每个中断调用函数为 NVIC_Init();7 [' N5 M+ s: H: M5 n- ]( J
; S" z- j: J6 [) G% j& A

' b2 \, S: K. W0 d
* c( V" Y5 Y" Z# z+ ~8 B
赞 收藏 评论0 发布时间:2022-5-9 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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