要使用STM32,需要各種文檔,其中有(以STM32F103RBT6為例):
st官方資源地址:http://www.st.com/internet/mcu/product/164487.jsp
1、datasheet:http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00161566.pdf
2、REFERENCE MANUALS:http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/CD00171190.pdf
3、ERRATA SHEETS:http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/ERRATA_SHEET/CD00190234.pdf
4、STM32F10x standard peripheral library:http://www.st.com/internet/com/SOFTWARE_RESOURCES/SW_COMPONENT/FIRMWARE/stm32f10x_stdperiph_lib.zip
ARM官方:
5、Cortex-M3 Technical Reference Manual Revision r1p1:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0337e/DDI0337E_cortex_m3_r1p1_trm.pdf
6、ARMv7M Architecture Reference Manual:http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0403c/index.html
非官方的:
The Definitive Guide to the ARM Cortex-M3(中文名:Cortex-M3 權威指南),雖然非官方,但很權威
下面,我們看看關於NVIC寄存器的描述,都在哪些手冊里面有提到
在使用STM32F10x standard peripheral library寫有關於stm32中斷的程序的時候,需要開啟某個特定中斷的控制位,除了對應外設的寄存器之外,還需要設置NVIC的相關寄存器的對應位。例如:
/****** STM32 specific Interrupt Numbers *********************************************************/ WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */ TAMPER_IRQn = 2, /*!< Tamper Interrupt */ RTC_IRQn = 3, /*!< RTC global Interrupt */ FLASH_IRQn = 4, /*!< FLASH global Interrupt */ RCC_IRQn = 5, /*!< RCC global Interrupt */ EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */ DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */ DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */ DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */ DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */ DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */ DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
而NVIC_Init()這個函數:
/** * @brief Initializes the NVIC peripheral according to the specified * parameters in the NVIC_InitStruct. * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains * the configuration information for the specified NVIC peripheral. * @retval None */ void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) { uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F; /* Check the parameters */ assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd)); assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority)); if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE) { /* Compute the Corresponding IRQ Priority --------------------------------*/ tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08; tmppre = (0x4 - tmppriority); tmpsub = tmpsub >> tmppriority; tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre; tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub; tmppriority = tmppriority << 0x04; NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority; /* Enable the Selected IRQ Channels --------------------------------------*/ NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); } else { /* Disable the Selected IRQ Channels -------------------------------------*/ NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); } }
可以看到,它會去設置幾個寄存器:NVIC的IP,ISER,ICER等等,NVIC是基址,為:
#define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */ #define NVIC_BASE (SCS_BASE + 0x0100) /*!< NVIC Base Address */ #define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */ #define NVIC ((NVIC_Type *) NVIC_BASE) /*!< NVIC configuration struct */
NVIC_Type為:
/** @addtogroup CMSIS_CM3_NVIC CMSIS CM3 NVIC memory mapped structure for Nested Vectored Interrupt Controller (NVIC) @{ */ typedef struct { __IO uint32_t ISER[8]; /*!< Offset: 0x000 Interrupt Set Enable Register */ uint32_t RESERVED0[24]; __IO uint32_t ICER[8]; /*!< Offset: 0x080 Interrupt Clear Enable Register */ uint32_t RSERVED1[24]; __IO uint32_t ISPR[8]; /*!< Offset: 0x100 Interrupt Set Pending Register */ uint32_t RESERVED2[24]; __IO uint32_t ICPR[8]; /*!< Offset: 0x180 Interrupt Clear Pending Register */ uint32_t RESERVED3[24]; __IO uint32_t IABR[8]; /*!< Offset: 0x200 Interrupt Active bit Register */ uint32_t RESERVED4[56]; __IO uint8_t IP[240]; /*!< Offset: 0x300 Interrupt Priority Register (8Bit wide) */ uint32_t RESERVED5[644]; __O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register */ } NVIC_Type; /*@}*/ /* end of group CMSIS_CM3_NVIC */
從上面可以了解到的是,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:

以及:

以及ARMv7-M Architecture Reference Manual中,B3.4 Nested Vectored Interrupt Controller (NVIC)的相關說明,例如:

當然,你看權威指南也可以的,在其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的自己換算一下即可):

可以看到,STM32F10x standard peripheral library文件stm32f10x.h中的中斷號的定義是能夠與這里對應上的。
另外,stm32F103RB的Datasheet(CD00161566)里面的2.3.5 Nested vectored interrupt controller (NVIC)提到F103僅有43個可屏蔽中斷,所以只需用到NVIC_ISER0和NVIC_ISER1來設置啟用外設中斷。
【The STM32F103xx performance line embeds a nested vectored interrupt controller able to handle up to 43 maskable interrupt channels (not including the 16 interrupt lines of Cortex™-M3) and 16 priority levels.】
得查閱這么多文檔,才能知道這個Interrupt Set-Enable Registers寄存器在哪里有描述,怎么設置,文檔很分散。這些文檔估計是程序員組織的,呵呵。因為像這些M3內核的相關模塊,與外設無關的,只要是M3內核的器件都是通用的,所以不用每個器件的手冊都帶,這樣比較節省空間,⊙﹏⊙b汗
所以,以后要是涉及到M3內核相關的,都得去查閱《M3權威指南》或者官方的《Cortex-M3 Technical Reference Manual》以及《ARMv7M Architecture Reference Manual》。
2012年9月13日17:43:13 更新:
根據xieyudi的回復,查看了PM0056: STM32F10xxx/20xxx/21xxx/L1xxxx Cortex-M3 programming manual
里面對於M3內核的部分介紹的比較詳細,關於NVIC,SCB寄存器的說明都有了,基本可以不用看ARM的官方文檔即可編程。感謝xieyudi網友
順帶,Flash相關的說明在:PM0075: STM32F10xxx Flash memory microcontrollers
