中斷,在單片機中佔有很是重要的地位。代碼默認地從上向下執行,遇到條件或者其餘語句,會按照指定的地方跳轉。而在單片機執行代碼的過程當中,不免會有一些突發的狀況須要處理,這樣就會打斷當前的代碼,待處理完突發狀況以後,程序會回到被打斷的地方繼續執行。git
外部中斷/事件控制器(EXTI)管理了控制器的 23 箇中斷/事件線。每一箇中斷/事件線都對應有一個邊沿檢測器,能夠實現輸入信號的上升沿檢測和降低沿的檢測。EXTI 能夠實現對每一箇中斷/事件線進行單獨配置,能夠單獨配置爲中斷或者事件,以及觸發事件的屬性。github
外部信號進入通過1的邊沿檢測電路,檢測是否符合(有2和3的上升沿和降低沿選擇寄存器決定),產生信號,而後和4軟件中斷事件寄存器或值,(在這裏也就說能夠寫入軟件中斷事件寄存器模擬中斷和事件),以後產生信號一分爲二,看5中斷屏蔽寄存器和7事件屏蔽寄存器,若是中斷和事件都沒有屏蔽,首先會產生事件,進入脈衝發生器。其次,會進入6掛起寄存器,而後進入NVIC。編程
注意:app
一、上面說,咱們可使用寄存器4軟件模擬中斷事件寄存器模式符合條件的信號進入,爲何不能用6寄存器呢?由於框架
寄存器是可讀可清除的寄存器,經過寫1清除。寫0無效。因此不能使用函數
二、關於掛起寄存器,掛起就是,證實有了中斷,會在觸發中斷。可是不會硬件清除。ui
只能軟件清除,或者修改邊沿極性的時候清除。以下spa
先說EXTI吧, 翻譯
EXTI 控制器的主要特性:code
下圖是ST207的框架圖
下圖爲翻譯版
從圖中看出和外部中斷有關的寄存器有:上升沿觸發選擇、降低沿觸發選擇、軟件中斷事件寄存器、中斷屏蔽寄存器、掛起請求寄存器、事件屏蔽寄存器和NVIC中斷控制寄存器等。此外就是對輸入線的理解了。
另外七根 EXTI 線鏈接方式以下
也就是說對於一個外部中斷線能夠和多個GPIO相連,當你要使用哪個IO的時候只要對SYSCFG_EXTICR對應的位設置就行了,在中斷屏蔽寄存器或事件屏蔽寄存器對應位能夠設置使用哪個中斷線
注:ST的使用SYSCFG_EXTICR來配置,GD的採用AFIO寄存器(在GPIO寄存器中)
EXTI是外部中斷吧,上面的主要是針對的這22條中斷線的說明,咱們還知道仍是有不少中斷的,好比定時器中斷,串口中斷等等,他們不屬於這22條中斷線。
咱們能夠在中斷向量表中看到
其餘的中斷配置都在各個模塊的寄存器中了
在上面的EXTI寄存器都設置好後就能夠設置NVIC了,關於NVIC的芯片編程手冊上描述較少,可是說了
因此咱們就參考一下M3手冊吧
找到AIRCR寄存器,其中8到10位爲優先級分組
咱們在代碼中使用的庫函數是
void NVIC_PRIGroup_Enable(uint32_t NVIC_PRIGroup) { /*Set the priority grouping value */ SCB->AIRCR =AIRCR_VECTKEY_MASK | NVIC_PRIGroup; }
其中咱們查到
一、SCB->AIRCR在庫函數的地址是0XE000ED0C,不懂的如何查詢的,請自行百度
二、查到SCB的結構體定義
咱們看到SCB是SystemControl Block的簡寫
下面咱們說一下分組的取值
在misc.c中有
* ========================================================================================================================== * NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority |NVIC_IRQChannelSubPriority | Description * ========================================================================================================================== * NVIC_PriorityGroup_0 | 0 | 0-15 | 0 bits for pre-emption priority * | | | 4 bits for subpriority * -------------------------------------------------------------------------------------------------------------------------- * NVIC_PriorityGroup_1 | 0-1 | 0-7 | 1 bits for pre-emption priority * | | | 3 bits for subpriority * -------------------------------------------------------------------------------------------------------------------------- * NVIC_PriorityGroup_2 | 0-3 | 0-3 | 2 bits for pre-emption priority * | | | 2 bits for subpriority * -------------------------------------------------------------------------------------------------------------------------- * NVIC_PriorityGroup_3 | 0-7 | 0-1 | 3 bits for pre-emption priority * | | | 1 bits for subpriority * -------------------------------------------------------------------------------------------------------------------------- * NVIC_PriorityGroup_4 | 0-15 | 0 | 4 bits for pre-emption priority * | | | 0 bits for subpriority * ==========================================================================================================================
搶佔優先級& 響應優先級區別
例子:
假定設置中斷優先級組爲2,而後設置
中斷3(RTC中斷)的搶佔優先級爲2,響應優先級爲1。
中斷6(外部中斷0)的搶佔優先級爲3,響應優先級爲0
中斷7(外部中斷1)的搶佔優先級爲2,響應優先級爲0。
那麼這3箇中斷的優先級順序爲:中斷7>中斷3>中斷6
表如今代碼中
NVIC_InitPara NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQ = IRQn; NVIC_InitStructure.NVIC_IRQPreemptPriority =pri; NVIC_InitStructure.NVIC_IRQSubPriority = pri1; NVIC_InitStructure.NVIC_IRQEnable = ENABLE; NVIC_Init(&NVIC_InitStructure);
分組0,那麼pri的取值範圍0~0,pri1的取值範圍0~16
分組2,那麼pri的取值範圍0~4,pri1的取值範圍0~4
分組4,那麼pri的取值範圍0~16,pri1的取值範圍0~0
下面咱們講解一下NVIC寄存器
__IO uint8_t IP[240]; //中斷優先級控制的寄存器組
__IO uint32_t ISER[8]; //中斷使能寄存器組
__IO uint32_t ICER[8]; //中斷失能寄存器組
__IO uint32_t ISPR[8]; //中斷掛起寄存器組
__IO uint32_t ICPR[8]; //中斷解掛寄存器組
__IO uint32_t IABR[8]; //中斷激活標誌位寄存器組
中斷優先級控制的寄存器組:IP[240]
全稱是:InterruptPriority Registers
240個8位寄存器,每一箇中斷使用一個寄存器來肯定優先級。
好比:STM32F10x系列一共60個可屏蔽中斷,使用IP[59]~IP[0]。
每一個IP寄存器的高4位用來設置搶佔和響應優先級(根據分組),低4位沒有用到。
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
中斷使能寄存器組:ISER[8]
做用:用來使能中斷
32位寄存器,每一個位控制一箇中斷的使能。STM32F10x只有60個可屏蔽中斷,因此只使用了其中的ISER[0]和ISER[1]。
ISER[0]的bit0~bit31分別對應中斷0~31。ISER[1]的bit0~27對應中斷32~59;
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
中斷失能寄存器組:ICER[8]
做用:用來失能中斷
32位寄存器,每一個位控制一箇中斷的失能。STM32F10x只有60個可屏蔽中斷,因此只使用了其中的ICER[0]和ICER[1]。
ICER[0]的bit0~bit31分別對應中斷0~31。ICER[1]的bit0~27對應中斷32~59;
配置方法跟ISER同樣。
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
中斷掛起控制寄存器組:ISPR[8]
做用:用來掛起中斷
中斷解掛控制寄存器組:ICPR[8]
做用:用來解掛中斷
static __INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn); static __INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn); static __INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn);
中斷激活標誌位寄存器組:IABR[8]
做用:只讀,經過它能夠知道當前在執行的中斷是哪個
若是對應位爲1,說明該中斷正在執行。
static __INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn)
必定要使能系統時鐘
由於配置GPIO和中斷線的映射關係須要SYSCFG
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource11);
只要用到外部中斷,就必定要打開SYSCFG時鐘
開源代碼地址:
https://github.com/strongercjd/STM32F207VCT6/tree/master/09-EXTI
點擊查看本文所在的專輯,STM32F207教程