|
下面,我们看看关于NVIC寄存器的描述,都在哪些手册里面有提到 在使用STM32F10x standard peripheral library写有关于stm32中断的程序的时候,需要开启某个特定中断的控制位,除了对应外设的寄存器之外,还需要设置NVIC的相关寄存器的对应位。例如: - /****** STM32 specific Interrupt Numbers *********************************************************/8 r9 Q' @4 ` e/ d7 C. Y# w
- WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */2 C( U( t2 |, B/ W9 h6 h
- PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */; }9 H2 V+ u4 T1 `" a) \
- TAMPER_IRQn = 2, /*!< Tamper Interrupt */
: _4 F/ o, W7 ~6 t - RTC_IRQn = 3, /*!< RTC global Interrupt */
' l6 ? l% a" F( t4 t - FLASH_IRQn = 4, /*!< FLASH global Interrupt */
. p; ~1 ]1 v; Y" w1 H. B - RCC_IRQn = 5, /*!< RCC global Interrupt */
+ t. v$ F: V9 k7 N - EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */, ^- G# B! ?. o p& @. k
- EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */
) w! n2 u) K0 M+ v/ C# @* Q+ A - EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */) L7 Z" \8 j, ^( c1 E( P3 ]) w
- EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */0 Z8 m' ~% ~. ~1 Z! m$ Q5 X) ]
- EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */. p2 ^# u; F* S7 r
- DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */5 k, \( G2 E2 g' A
- DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */
, |7 C* g/ I/ i# `, y, X9 Z8 O - DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */
$ F, l$ }+ o* r* w$ Q3 V/ o - DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */8 U, p; g' J* F3 p# k
- DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */
: _' X8 X0 r; ?, k. I$ P, Y - DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */
6 D: I4 d$ q1 Z5 a3 @ - DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */
- a/ d- h A* `; e
: H/ \, w4 }8 I8 p3 u! F9 Q, s. _- NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
# N: y' @! Z) g. a8 G2 O+ n$ F - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;- `3 e6 n! l2 \
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;$ ^ ~6 {7 H7 r, r
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
& G& C3 @5 T- y; C. e" N* X# e - NVIC_Init(&NVIC_InitStructure);
复制代码
8 q, m- ]* M, |& d' q而NVIC_Init()这个函数: - /**
/ F1 C( P# v3 o8 `" [ - * @brief Initializes the NVIC peripheral according to the specified2 U' Y) K/ L8 {) b7 n$ s5 v- a
- * parameters in the NVIC_InitStruct.5 X3 @2 N* v1 z/ A- I: k
- * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains# ?& v* ]$ O3 ?7 c
- * the configuration information for the specified NVIC peripheral.
# d3 f- ]2 F' | - * @retval None _2 o( A2 j: y; s2 R
- */
/ B) E; }& G" N2 V3 { - void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
: \( p! i2 V3 M% G! ` - {
, C3 @9 _$ m& P - uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
. k) e2 `2 a9 d; m/ r - - O1 U" p1 L# U' M9 U3 j
- /* Check the parameters */% C, Y( x2 x( D
- assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));/ C9 h( `4 S$ [% O/ {4 h. A4 K
- assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); + r( A. e- q0 l& N$ W5 V% ^1 I
- assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));+ D) S9 u8 ^6 N* m+ H0 w+ w
-
& s) _& @( s% T2 w - if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)- h: p4 ]% A' C
- {
- @9 y6 V% N0 J5 u B- E" O - /* Compute the Corresponding IRQ Priority --------------------------------*/
1 V% \+ P% D* g# U& Y9 P: n k - tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
) C) Q, A2 r8 j( } - tmppre = (0x4 - tmppriority);- f4 R5 R, p2 g* X3 Y3 s8 {
- tmpsub = tmpsub >> tmppriority;; v- A l% \7 { f- j ~/ }. `& b
- i8 Q% S2 W# [4 L
- tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;+ d$ c! i I2 c5 R! h
- tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
" j d+ d& Q- h0 S - tmppriority = tmppriority << 0x04;
4 L( Y! t$ ~% a, x# r$ o - " ]) ^: _7 S6 ]; h4 I
- NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;; X( J7 O) _7 X7 d* k% p
-
, Y' A- j' P" N4 M8 X8 Q - /* Enable the Selected IRQ Channels --------------------------------------*/1 c" W3 p" F+ m' a! h
- NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =3 I# a) a# v5 l y
- (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
: t, k" b, D3 X' |- h0 E - }2 r. z4 M1 W- [% x- ^+ c
- else
D( Q1 K' D) u; \! s2 N7 m1 E: I - {
1 v! ~2 x2 p% A ~( | - /* Disable the Selected IRQ Channels -------------------------------------*/& K1 E8 K0 Z+ D" U' z4 ^3 T
- NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =) B* g* J% g( p) u
- (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
- I3 U4 V2 F1 O" _ - }/ j3 Q4 f9 h) N4 @
- }
复制代码 6 ~! w0 q! k* Y- W8 `; R D
可以看到,它会去设置几个寄存器:NVIC的IP,ISER,ICER等等,NVIC是基址,为: - #define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */( D, T. R1 `7 G6 Y: q( _: R
- #define NVIC_BASE (SCS_BASE + 0x0100) /*!< NVIC Base Address */
6 s) P. |, m- V ~4 y. [) X' T. @ - #define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */
# y" ^4 r: i, S$ [ - ; d. E1 J( y1 Z8 `5 ]* A9 Q9 C
; t, I* U4 q' u% L; C% _4 T8 h. D Q- #define NVIC ((NVIC_Type *) NVIC_BASE) /*!< NVIC configuration struct */
复制代码
% h" ^- n' E% c8 W. Q& qNVIC_Type为: - /** @addtogroup CMSIS_CM3_NVIC CMSIS CM3 NVIC: G# M8 B" h: l' U! T$ n
- memory mapped structure for Nested Vectored Interrupt Controller (NVIC)! X% P) @, h3 _, j: H ]
- @{# r/ F) K* o6 j- L
- */8 B8 }5 b& v3 s' `) ^% ?; e5 D
- typedef struct
( y, Q! ?: N' F) T7 H6 F- {, e - {6 r& b/ I1 E7 p6 ]4 F& l
- __IO uint32_t ISER[8]; /*!< Offset: 0x000 Interrupt Set Enable Register */
- q/ s$ Y7 M1 ]+ C1 {$ ] - uint32_t RESERVED0[24]; ( r, n( Y: a) R8 s+ K/ ]
- __IO uint32_t ICER[8]; /*!< Offset: 0x080 Interrupt Clear Enable Register *// r4 d0 N% [/ K# L1 D- p8 P, G
- uint32_t RSERVED1[24];
T4 {) O* n* i4 O+ ?8 ?. o - __IO uint32_t ISPR[8]; /*!< Offset: 0x100 Interrupt Set Pending Register */
" \2 O' Z2 ~# B v& D8 F0 k8 ~ - uint32_t RESERVED2[24];
) @+ w, p2 Z8 H! V8 }. G - __IO uint32_t ICPR[8]; /*!< Offset: 0x180 Interrupt Clear Pending Register */2 P" y7 K3 h N! Z& l
- uint32_t RESERVED3[24];
; X4 Y* q1 C7 \6 F& Y" \; @8 h - __IO uint32_t IABR[8]; /*!< Offset: 0x200 Interrupt Active bit Register */" ~5 c% E7 q% U" r3 T
- uint32_t RESERVED4[56];
) F$ M# e6 E4 Q ^9 V# A - __IO uint8_t IP[240]; /*!< Offset: 0x300 Interrupt Priority Register (8Bit wide) */
( }0 w& p( Y) u: K: @+ C/ ? - uint32_t RESERVED5[644];
5 ^! }5 J2 j% _* X1 K; N - __O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register */) y& P) Z- U% E6 g$ W0 N, J7 n' k
- } NVIC_Type;
% H4 b! i1 e6 n. P# c: W2 Y - /*@}*/ /* end of group CMSIS_CM3_NVIC */
复制代码 9 |: C6 I0 k: w4 ~1 Q
从上面可以了解到的是,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 D! w) J* O1 `+ A0 u, B5 p' V3 @+ J
( h0 U( ^( ]/ }" x2 {$ e. d2 K以及: & E, D; c8 U3 y- G
$ a' d$ ^2 S, ~% [5 X. I: U
B3.4 Nested Vectored Interrupt Controller (NVIC)的相关说明,例如:
/ l |0 T' a4 L. g) g( K
- X5 e) m3 @' 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的自己换算一下即可): # Q, _( @5 n! g1 {3 v- ^. j5 G0 l' W
N$ D7 d2 @- l- e( {& T
可以看到,STM32F10x standard peripheral library文件stm32f10x.h中的中断号的定义是能够与这里对应上的。 另外,stm32F103RB的Datasheet(CD00161566)里面的2.3.5 Nested vectored interrupt controller (NVIC)提到F103仅有43个可屏蔽中断,所以只需用到NVIC_ISER0和NVIC_ISER1来设置启用外设中断。
" j1 N+ ]! _8 M3 `6 N |