下面,我们看看关于NVIC寄存器的描述,都在哪些手册里面有提到 在使用STM32F10x standard peripheral library写有关于stm32中断的程序的时候,需要开启某个特定中断的控制位,除了对应外设的寄存器之外,还需要设置NVIC的相关寄存器的对应位。例如: - /****** STM32 specific Interrupt Numbers *********************************************************/' L& v0 P9 h" e6 L, Y: b5 A
- WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */
* s/ [8 t, o0 a$ L. [0 S - PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */
9 o. C' r9 S* M - TAMPER_IRQn = 2, /*!< Tamper Interrupt */
1 H1 F9 Y4 m: ~& ]4 L* g4 S2 o - RTC_IRQn = 3, /*!< RTC global Interrupt */) D t. d) g4 A
- FLASH_IRQn = 4, /*!< FLASH global Interrupt */
" V2 K7 Y8 d2 o6 Q: C! \9 m; E' D - RCC_IRQn = 5, /*!< RCC global Interrupt */2 l8 h+ j" P: B {; c$ K
- EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */2 A _2 a* S- q
- EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */& D* R. d4 n/ |
- EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */3 N/ G% Z. m L( `6 g
- EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */
) P3 [& J7 z k- a2 b! E! } - EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */& S6 m1 z( t/ p+ j2 d% y2 H7 E5 I
- DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */
& b" m' r& d2 v& O3 } - DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */5 Z/ l' j' b Z: y t1 \# |
- DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */
0 _1 n% H% S; i( p _4 S0 k - DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */. X! r; l# \# u# {/ w0 y
- DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */3 b0 g$ [1 w4 a' w& [6 o7 J
- DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */9 g7 H8 D0 ?0 G+ f: g; T
- DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */1 D' t# g% I9 C
8 f) s2 T" x$ s( x; Y- NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;! l, {9 B# D- Z+ g+ D1 _. D
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;6 X7 F2 W& F+ W [; [4 v; e$ y/ V
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;5 |& {& w# F( i, i4 x* Y: P
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; W, R5 H* X f
- NVIC_Init(&NVIC_InitStructure);
复制代码
* U" r2 L8 O6 g1 r而NVIC_Init()这个函数: - /**
& T& u# w) m) r4 i" D ]3 ` - * @brief Initializes the NVIC peripheral according to the specified
4 W) T$ |6 L9 N6 v, e! N/ k - * parameters in the NVIC_InitStruct.) m2 Q0 W9 {+ z; H$ H" E
- * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains0 W! R# Z0 c) G% D: s/ @
- * the configuration information for the specified NVIC peripheral.* ?& p3 z" ?# B3 d `
- * @retval None9 E @! f7 Z8 M
- */
0 A7 o/ M! o: A8 m4 G - void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
& W0 e" V8 R1 ^7 d" G, ] - {
# r1 e3 I" H( x$ L; s" D% K - uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
' w: U. x* ~4 j/ M; a0 l! t2 j -
$ a' ]7 }+ Q/ X9 ?9 x! M, A# z - /* Check the parameters */3 K* n2 |: n% Z; p6 L- h
- assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));9 S! h8 }# r: }& o L* n$ Q
- assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); 9 x- c5 a; s8 P' F) _/ z* l
- assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));1 f7 H6 d) L5 X3 S% M
- . ~9 K% w1 \* B1 }
- if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)- C, ^! \) l5 J. }
- {4 O- p; t! X+ f# H n; }, z/ z
- /* Compute the Corresponding IRQ Priority --------------------------------*/ * U$ [' G. n% Y7 u* W. ~4 o- r: C
- tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
1 R( ^4 F% \ m5 o. | - tmppre = (0x4 - tmppriority);; A+ E) d- A. s* _$ [3 g! T( c
- tmpsub = tmpsub >> tmppriority;1 I0 t& _/ {+ i6 l- L1 v* _% u' i9 J
- ; Q( g! p H# b9 M4 T$ k0 J: {
- tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
$ Q M# d7 B$ b. p8 U9 _( r - tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;5 W& m- K, d8 e& U0 v) }
- tmppriority = tmppriority << 0x04;
. j, n8 k( a+ T8 K9 `9 f3 h* ~ -
2 g z0 T7 A8 D - NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;2 s& V/ b% Y7 \ K9 E+ U: X# A1 g' X8 ^
-
8 B7 ^5 Z) O3 m8 Z+ h - /* Enable the Selected IRQ Channels --------------------------------------*/. f5 s: {: \5 t+ K* _0 f- _
- NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = e+ B- Z1 J# p) V
- (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);, K# c L* r. D& J$ k1 V" W
- }
5 ~- P& T/ D/ q! t; ^/ W2 n - else& S# J7 M* H- Z1 O$ L. j
- {$ L% z; I* S. e/ t! y, P
- /* Disable the Selected IRQ Channels -------------------------------------*/8 J1 k/ n- }/ a! B2 `4 }2 N+ q/ e
- NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =8 r D3 @% V) {
- (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
$ h1 z; F0 r1 ~! d/ y1 P! } - }
; J6 d2 M& N/ o# Z E4 r& U" e- _ - }
复制代码
# M! q% ]" ?( U5 A: @: s可以看到,它会去设置几个寄存器:NVIC的IP,ISER,ICER等等,NVIC是基址,为: - #define SCS_BASE (0xE000E000) /*!< System Control Space Base Address *// G% Q) v0 x3 M/ l; J; Z; Q
- #define NVIC_BASE (SCS_BASE + 0x0100) /*!< NVIC Base Address */
9 R! i# [8 r; q/ B - #define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */+ {: {' h% a$ B+ ~5 o$ t+ M p
. l9 s! D7 b& d4 r- % A$ \9 u; W3 C" U9 ]7 A* Y4 }
- #define NVIC ((NVIC_Type *) NVIC_BASE) /*!< NVIC configuration struct */
复制代码
4 E9 ~" a p# m4 HNVIC_Type为: - /** @addtogroup CMSIS_CM3_NVIC CMSIS CM3 NVIC, J* t/ n7 m" U8 v
- memory mapped structure for Nested Vectored Interrupt Controller (NVIC)/ f$ m3 q5 ?$ U; c+ z, ^ H/ ^* m; e" g
- @{" H! j0 j9 d) l# e$ W& i
- */
U3 ` \4 [3 w - typedef struct7 t- D$ b1 T! k0 |; z" r4 L
- {9 f) O, m) ]2 L' C' d2 T
- __IO uint32_t ISER[8]; /*!< Offset: 0x000 Interrupt Set Enable Register */ @5 X3 a; Q% X( i
- uint32_t RESERVED0[24]; , Q7 Z. z/ V' t7 @" L
- __IO uint32_t ICER[8]; /*!< Offset: 0x080 Interrupt Clear Enable Register */
& v8 i# H. n. C& D% E& { - uint32_t RSERVED1[24]; % |3 b. m: M! S/ }- a, [4 ^
- __IO uint32_t ISPR[8]; /*!< Offset: 0x100 Interrupt Set Pending Register */
* D4 [* G; T6 o6 y1 m% } - uint32_t RESERVED2[24]; 5 c' M4 O$ G" o2 `2 k+ M
- __IO uint32_t ICPR[8]; /*!< Offset: 0x180 Interrupt Clear Pending Register */9 R. E: j$ U4 G- u; `$ a
- uint32_t RESERVED3[24];
; }9 |* _$ v s( ]) M - __IO uint32_t IABR[8]; /*!< Offset: 0x200 Interrupt Active bit Register */2 c" F$ w$ [ `& I
- uint32_t RESERVED4[56]; ( h: D! g- S, S) w1 I
- __IO uint8_t IP[240]; /*!< Offset: 0x300 Interrupt Priority Register (8Bit wide) */* }$ x2 ?* P s( l, z* j$ r- \. Q
- uint32_t RESERVED5[644];
! K# ~$ p4 e K) S - __O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register */1 f0 K* P* U' j! L7 X+ j$ a
- } NVIC_Type;
- M% A" |( V- M& a5 B - /*@}*/ /* end of group CMSIS_CM3_NVIC */
复制代码 7 u$ L$ G0 z. n
从上面可以了解到的是,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:
3 t h& g4 K# {% f+ t 3 \# B6 C5 P4 l2 N
以及:
9 @, Z3 k- R1 p6 J2 {/ @
/ t1 t5 |& E! J: k. x
B3.4 Nested Vectored Interrupt Controller (NVIC)的相关说明,例如:
3 m+ ?$ Y/ f. u
9 I) p3 Z% w3 V2 H3 O! D
当然,你看权威指南也可以的,在其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的自己换算一下即可): / j- k' r0 Y9 S8 w2 E
) b9 x- z- a% x5 G$ C
可以看到,STM32F10x standard peripheral library文件stm32f10x.h中的中断号的定义是能够与这里对应上的。 另外,stm32F103RB的Datasheet(CD00161566)里面的2.3.5 Nested vectored interrupt controller (NVIC)提到F103仅有43个可屏蔽中断,所以只需用到NVIC_ISER0和NVIC_ISER1来设置启用外设中断。
! j2 ]" I- I5 f |