主要内容:9 f i3 [ i. w& F" H: z7 ~
1) NVIC中断优先级分组;
8 D" ~- L. W+ ~' c8 W3 j2 c+ K3 K$ @2) NVIC中断优先级设置。# h1 F+ X9 ?7 f5 r8 {; G9 m
( s1 O9 H5 X4 Z, O8 J9 r, b
1. NVIC中断优先级分组) K6 F R7 Y' N4 I0 Q/ S' S
1.1 CM3内核支持256个中断,其中包含16个内核中断和240个外部中断,并且具有256级的可编程中断设置;
6 @' a( l2 n% a+ v6 {1.2 STM32并没有使用CM3内核的全部东西,只用了它的一部分;
1 [: o$ _6 \9 J1.3 STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级;; K+ o; `3 E/ ]9 x- V4 H4 c( F
1.4 STM32F103系列上面,又只有60个可屏蔽中断(在107系列才有68个)。1 G2 L3 J; C$ U) g3 j
2. NVIC中断优先级向量表(STM32F10xx产品(非互联型))
9 E- X; G2 v1 a) @. I5 ?* m$ X2 D7 s6 T1 |4 g, m( E+ N! b
9 H; Q2 E7 l T0 E0 c3 C1 Q
1 n$ s( e# q: s2 u+ T
- V0 s8 J& `6 d$ ]7 G, X7 P
) i3 [/ q* V1 @3. NVIC中断优先级管理方法
/ D2 Z2 c! y* w3.1 对STM32中断进行分组,组0~4。同时,对每个中断设置一个抢占优先级和一个响应优先级值;1 t" K% U5 E# I) j7 s0 G! B' n$ p. i
3.2 分组配置是在寄存器SCB->AIRCR中配置:
+ p( s- d4 ~$ O2 Q- s/ a# U0 X8 G' ]1 N3 p& Z- u/ Q+ {
$ v5 w9 n1 Z0 B; f
# K+ t! A7 O, M9 D+ z3.3 分组配置是在寄存器SCB->AIRCR中配置。' d3 y# p9 H, ` `; ]$ X9 R
# R. y6 o) T" k5 l
4. 抢占优先级和响应优先级区别6 |! @2 |' V4 R
4.1 高优先级(值越小越高)的抢占优先级是可以打断正在进行的低抢占优先级中断的;' W6 b0 x; N/ V* s9 K
4.2 抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断;
+ q6 k+ M3 ~1 G" G/ o7 K8 v4.3 抢占优先级相同的中断,当两个中断同时发生的情况下,高响应优先级先执行;
! F' K" P9 e# l3 y: W- @- m4 s; `4.4 如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行。/ e6 D& [; k- F
举例:( u2 l4 ?2 b( X y2 L
假定设置中断优先级组为2,+ D O( k% N+ l! g- w* l
设置中断3(RTC中断)的抢占优先级为2,响应优先级为1;
: k# w! R3 h( b3 L* {0 N" c设置中断6(外部中断0)的抢占优先级为3,响应优先级为0;
6 M d' k: D- d$ x' A" e! f设置中断7(外部中断1)的抢占优先级为2,响应优先级为0。
" D6 ~4 w- i5 X8 p% b那么这3个中断的优先级顺序为:中断7>中断3>中断6。% s F$ c7 ?+ f. c
**备注:**一般情况下,系统代码执行过程中,只设置一次中断优先级分组,比如分组2,设置好分组之后一般不会再改变分组。随意改变分组会导致中断管理混乱,程序出现意想不到的执行结果。
: {$ D9 H) x+ q' H; r6 D# I# N: {0 s8 T" H8 B `
5. 中断优先级分组函数:0 n' t6 p/ S& s. |) E) u# W% W
' E! P) K; r( i. L- void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
( y; f& e' p! Y) ~) t8 }* y - {: M5 z* u. q; X; N: d
- assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));3 R8 ~9 H/ Y2 R8 `& w& x
- SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
3 c# P! L0 Q. n% W! F5 F$ t$ b - }: M5 R+ R; ~* n! r; e- n
- //例如NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//
复制代码 5 `/ ^% Q0 V7 c; i
6. MDK中NVIC寄存器结构体
2 |5 _* S& O. Z2 E+ T+ T' W# Y6 V* q: `' J9 u6 w
- typedef struct" g+ H3 ~% f, y. O* k
- {
- c4 g" \; Y6 A& |5 } - __IO uint32_t ISER[8]; //中断使能寄存器组// $ y4 g9 m. a4 X! x, J& F
- uint32_t RESERVED0[24];
7 O$ L, @8 m. C" K3 f - __IO uint32_t ICER[8]; //中断失能寄存器组//
t& M# K: H* s - uint32_t RSERVED1[24]; % E0 }0 X4 y3 O/ }
- __IO uint32_t ISPR[8]; //中断挂起寄存器组// % z/ @: N" D/ e1 k
- uint32_t RESERVED2[24];
2 O" ]6 w* @# ^6 @( f4 S, C - __IO uint32_t ICPR[8]; //中断解挂寄存器组//
! s9 D" a+ q. [! b# q0 ] - uint32_t RESERVED3[24];
- r: a) Q v6 Q( V; b. P - __IO uint32_t IABR[8]; //中断激活标志位寄存器组//
0 b- T) N- [, O' c. m: i - uint32_t RESERVED4[56]; 9 i+ K' C) C2 K( \: l7 r
- __IO uint8_t IP[240]; //中断优先级控制的寄存器组//
( f7 K, r% M6 E! R! j6 Q - uint32_t RESERVED5[644]; - h+ d' F \. E3 @( N+ X
- __O uint32_t STIR;
( d+ E2 Y- P9 z- g/ M/ q6 m% | - }
' c, Y4 A( C9 y+ L - NVIC_Type;
复制代码 , b* ^$ n) H7 q4 i5 y+ s0 o) M
7. 每个中断的优先级设置
1 b% i" W& o6 H$ C, _1.1 中断优先级控制的寄存器组:IP[240] (全称:Interrupt Priority Registers)
, k8 @- M8 f6 Z240个8位寄存器,每个中断使用一个寄存器来确定优先级。STM32F10x系列一共60个可屏蔽中断,使用IP[59]~IP[0]。每个IP寄存器的高4位用来设置抢占和响应优先级(根据分组),低4位没有用到。
# ^! T* p E k& ~相关函数:( _' t" @! ^; A2 l1 M* I
0 D( |. U X( `% V" e
- void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
复制代码
; M( c& v& _! B4 v9 l7.2 中断使能寄存器组:ISER[8] (作用:用来使能中断)% \5 o* ^* n W
32位寄存器,每个位控制一个中断的使能。STM32F10x只有60个可屏蔽中断,所以只使用了其中的ISER[0]和ISER[1]。ISER[0]的bit0bit31分别对应中断031。ISER[1]的bit027对应中断3259。
' U: E; A/ o, p0 z% C# M相关函数:, P Z! G& n$ `8 V8 P+ a
" c: r; r. Y" b) P& |- void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
复制代码
: J$ A% O2 _0 ^ Y7.3 中断失能寄存器组:ICER[8] (作用:用来失能中断)
- g, O* F9 I8 p( \32位寄存器,每个位控制一个中断的失能。STM32F10x只有60个可屏蔽中断,所以只使用了其中的ICER[0]和ICER[1]。ICER[0]的bit0bit31分别对应中断031。ICER[1]的bit027对应中断3259。
: N6 A C9 w. y1 X- ^相关函数:8 A4 G6 c& f2 l+ s. t& q1 v0 `
. [' G3 k9 d6 d6 U- |) K8 K4 Y- void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
复制代码
7 J3 J- U# D+ M) }5 J7 H) R: m7.4 中断挂起控制寄存器组:ISPR[8] (作用:用来挂起中断)8 L0 ]7 U O/ h6 P c9 [8 a
7.5 中断解挂控制寄存器组:ICPR[8] (作用:用来解挂中断)
" ]! v+ l4 ]9 [ }( B; f& {
c+ V5 [6 ?' D* j1 a* Q6 p# W- //7.4和7.5涉及的部分相关函数//# X3 ]- t. ^+ S$ X' M& A
- static __INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn);/ v$ m: p$ ?7 a3 l
- static __INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn);8 G5 t& c2 U- T0 Y+ l& w' L9 ?
- static __INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn); [7 m& I* Z' _3 ^( K
- //以上函数位于core_cm3.h文件中//
复制代码
& \; X0 e0 ^ ]1 D8 @7.6 中断激活标志位寄存器组:IABR [8] (作用:只读,通过它可以知道当前在执行的中断是哪一个)6 L0 o# K7 R% w; \1 B" r
如果对应位为1,说明该中断正在执行。
3 v) q- H( {# E' D+ ~, }相关函数:
5 A: d& `3 X: s( Y+ F& f; @$ m/ b$ S. K; I3 B! M$ f D
- static __INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn);
复制代码 4 l: O' r* E8 L6 _6 Q
8. 中断参数初始化函数解读/ ~; A* x* u4 F ^9 O" |7 J, [
, N8 l0 {9 G5 I) C& ^. X- void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct); v7 j1 H8 U0 ~3 p
- typedef struct
1 f$ m% p$ T# F" Y - {) L& C# I1 S8 i
- uint8_t NVIC_IRQChannel; //设置中断通道//+ T% s! T: B7 [7 `5 u7 v9 z1 i! T
- uint8_t NVIC_IRQChannelPreemptionPriority; //设置抢占优先级// v! Z% Y: @& C \9 @/ ]' p& {
- uint8_t NVIC_IRQChannelSubPriority; //设置相应优先级//
+ f2 F5 U; ]" t8 N) |9 ~$ O! ]6 q6 U - FunctionalState NVIC_IRQChannelCmd; //使能//# l* m7 M. \8 [7 ^1 u: f
- }NVIC_InitTypeDef; //位于misc.h文件中//
" Y! L; G. q$ y2 i/ \7 \1 y - NVIC_InitTypeDef NVIC_InitStructure; ; E, d3 X" w( e6 h, N8 Q
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //串口1中断,中断类型参考stm32f10x.h中的IRQn_Tpye;//
* g) K6 j' E5 T0 U; f - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; //抢占优先级为1//: }5 o, x9 Z: p$ X# p3 ~1 a4 D/ ]
- NVIC_InitStructure.NVIC_IRQChannelSubPriority= 2; //响应优先级位2//
; L7 a* Z2 l% o5 o( u: ] - NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE; //IRQ通道使能//* [5 Y8 z0 B; |6 ^1 s' N& y
- NVIC_Init(&NVIC_InitStructure); //根据上面指定的参数初始化NVIC寄存器//
复制代码
: L3 @$ Q5 L4 Y: d+ L. y* N4 X9. 中断优先级设置步骤1 [( F9 o9 x' t
9.1 系统运行后先设置中断优先级分组;* n7 E' U: X5 ?4 p
. s# H r- s; f" G8 T
- void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); //整个系统执行过程中,只设置一次中断分组;//
复制代码 - S$ C' J# A# ~4 l8 O
9.2 针对每个中断,设置对应的抢占优先级和响应优先级;
) D) O$ Q( n* ~* r% k
8 ?+ J5 T# z0 C0 G6 U$ w- void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
复制代码 5 n# b d( q, H% E9 S7 V/ |
9.3 如果需要挂起/解挂,查看中断当前激活状态,分别调用相关函数即可。, f6 l7 |" H' O# C
————————————————
; o( D N2 Q, _! z1 R( u8 H' z4 V版权声明:天亮继续睡
3 d1 ~* w* y+ s( s1 a- T( |" f$ Q; N5 Q$ G, T6 D7 u5 b i' J
: m! k+ x! }" y7 |$ H3 v- h* S1 B
|