|
下面,我们看看关于NVIC寄存器的描述,都在哪些手册里面有提到 在使用STM32F10x standard peripheral library写有关于stm32中断的程序的时候,需要开启某个特定中断的控制位,除了对应外设的寄存器之外,还需要设置NVIC的相关寄存器的对应位。例如: - /****** STM32 specific Interrupt Numbers *********************************************************/
3 o- _% `* x; w - WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */
* ^" J* h5 H1 `" Y- { - PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */+ ` q C6 x- i1 d6 O8 k! `2 i1 Z
- TAMPER_IRQn = 2, /*!< Tamper Interrupt */
' w6 e& y2 t' m# f7 e - RTC_IRQn = 3, /*!< RTC global Interrupt */
" F) c7 m$ x, k' J, n& f- `1 i - FLASH_IRQn = 4, /*!< FLASH global Interrupt */
# r/ Z+ \4 X8 w8 g/ ~$ Y# t - RCC_IRQn = 5, /*!< RCC global Interrupt */
$ Z Q" {% H ]; d+ g) F - EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */
5 S1 o: v k/ k. s - EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */4 T' i& J2 B g0 l
- EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ w$ m9 R* t: ?9 W! R
- EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */
* R* _+ X; i/ n; [' b$ Q - EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */' e. a0 C% C4 v& P5 E* Q ]8 A
- DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */
' ? Z; x0 w. T4 m( O) `8 I7 d0 m - DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */
& ~/ O# p5 c6 b! ~ C0 I - DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */0 L/ m) w* _" ]3 y" @3 f
- DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */ l2 k- ~. \' ]) \6 l' a9 O: @
- DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */4 n9 u, g. H& k5 v
- DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */# y+ X) ?9 g# o- g4 ~; w
- DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */6 E7 d" @7 u6 }3 C3 A5 y
- 0 W7 t" Y4 H, |8 d! W1 v- m
- NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
1 e3 B8 `; u g: o% r - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
! A# U+ m. s) o" B8 p - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;; r1 `: J9 b* ]2 {) f1 l' {6 {
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
3 j5 c: |+ d, a8 x - NVIC_Init(&NVIC_InitStructure);
复制代码 ( s4 {, ~8 ~/ h
而NVIC_Init()这个函数: - /**: S6 o7 ~4 g8 \' ?
- * @brief Initializes the NVIC peripheral according to the specified: ?0 o9 t0 x6 H( e
- * parameters in the NVIC_InitStruct.; a: G6 b5 c; e1 I; P5 w9 W. u
- * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains
, L! {; _7 N0 [* ^; P - * the configuration information for the specified NVIC peripheral.
: x- U% V6 C4 V0 D1 c2 S" b - * @retval None) V4 J& f% N/ |
- */
2 P: N6 j2 V* M0 `9 e- K - void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) ~: ]$ _5 w$ c- X! Z- q; h8 G
- {4 [8 g; k, |$ ^8 `8 Y0 q3 Y6 Z
- uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;0 X6 g2 f, f1 u& Y" m, a
- : s' \0 c: a. {6 I- K8 P
- /* Check the parameters */
h. d! o6 d. u5 ~2 M( s A. j - assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));9 Z/ L# K7 C: s$ {' _% M
- assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));
$ _" `6 U' x7 v2 v r - assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));: c) H0 p# |) z) M4 d
-
- a x" t; e6 j - if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)) m& ~0 i7 y1 E$ l6 Q
- {2 V# U- U0 N, g2 H. m9 N$ F
- /* Compute the Corresponding IRQ Priority --------------------------------*/
+ f5 H7 Q- h# M9 E& w# E - tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;& C- S. T/ X; _& j1 j% \8 T
- tmppre = (0x4 - tmppriority); W/ L& m6 j& [/ H$ ^
- tmpsub = tmpsub >> tmppriority;
- ]& @1 i. O" E4 _9 E+ c - ( D. i: P: ]. H1 y6 ]3 d4 `9 @7 [" q
- tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;; ~ D9 j7 P1 {3 c5 a& m
- tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;6 B( o' [1 X& {0 P: r0 k
- tmppriority = tmppriority << 0x04;- ~# E7 ~! z9 z2 O$ M+ T9 Y* c5 N
-
+ ]+ u6 J; D; F - NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
' a: v4 c) f! u) m+ A( _ - 9 P# ] i3 {. ^- O
- /* Enable the Selected IRQ Channels --------------------------------------*/
$ F. N6 H, F( p( C# Q' O' k) b* c - NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =$ D( F' d$ r; G/ W
- (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
8 g( M0 w p" @1 a5 ~* X; C0 M - }; E& h3 Q1 x' r" @- r1 q8 X
- else( W, Y5 |" T' m3 {
- {* O7 D4 ~4 p0 @1 U8 e- y
- /* Disable the Selected IRQ Channels -------------------------------------*/
: P6 j! \* H& E' i8 ?" E! x8 y - NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = Q& Q+ F: U0 M$ O8 ]
- (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);+ U; {# x6 ~$ N
- }
: o8 i: k# g( A0 ^+ D C - }
复制代码
6 g' `/ q& \2 g3 W3 a3 k: S: g可以看到,它会去设置几个寄存器:NVIC的IP,ISER,ICER等等,NVIC是基址,为: - #define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */+ E) v! D3 ?5 o* @; H3 y2 Q! _
- #define NVIC_BASE (SCS_BASE + 0x0100) /*!< NVIC Base Address */3 N( w% O7 u0 P% ?' T
- #define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */
5 l5 s* s$ O. v0 N }
# K3 R. R" _3 ?9 m! T- - X- y4 `3 y3 |# z
- #define NVIC ((NVIC_Type *) NVIC_BASE) /*!< NVIC configuration struct */
复制代码 ; n) v! e% b. ]$ ^7 C( p3 W/ E
NVIC_Type为: - /** @addtogroup CMSIS_CM3_NVIC CMSIS CM3 NVIC
; o+ s/ R" D' Q, ? - memory mapped structure for Nested Vectored Interrupt Controller (NVIC)# \" t& X9 q. A2 c: a2 a8 f
- @{
% M. p) v, M5 a5 P1 M1 i. \ - */
: i" ^$ x; u4 r5 w9 L - typedef struct
8 U6 c$ d$ {, Q: [; j p3 f. i- _ - {
+ @! @4 H2 t9 m8 L - __IO uint32_t ISER[8]; /*!< Offset: 0x000 Interrupt Set Enable Register */
/ t7 Z; [, i& j4 G' E, Y9 @8 Y7 _ - uint32_t RESERVED0[24]; 4 v, m7 ]( ?1 O- K; a4 \- ^
- __IO uint32_t ICER[8]; /*!< Offset: 0x080 Interrupt Clear Enable Register */8 l* P) w$ G G
- uint32_t RSERVED1[24]; 9 X/ E& \9 X, g' Y% o* }" z
- __IO uint32_t ISPR[8]; /*!< Offset: 0x100 Interrupt Set Pending Register */
. _$ M- e; y5 Z1 A3 U - uint32_t RESERVED2[24];
) Y/ ]" L) z. [; L5 x- q3 O# _ - __IO uint32_t ICPR[8]; /*!< Offset: 0x180 Interrupt Clear Pending Register */
" @' b1 E: Z/ }9 ~2 V& Z - uint32_t RESERVED3[24];
d, @, H3 W: K/ J( j - __IO uint32_t IABR[8]; /*!< Offset: 0x200 Interrupt Active bit Register */
9 P. ]* W" V9 v4 @3 p, V4 ~; X - uint32_t RESERVED4[56]; , ~: N/ r4 s6 o( R
- __IO uint8_t IP[240]; /*!< Offset: 0x300 Interrupt Priority Register (8Bit wide) */* G6 o6 r0 l& }/ n B
- uint32_t RESERVED5[644];
) ^ E( D9 U( J$ e, F+ K+ t L% y' P - __O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register */( Y/ a/ A4 _, q* N7 a* G
- } NVIC_Type;
. e+ A+ o, e* y2 W8 U1 [6 \/ U6 a - /*@}*/ /* end of group CMSIS_CM3_NVIC */
复制代码 1 E# o7 T+ e: e. Q. Q. 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: ( J7 Z) L0 ]" h! R5 a( K
+ S1 j9 \; r& v2 {6 n
以及:
]) H' R, I3 }) c$ ^
! v s- l$ z8 b) u; V- @! x
B3.4 Nested Vectored Interrupt Controller (NVIC)的相关说明,例如: 1 |. u- u/ A, ? N
8 ]! {9 h1 D6 S# d# n* 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的自己换算一下即可): , ]8 u3 [7 [2 y0 j
7 l! u$ S. f. j- Z) J
可以看到,STM32F10x standard peripheral library文件stm32f10x.h中的中断号的定义是能够与这里对应上的。 另外,stm32F103RB的Datasheet(CD00161566)里面的2.3.5 Nested vectored interrupt controller (NVIC)提到F103仅有43个可屏蔽中断,所以只需用到NVIC_ISER0和NVIC_ISER1来设置启用外设中断。 ! y% f3 n3 q7 L
|