|
前言: 5 F0 H/ v! X7 `
1.要想学习STM32中断,要先掌握STM32对优先级的定义;$ ~% q) f& P. f6 W% N% U
2.有51单片机开发经验会比较容易理解中断优先级;+ N) L9 l$ f$ `
3.本篇博文基于STM32F103ZET6芯片和3.5.0标准库编写;
% C; e6 Q# O' D( l9 h4.本篇博文从寄存器入手,最终实现编程的步骤;如有不足之处,还请前辈多多指教; $ I" B+ k6 H2 l# k. _) s' a9 s
一 基础知识 1 }' `) f! c- z" m; T3 O( ~
9 c: p5 ^9 a @% |
" b5 K$ } Q- e5 ]# M/ ]
& }- x: W. w: n
( G* g" ?* p7 N7 P `# c0 @. b7 x
1. cortex-m3支持256个中断,其中包含了16个内核中断,240个外部中断。(本博文只介绍60个外部可屏蔽中断)
% ^3 l2 E+ G* W0 [# h* S2. stm32只有84个中断,包括16个内核中断和68个可屏蔽中断" b/ A+ ]' P) X5 g' s
3. stm32f103上只有60个可屏蔽中断,f107上才有68个中断5 ]; g7 x' \/ h
4. 先占优先级也就是抢占优先级,概念等同于51单片机中的中断。假设有两中断先后触发,已经在执行的中断先占优先级如果没有后触发的中断 先占优先级更高,就会先处理先占优先级高的中断。也就是说又有较高的先占优先级的中断可以打断先占优先级较低的中断。这是实现中断嵌套的基础。8 I0 }# W' ^$ J6 m9 `% f4 l$ Q
次占优先级,也就是响应优先级,只在同一先占优先级的中断同时触发时起作用,先占优先级相同,则优先执行次占优先级较高的中断。次占优先级不会造成中断嵌套。 如果中断的两个优先级都一致,则优先执行位于中断向量表中位置较高的中断。 + Y# q6 P/ j. N
- NVIC是什么?
7 c( H+ h4 g2 Y2 {
- 嵌套向量中断控制器;用于为中断分组,从而分配抢占优先级和响应优先级;% L7 H: e. @( l" a
分组的方式有两种:
k* S6 o# S* x0 [8 u$ b7 ?(1)Cortex-m3内核提供了一种3位宽度的PRIGROUP数据区,用于指示一个8位数据序列中的小数点的位置,从而表示中断优先级的分组。见下表:
' f2 Z# s! Q1 [% ^6 L5 s - z! o) h; u S- d, D' a
; w! m; [1 F$ s" X5 L$ K
, z, ~* g) X J3 _, o: n, w% T3 B; K/ U& M% B
: f/ E: m& U- P- G
(2)而实际上STM32并没有用到这么多中断,所以在分组上只分了5个组,并且表示方法有所不同;见下表:
! A: p1 y( v; Z9 A5 O4 Y( Q
. t. C$ K) K$ ?2 }
我们在应用当中只会用到STM32的分组(5组)方式,所以下面着重于5组分组方式; * Z! s; N* A' c$ K" |' Y
二 中断向量表 (STM32F10x系列)
/ [; C/ U% b0 x; f7 V! F ( j" U* L5 A. P+ c2 a
8 F* z( s- `3 @. H& x, f
6 p+ E6 d; c9 _4 ?7 [0 s+ c+ `* @2 B/ M$ a+ S
" f7 i+ f" T& }7 ^) R& h N
" i2 D& X$ S/ l% G(图片来自STM32使用手册,只需看,不需要熟记,知道大概这么多中断就好) u$ f2 |) f) f( Y/ n5 O' G" m
5 L% o) |3 |; L0 w/ w h
三 配置中断相关寄存器 & {0 `) X/ o* b& G* [7 D R
- /*
. @" T! E7 u0 v- b5 \* T - cortex-m3内核分组方式(8组)结构体表达方式:
" T( x4 X. K& d3 c1 W& c - */
8 B! v6 H" u7 X8 n+ ~" g- z - typedef struct: s% T1 @' X; ^% l
- {1 Z% J8 @) M2 |1 E3 v- K
- __IO uint32_t ISER[8]; 中断使能设置寄存器 /*!< 偏移量: 0x000 Interrupt Set Enable Register */
+ R5 [& H* q: w1 r" f - uint32_t RESERVED0[24];
: s4 {( @* R) W+ m. v0 E" n3 t2 P - __IO uint32_t ICER[8]; 中断清除使能寄存器 /*!<偏移量: 0x080 Interrupt Clear Enable Register */. h1 {, T" H! h; w2 b3 A, P
- uint32_t RSERVED1[24]; 0 T3 W+ W. g( E3 x I7 a
- __IO uint32_t ISPR[8]; 中断挂起设置寄存器 /*!< 偏移量: 0x100 Interrupt Set Pending Register */2 Q/ t$ M9 F' y' A
- uint32_t RESERVED2[24]; ' S3 `" ~% z8 e
- __IO uint32_t ICPR[8]; 中断清除挂起寄存器 /*!<偏移量: 0x180 Interrupt Clear Pending Register */9 N3 r1 A) m2 E2 M
- uint32_t RESERVED3[24];
& C& b7 _3 T7 P' B! T/ i - __IO uint32_t IABR[8]; 中断激活状态位寄存器 /*!< 偏移量: 0x200 Interrupt Active bit Register */
# M# ?2 n1 k- b9 u) Y% A2 Z* ^ - uint32_t RESERVED4[56];
$ F' J. \. R$ [3 B% n0 U" P, S - __IO uint8_t IP[240]; 中断优先级寄存器 /*!< 偏移量: 0x300 Interrupt Priority Register (8Bit wide) */
q% i# u, h1 J! i5 v7 K - uint32_t RESERVED5[644]; 软件触发方式寄存器
( b) N. G E% v* u! U0 @5 k- X - __O uint32_t STIR; /*!< 偏移量: 0xE00 Software Trigger Interrupt Register */( C7 i, |6 l- V4 I8 ~, X. h
- } NVIC_Type;
复制代码- /*
$ r6 Y {2 S; r* o7 K; M/ R; _& K O% { - STM32分组(5组)方式结构体表达方式
2 P% w, E+ u! ]4 k) ?8 v - typedef struct
N: |/ a5 L& t2 S - {
4 f5 Z1 r$ v9 b - vu32 ISER[2];
N' x7 n! t9 }1 S: T% H$ \ - u32 RESERVED0[30];/ [. b; E1 l, O, B" L
- vu32 ICER[2]; \# x3 _2 ?9 `2 h+ p% e0 ~
- u32 RSERVED1[30];
) h* T: d; c# n. B { L - vu32 ISPR[2];
6 \ {( Q' P3 y& @; G - u32 RESERVED2[30];! Y' ^+ E8 E1 j
- vu32 ICPR[2];
3 c; P/ @ m+ r% A+ W - u32 RESERVED3[30];
) V& E% I! X% @3 O1 ]; m+ U# d - vu32 IABR[2];9 y0 X3 E( [. @( S5 e2 B
- u32 RESERVED4[62];- b2 D- u+ Q1 n
- vu32 IPR[15];
8 S$ y# r+ Q# c" b - } NVIC_TypeDef;( D; S; g% o+ N9 q' C
- */
复制代码 . I4 h% c2 a( g$ ]! S
以上寄存器介绍:0 _' K: A0 L v7 e
+ H: h0 [) Q x. P7 @$ ]0 Q! f
对一些概念的解释:
. M) j& q, s& N! t/ m- r/ }, X5 P, m' d9 r* Y
1. 挂起:当置位中断挂起寄存器的时候,相应的中断将会被挂起,这是这个中断将不会立即执行,而是等待可执行的时候再执行;比如高低级别的中断同时产生,就先挂起低级别的中断,等高级别的中断执行完毕,解除并执行低级中断;
2 g0 M# H/ h9 i8 h. a( I2. 对中断优先级控制寄存器的解释
' A, O8 [7 g! h. N! V! f, _ ( @- h6 \) F7 {9 ^
* I) k4 e S& t: z( Q/ h& a
' Y$ L5 {" b- {6 g3 q Z/ U Q' N+ M0 @# e: g1 L9 z: @3 M
四 编程步骤 0 y! q: e! z# Y) B
(1)选择优先级分组/ f* c- _+ q5 ~* k- L
/*
' {; R( k a$ Y; G1. 此函数在库文件misc.h文件下;
, |3 {9 t. q2 i' z, _( ]
2. 参数可参照下面图片: ( T6 v. _; c( m1 q* |1 l
5 K, G, X8 D0 c6 v( }
3. 功能:选择分组方式;
( |8 P$ n$ K5 z% {: b*/" z# Z1 y0 h, F5 |6 y
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); 栗子:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
0 i8 ~* D3 E4 R+ }/ n; C/ f% i//抢占优先级可选0~3,响应优先级可选0~3; u! z9 {" b, F7 i9 h! c
(2)选择,配置,并使能中断) |1 N9 i( t! a
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //选择EXTI2中断
2 C" d: \" p wNVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级为2
) A" T; C n2 w" qNVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //响应优先级为2- p# i% n( F( I3 l. ^) _
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能EXTI2中断;' X' u3 B R. Z7 \8 Y( F6 W1 S
NVIC_Init(&NVIC_InitStructure); //初始化以上参数;
8 F. X5 E9 [- @
(3)写出相应中断函数
( V8 ~1 p3 I0 \& |+ @4 C# ~; ?栗子:
/ {6 M4 J7 A8 Q6 W! z# j; wvoid EXTI2_IRQHandler(void)$ ^4 z3 @' A5 }' y' d! V
{ //逻辑代码; EXTI_ClearITPendingBit(EXTI_Line2);; M" y9 m4 a6 q D0 E7 `
} 1 X; C9 e/ k! p# E
|