|
下面,我们看看关于NVIC寄存器的描述,都在哪些手册里面有提到 在使用STM32F10x standard peripheral library写有关于stm32中断的程序的时候,需要开启某个特定中断的控制位,除了对应外设的寄存器之外,还需要设置NVIC的相关寄存器的对应位。例如: - /****** STM32 specific Interrupt Numbers *********************************************************/+ e' Y8 o" ]9 M2 K2 ^1 P
- WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */# T. I+ f: j2 p
- PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */# @* l) X: i: `. G
- TAMPER_IRQn = 2, /*!< Tamper Interrupt */: v% Y9 H* j. T$ c9 o! w+ o& m
- RTC_IRQn = 3, /*!< RTC global Interrupt */
: K0 j i; }: a. A3 e - FLASH_IRQn = 4, /*!< FLASH global Interrupt */, F: L) s* x. Y+ H% M" B- S
- RCC_IRQn = 5, /*!< RCC global Interrupt */
* \- d3 p% ]' J& M) c5 K% Y - EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */, f W: O' S) S% h, @7 @
- EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */
, e' G& B. y) o0 i& P$ l* u0 |( y - EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */9 `9 b* _, i5 l \) @3 Y
- EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */
) X* q8 e; K! k! v& e9 e5 U - EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */
# } r9 E& \# _/ E - DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */
( m$ z+ o9 U( ^9 u - DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */" M! v- j5 u* u& W) j- O
- DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */
, r/ q- t5 ` l% _- ]4 h - DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */5 s/ \: Q+ k2 T+ e& |) l7 a- K2 y8 g
- DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */$ Y& |" ]- e( A! l+ }+ L* H8 Z
- DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */
1 P) p0 D9 N3 d2 c - DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */
6 z$ f1 P6 U( f' k, f
6 B& _' S! f: e* o) c+ I- NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
; G6 H4 F% D" P; _; ~/ z5 o - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
) p/ D- E: s! M$ p% x" s: T - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;1 S; c7 s/ ^$ @1 L; y
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;7 E5 F$ i; J! M6 h* B
- NVIC_Init(&NVIC_InitStructure);
复制代码 ! u2 |: ^ |- T7 F0 }1 V4 P- w$ O8 q5 f& ]
而NVIC_Init()这个函数: - /**
4 {# t' M3 h/ E$ U) n - * @brief Initializes the NVIC peripheral according to the specified# m! M, X* Q. i+ Z
- * parameters in the NVIC_InitStruct.9 V& Y1 [& V6 T T
- * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains
- S( h, {/ [+ [, ~- |7 Z - * the configuration information for the specified NVIC peripheral.& ^( c. Y h# }$ v/ w# n
- * @retval None+ _2 z2 u+ g& ~8 b6 }( n! i" }6 ?0 y
- */
& ^! e% [* N8 F7 c; x7 Z0 { - void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
/ n# Z" x, C+ R - {
" R* V8 }$ @( W9 u - uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
6 L2 \! `; W2 ~# F. U0 G4 k -
. m9 N \6 R8 h3 v& [' m$ R* F - /* Check the parameters */4 H- d( _( U, _
- assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));* p, Y$ w. A2 e* v
- assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); ; w& C; l `7 _; d$ S% G) L
- assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
1 c& V3 ?( ~. s! K - % |1 F/ q; a; W" a8 ]6 \
- if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
$ O) w0 { L2 \8 H/ U1 q - {
" [+ J4 s. W, I+ p* M1 u4 k - /* Compute the Corresponding IRQ Priority --------------------------------*/ $ C7 e5 d. c) v; V3 a1 Y+ ~
- tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08; N& z6 z% U) f! n) P) Z
- tmppre = (0x4 - tmppriority);
6 P7 o0 w3 h5 T/ V - tmpsub = tmpsub >> tmppriority;
- `# [# Y' `6 w7 p
! d$ N8 _# ?. S# K" i, \- tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;$ M2 D4 j% H3 d/ g; U: N+ z, X! B5 i
- tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
0 ^+ T0 }0 ]3 J# n2 u( O. g- r Z - tmppriority = tmppriority << 0x04;1 H7 `- E2 b5 f6 E' {$ o: i
-
3 G# X2 u4 O, I8 o& \ - NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;- n, Z2 Q3 n7 G( H9 x% g
-
% c) w9 s; G G* x8 z - /* Enable the Selected IRQ Channels --------------------------------------*/$ s; j- E( `; V6 J- I* U8 t& q
- NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =3 K6 p* M* G3 m7 J% ^% S% A
- (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);2 L7 ]% S! @* S4 ~$ {0 `
- }- k9 \2 Y3 C1 W& A
- else
& f9 J$ @6 e; ] - {$ p- x; J! @' ^% A! U% G6 q
- /* Disable the Selected IRQ Channels -------------------------------------*/* \, d: O# b' c" c
- NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
5 |- q+ N! L2 w j% l: f! } - (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);+ {: `% W+ q' F
- }$ P7 w7 c1 }' I
- }
复制代码 ( D; y d4 y- x- S: K1 ?$ n1 v6 |
可以看到,它会去设置几个寄存器:NVIC的IP,ISER,ICER等等,NVIC是基址,为: - #define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */
5 g7 `+ e" n) U7 I# d4 V0 H" k - #define NVIC_BASE (SCS_BASE + 0x0100) /*!< NVIC Base Address */
. |) @" C; [ s# B9 ~ - #define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */
; O0 {( r) ^" a - / }* ]6 \3 P% S; _
6 W8 X1 s0 p- V2 S- #define NVIC ((NVIC_Type *) NVIC_BASE) /*!< NVIC configuration struct */
复制代码
1 y0 @0 v7 r+ V% ^4 wNVIC_Type为: - /** @addtogroup CMSIS_CM3_NVIC CMSIS CM3 NVIC
9 L2 [8 T; i$ K6 x" p. @9 A - memory mapped structure for Nested Vectored Interrupt Controller (NVIC)
6 L% o& r9 o7 P+ L; H* L0 Y: Z - @{ f: P$ e! q' D. d
- */
% R( {1 ^& w: m5 ?+ [9 w - typedef struct
" D. W" i: L# T6 G/ b - {
* F% {9 g( _* [* R4 I/ d6 i - __IO uint32_t ISER[8]; /*!< Offset: 0x000 Interrupt Set Enable Register */; X; N% x2 B% q4 N* P
- uint32_t RESERVED0[24];
u4 W" v: G; N. {' Q - __IO uint32_t ICER[8]; /*!< Offset: 0x080 Interrupt Clear Enable Register */1 n6 u, S; H! D1 Q; x' T- n
- uint32_t RSERVED1[24];
% l* b# c7 q8 w9 y% K- l - __IO uint32_t ISPR[8]; /*!< Offset: 0x100 Interrupt Set Pending Register */
5 Z) x! ]3 ]1 T5 g- o1 g - uint32_t RESERVED2[24]; 0 I% E$ u7 Y5 a e
- __IO uint32_t ICPR[8]; /*!< Offset: 0x180 Interrupt Clear Pending Register */
0 \; P8 [# k, o7 q - uint32_t RESERVED3[24];
9 U$ K. \8 r4 k6 f - __IO uint32_t IABR[8]; /*!< Offset: 0x200 Interrupt Active bit Register */$ |! K4 k3 t$ k2 ?: c ]5 ^/ K
- uint32_t RESERVED4[56]; ( c+ y ?7 [1 k4 z2 j
- __IO uint8_t IP[240]; /*!< Offset: 0x300 Interrupt Priority Register (8Bit wide) */ {- o% S) g. [' e
- uint32_t RESERVED5[644];
% e3 C" H* f2 q& n3 {. q2 u - __O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register *// ^( b; i% Q- [, w6 x9 J
- } NVIC_Type; 1 \( b7 }: A' B; X
- /*@}*/ /* end of group CMSIS_CM3_NVIC */
复制代码 8 Z& f( p5 w0 I
从上面可以了解到的是,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:
4 J9 c1 C. T# E* k5 w* ^ & @' k X! n* `0 x* ]1 _/ Y
以及:
# W3 \! y" g; u ]0 Z |
& c4 Q5 ]3 R7 o% D
B3.4 Nested Vectored Interrupt Controller (NVIC)的相关说明,例如:
3 H% u' ~/ T5 U9 v- a
) s1 p/ x( ~1 S3 G6 G9 ]+ l$ g
当然,你看权威指南也可以的,在其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的自己换算一下即可):
2 _' e# |, J- M. A0 _. w
) [% ^( [1 ?- g' Q/ l* A" ?
可以看到,STM32F10x standard peripheral library文件stm32f10x.h中的中断号的定义是能够与这里对应上的。 另外,stm32F103RB的Datasheet(CD00161566)里面的2.3.5 Nested vectored interrupt controller (NVIC)提到F103仅有43个可屏蔽中断,所以只需用到NVIC_ISER0和NVIC_ISER1来设置启用外设中断。
c$ U: b+ u7 E. M# d1 | |