下面,我们看看关于NVIC寄存器的描述,都在哪些手册里面有提到 在使用STM32F10x standard peripheral library写有关于stm32中断的程序的时候,需要开启某个特定中断的控制位,除了对应外设的寄存器之外,还需要设置NVIC的相关寄存器的对应位。例如: - /****** STM32 specific Interrupt Numbers *********************************************************/
( F* o2 O4 {% g, C - WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */
3 M5 T. N7 r7 [( _ - PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */' w7 ]6 t. a7 ~: L' O
- TAMPER_IRQn = 2, /*!< Tamper Interrupt */% T+ D- t& F8 p& e7 |. ` R
- RTC_IRQn = 3, /*!< RTC global Interrupt */
( X( m0 D( t0 |* q7 @" Q - FLASH_IRQn = 4, /*!< FLASH global Interrupt */
& n: L9 T9 y) [) V - RCC_IRQn = 5, /*!< RCC global Interrupt */+ O9 j; T$ u" i) T$ G# y3 F
- EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */+ }: }2 q' I+ {. Q, t# S" l3 {* j
- EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */
/ q3 O' B6 N% v! i( D# q5 x/ P - EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */
) I! f/ L m7 c4 L; i7 s - EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */- Y* r& Z' ^; P% P1 W. [9 R5 J8 M4 ]. ]
- EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */
L+ S) ]# K/ f, F! A - DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */
; s8 d( `# X" Q# j( ] F2 S - DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */& Z7 V$ S, E6 Q! b
- DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */
0 j$ K9 \' M- F$ B - DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */
1 I/ n# x, R( ~ - DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */
5 F& c! \; j8 D7 s. h - DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */
: W( a9 ~2 ?, p1 Q5 z" V3 M- p8 O - DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */ ~) b5 @; J# b+ b8 D" L6 j8 x
- 3 W& a c+ \- a: F
- NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
$ r( h/ q, V5 [ }3 H$ g - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;2 i+ E& l0 @6 G3 O. w; b' g, `
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;) h y' ~: a- y2 V
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
: @2 O$ [% P" u( k4 Y( k1 ~ - NVIC_Init(&NVIC_InitStructure);
复制代码
/ Y# B8 _7 @) S6 V. y1 N. r3 S; M而NVIC_Init()这个函数: - /**! g2 t7 W* b: ~) k) O# S
- * @brief Initializes the NVIC peripheral according to the specified" F1 a- z. W$ o* V( P
- * parameters in the NVIC_InitStruct.
8 c" @5 }' e+ z* a/ L - * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains6 L1 q7 c) W& b, i. M. w
- * the configuration information for the specified NVIC peripheral./ \* q; x. z* s9 v
- * @retval None
- D5 u: W" x1 b# @/ z+ T - */
5 I2 M7 b) U& j; B5 u6 p+ F - void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct). t7 z- {; M5 f% q* f/ ^
- {
7 I' ?% k- q# b% U5 E" s9 S - uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;2 M9 Q- Z4 J+ I
-
1 r5 H7 P1 _. U2 o! K - /* Check the parameters */. } T- a u9 e2 y+ n+ C+ Y
- assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));7 x X4 a2 d' _2 L. k7 \
- assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); ! e2 g5 v( k5 R& T6 b/ E$ k; ]( z
- assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
+ x! v% ~7 W& i# X: z5 s - . k/ N1 @% S7 O
- if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
3 _& E( y/ \. N Y4 G - {7 W7 E# Q9 k5 r- E
- /* Compute the Corresponding IRQ Priority --------------------------------*/
, H' L& X; ~/ `+ p/ f5 i - tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;' p, l' r. D# \; W. }. D0 n( B4 {
- tmppre = (0x4 - tmppriority);) R8 x1 D$ O( {. @ F4 H
- tmpsub = tmpsub >> tmppriority;
. C/ G/ g7 q9 N4 }+ B% b3 W" z8 x: Y7 Y
$ d; @$ ~9 [" K5 k+ z1 ~2 `- tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;! o! }. ` m. o' Q
- tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
! l6 A5 |0 f1 b' l7 z6 Y - tmppriority = tmppriority << 0x04;/ s% B) m* y# i, X! V' |$ r8 y
- . \' N" E1 T9 G; M2 V# @
- NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;0 S# a+ P. D, Q; y" E2 `$ N* k4 w
-
% N6 c( q' ?" Y( o# A* E7 V+ l% V1 R - /* Enable the Selected IRQ Channels --------------------------------------*/+ P1 W+ R; n/ x6 K& ~5 a% v5 n
- NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =0 y: q! M7 ?# o! e4 o( o
- (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);% s4 K3 C. o. z* ? v6 h" _
- }+ W3 o0 J& ^% A0 T1 m" i
- else3 w: X4 a. S2 O! d
- {
- H* T# [- r. r1 _ - /* Disable the Selected IRQ Channels -------------------------------------*/
; S; y% V4 l! |& D/ Y4 | - NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
; Z! t2 O, x* k1 ^ - (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);4 G5 \$ M C& h3 u) t
- }% i- M2 c% X+ n& H! r. ~0 d
- }
复制代码 ) p0 Z- J( m4 `1 b: @ [: K* y
可以看到,它会去设置几个寄存器:NVIC的IP,ISER,ICER等等,NVIC是基址,为: - #define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */
2 O' X5 D0 R& C: b - #define NVIC_BASE (SCS_BASE + 0x0100) /*!< NVIC Base Address */" ]/ R3 C2 I: d: u. j# k
- #define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */
7 o; k( r6 K" k x3 m& w8 M- I
, K2 d& ^# a# I- q5 |# I- . y9 e5 i, x( \: R: r+ [( R/ `9 {
- #define NVIC ((NVIC_Type *) NVIC_BASE) /*!< NVIC configuration struct */
复制代码 " H* d/ u/ U) j' R) H+ c
NVIC_Type为: - /** @addtogroup CMSIS_CM3_NVIC CMSIS CM3 NVIC& ~; R) B! h2 \& q) _
- memory mapped structure for Nested Vectored Interrupt Controller (NVIC)
_9 f+ l' t, F) O3 V - @{
4 k- E. h4 J8 N4 E+ V - */
2 }: i3 z5 G$ e% E9 M( Y - typedef struct/ p% g/ X+ u. J2 ^2 J/ u. b7 Y8 Z3 |
- {
: x; `3 x" x3 C. [) i! C7 Y - __IO uint32_t ISER[8]; /*!< Offset: 0x000 Interrupt Set Enable Register */- u$ H2 x* ^6 u/ e2 e
- uint32_t RESERVED0[24];
. _, v, J. L) _5 p# T - __IO uint32_t ICER[8]; /*!< Offset: 0x080 Interrupt Clear Enable Register */
& k" g% m, d2 y5 e - uint32_t RSERVED1[24]; / k6 p6 B, q% r3 p% ~1 M, C9 e6 i. `
- __IO uint32_t ISPR[8]; /*!< Offset: 0x100 Interrupt Set Pending Register */( w! r+ Z9 B. s$ i
- uint32_t RESERVED2[24];
7 B: P& \' {6 [' R. l - __IO uint32_t ICPR[8]; /*!< Offset: 0x180 Interrupt Clear Pending Register */
1 Q6 H. v5 }2 @ - uint32_t RESERVED3[24]; + ^/ P( L& J7 i* w6 \: D
- __IO uint32_t IABR[8]; /*!< Offset: 0x200 Interrupt Active bit Register */
1 F3 Z) s7 c+ c* m& m* u - uint32_t RESERVED4[56];
% R; K o8 d. S1 M" d - __IO uint8_t IP[240]; /*!< Offset: 0x300 Interrupt Priority Register (8Bit wide) */
- B% m/ ~) e$ U$ b - uint32_t RESERVED5[644];
( w* S9 _% [' o8 m - __O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register */
$ \5 f& Q2 ^# u6 `9 a& Y$ A - } NVIC_Type;
: L9 m; A% V; o4 h3 j/ C - /*@}*/ /* end of group CMSIS_CM3_NVIC */
复制代码
& W3 V3 B% m* L从上面可以了解到的是,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:
- K3 s% Y+ [. l/ H. @, Z 4 Y' z0 d( {5 _9 }* T# {' ?" W; E7 n
以及: 1 _+ h7 w: _1 o- d0 @: n
2 x% u1 [7 X4 m. Y0 t4 s
B3.4 Nested Vectored Interrupt Controller (NVIC)的相关说明,例如:
" h; c2 I) T2 F3 @( S7 {' H2 O
" A% c- u, M4 y
当然,你看权威指南也可以的,在其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的自己换算一下即可):
! P* a- r: r* }) L8 W
( \' X( U. ~8 \- w) M, i
可以看到,STM32F10x standard peripheral library文件stm32f10x.h中的中断号的定义是能够与这里对应上的。 另外,stm32F103RB的Datasheet(CD00161566)里面的2.3.5 Nested vectored interrupt controller (NVIC)提到F103仅有43个可屏蔽中断,所以只需用到NVIC_ISER0和NVIC_ISER1来设置启用外设中断。 5 T* ~4 F& _0 b
|