|
下面,我们看看关于NVIC寄存器的描述,都在哪些手册里面有提到 在使用STM32F10x standard peripheral library写有关于stm32中断的程序的时候,需要开启某个特定中断的控制位,除了对应外设的寄存器之外,还需要设置NVIC的相关寄存器的对应位。例如: - /****** STM32 specific Interrupt Numbers *********************************************************/
) m5 x% i) R% G4 E: B - WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */) U+ m& U: D; w. Y( `) L
- PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */9 O; D n9 P0 C2 Z8 Y
- TAMPER_IRQn = 2, /*!< Tamper Interrupt */
/ `3 o7 p. R$ c& q- D! ^ - RTC_IRQn = 3, /*!< RTC global Interrupt */, a- Q% a1 f) m0 W
- FLASH_IRQn = 4, /*!< FLASH global Interrupt */
8 f% B6 A4 [) A - RCC_IRQn = 5, /*!< RCC global Interrupt */3 H0 H: I, c# r* q
- EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */7 J7 w& H9 F- O" @: Q7 }8 `
- EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */# n5 @. {& J9 n2 o
- EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */+ g1 Z% P5 Q# U6 c, y. ?
- EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */3 N3 A7 |9 }! C
- EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */
/ l' b3 M2 C; s H* r - DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */
" n: u+ U2 ]+ z: U - DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */
+ i: |+ X) J0 I: H - DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */
; L( u* f/ K- K" f8 B0 P: B, X" i - DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */. ~' a9 e6 L: Y7 O
- DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */
4 H/ H) X: t3 E" W; V8 k9 F - DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */
. Z& i9 P* T2 K4 o - DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */
# B# S5 i# i6 k4 M - & r% Q. V$ r2 D+ B) D
- NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;0 ~6 H, m9 C+ I) Q5 A- y |: s
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
* [7 c# O4 @4 t) Q: a - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
3 Q: }3 ? Z W1 K& c - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
. P+ q# A' {/ e7 @- H r! U9 n* @) a. a - NVIC_Init(&NVIC_InitStructure);
复制代码
7 `7 ?' X% Y4 M7 A; j/ r# P而NVIC_Init()这个函数: - /**
& s# l! s+ k1 s6 u0 x& ~8 A - * @brief Initializes the NVIC peripheral according to the specified" n* Y7 ?! H3 I8 Z4 K
- * parameters in the NVIC_InitStruct.) m& k4 @% M" E& K8 S' l
- * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains* O* P& _+ v/ p( U& @/ B
- * the configuration information for the specified NVIC peripheral.
4 L1 b; B4 f) f. s - * @retval None% Y+ E8 C$ x6 E- e3 I
- */4 q( y# Z- L. }! H0 U/ ?7 g
- void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)9 [5 ?$ I$ I+ P# A" L O& F
- {
; [/ s' F2 F" p - uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;' m: U, S5 @. i( Z! m. w
-
0 E. L1 Y9 c, A, k( O2 F1 x0 y2 Z - /* Check the parameters */
8 Y0 n' W! j t8 ^) p3 I0 | - assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
0 w/ o4 q, Q' h7 `. ]* {( j - assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); * ?+ Z4 H# t, l4 p
- assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));! t4 B& Q( i# M& d) m
- 7 b" Q& W- i. x
- if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)3 u( I2 \4 c$ U( E
- {
9 R$ ]* e+ Y7 l- x$ ?1 e - /* Compute the Corresponding IRQ Priority --------------------------------*/
# `* m, f3 E* ]: g Q' m - tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
/ e1 v3 X' K9 v: P/ W. H! s - tmppre = (0x4 - tmppriority);# V: x. \$ Z$ s1 o
- tmpsub = tmpsub >> tmppriority;
: f3 v- q, |3 S% \+ h" m
( u5 f, Q6 G5 E" V0 ~- tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;. [, l; R1 _! W' H
- tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
" G, O. ` _& _" D - tmppriority = tmppriority << 0x04;
1 j& X. e& b$ n - + ^! \% ?, V: b; P* [
- NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
: S1 r" q3 r5 k$ _2 z4 O- x - ; r) u! g. J3 J8 t: z
- /* Enable the Selected IRQ Channels --------------------------------------*/5 X2 J% j4 C+ p& ]. V/ u
- NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =2 G9 _# }8 Y3 L; T4 r
- (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);: Q6 j' Q% f5 y" A8 _0 P% T
- }
, E+ f1 A: ~, Q, X! z - else
: E& i1 z3 d" F# l9 T1 e& J8 J - {8 m K R( Q2 G( I0 V. q C
- /* Disable the Selected IRQ Channels -------------------------------------*/- v7 w+ w3 _: ^7 k1 O
- NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
* m7 U) N( p6 q7 x0 c* g - (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
% Q; C7 a/ A6 B/ S - }
) F! a$ V- I9 { G% h$ q& P - }
复制代码 E: R3 g' x' K; q! K) Y6 @- I
可以看到,它会去设置几个寄存器:NVIC的IP,ISER,ICER等等,NVIC是基址,为: - #define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */# V8 M2 J# i1 G
- #define NVIC_BASE (SCS_BASE + 0x0100) /*!< NVIC Base Address */# T3 n( u7 {! O
- #define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */" v% X; b& F8 k+ r) I/ I
- # n5 g% P3 e; z) [
- % K6 C u% y w; X
- #define NVIC ((NVIC_Type *) NVIC_BASE) /*!< NVIC configuration struct */
复制代码
& D1 \2 u5 J3 m3 wNVIC_Type为: - /** @addtogroup CMSIS_CM3_NVIC CMSIS CM3 NVIC$ f4 g+ s M, i8 X: \! b3 G
- memory mapped structure for Nested Vectored Interrupt Controller (NVIC)
3 p) E+ y2 z( P7 o - @{1 J9 U$ ?# Q3 H. b0 a# v( m
- */
5 `" y- ]5 I! \6 D6 q# n - typedef struct
2 G L% V0 k& p6 A! Q' ] - {
) ]# o4 v% g6 h0 O4 h - __IO uint32_t ISER[8]; /*!< Offset: 0x000 Interrupt Set Enable Register */
( h' C% l" f) y. N% e% C G* T, @ - uint32_t RESERVED0[24];
1 `4 k! l7 ]; q% E - __IO uint32_t ICER[8]; /*!< Offset: 0x080 Interrupt Clear Enable Register */
8 j& p6 s6 u& {2 K5 [2 l9 e' B5 w0 Y - uint32_t RSERVED1[24]; % ~2 B! ?6 ^, h8 |( N
- __IO uint32_t ISPR[8]; /*!< Offset: 0x100 Interrupt Set Pending Register */
+ I V6 H, H8 d# n* t, Y - uint32_t RESERVED2[24];
. X# m }0 A5 I% d - __IO uint32_t ICPR[8]; /*!< Offset: 0x180 Interrupt Clear Pending Register */
" `; s# p5 L! y- l: \( [ - uint32_t RESERVED3[24]; : x+ e$ B( D$ m2 q/ M' ^( z& h) R% O, w! k
- __IO uint32_t IABR[8]; /*!< Offset: 0x200 Interrupt Active bit Register */
1 X3 A- W! M, W3 k3 f5 C - uint32_t RESERVED4[56];
2 b+ L* X: L# V& w! y; H, ] - __IO uint8_t IP[240]; /*!< Offset: 0x300 Interrupt Priority Register (8Bit wide) */ \* y2 s' W" k% [! a! Q* Y3 s* X
- uint32_t RESERVED5[644];
& ?; J' ~7 z+ m) M - __O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register */
/ K N! r/ F- v5 k" P - } NVIC_Type; 1 v5 S/ C7 p" X$ A0 q% d
- /*@}*/ /* end of group CMSIS_CM3_NVIC */
复制代码
: {- W+ O% ]1 c从上面可以了解到的是,NVIC的寄存器的基址是没有错的,《The Definitive Guide to the ARM Cortex-M3》 85页有个比较详细的内存图;或者查看《Cortex-M3 Technical Reference Manual Revision r1p1》3.4 System address map,6.3 NVIC programmers model:
V6 ~/ [( f! q
1 T7 C: A' E3 s0 C# e以及: ) c, Z7 A8 \& Y* W: T, C4 ?
: M) y. l3 ?6 g8 t4 y U
B3.4 Nested Vectored Interrupt Controller (NVIC)的相关说明,例如: : J* M; x, e3 Q! `; C# j, ~0 ?! F
/ G1 X; d0 E0 i: u2 j( {7 j3 M
当然,你看权威指南也可以的,在其APPENDIX D:NVIC Registers Quick Reference里面也有所描述。 但还有一个问题,我怎么知道这个Interrupt Set-Enable Registers寄存器的哪个位对应哪个中断呢?例如NVIC_ISER0的第0位对应哪个呢,其实,上面的表B3-31的说明已经说了,每一位对应一个中断号,所以我们还得看看stm32F103对应的中断号,可以查阅《RM0008:Reference manual》的第10章,Interrupts and events中的中断向量表,找到对应MD容量的那个表Table 63. Vector table for other STM32F10xxx devices,前面16个M3内核的中断,不可以从这个寄存器里控制,所以不管,我们从WWDG开始,可以看到这个表中的第一列即对应于寄存器中的某位(超过31的自己换算一下即可):
1 b& e5 R1 T1 S, a2 i! A6 p
! Z }6 s" Q3 L2 ^$ N4 A( N
可以看到,STM32F10x standard peripheral library文件stm32f10x.h中的中断号的定义是能够与这里对应上的。 另外,stm32F103RB的Datasheet(CD00161566)里面的2.3.5 Nested vectored interrupt controller (NVIC)提到F103仅有43个可屏蔽中断,所以只需用到NVIC_ISER0和NVIC_ISER1来设置启用外设中断。 0 L* V# c! _) O4 z' g' q6 d
|