中斷,在單片機中占有非常重要的地位,代碼默認地從上向下執行,遇到條件或者其他陳述句,會按照指定的地方跳轉,而在單片機執行代碼的程序中,難免會有一些突發的情況需要處理,這樣就會打斷當前的代碼,待處理完突發情況之后,程式會回到被打斷的地方繼續執行,
1 EXTI控制器
外部中斷/事件控制器(EXTI)管理了控制器的 23 個中斷/事件線,每個中斷/事件線都對應有一個邊沿檢測器,可以實作輸入信號的上升沿檢測和下降沿的檢測,EXTI 可以實作對每個中斷/事件線進行單獨配置,可以單獨配置為中斷或者事件,以及觸發事件的屬性,
外部信號進入經過1的邊沿檢測電路,檢測是否符合(有2和3的上升沿和下降沿選擇暫存器決定),產生信號,然后和4軟體中斷事件暫存器或值,(在這里也就說可以寫入軟體中斷事件暫存器模擬中斷和事件),之后產生信號一分為二,看5中斷屏蔽暫存器和7事件屏蔽暫存器,如果中斷和事件都沒有屏蔽,首先會產生事件,進入脈沖發生器,其次,會進入6掛起暫存器,然后進入NVIC,
注意:
1、上面說,我們可以使用暫存器4軟體模擬中斷事件暫存器模式符合條件的信號進入,為什么不能用6暫存器呢?因為
暫存器是可讀可清除的暫存器,通過寫1清除,寫0無效,所以不能使用
2、關于掛起暫存器,掛起就是,證明有了中斷,會在觸發中斷,但是不會硬體清除,
只能軟體清除,或者修改邊沿極性的時候清除,如下
先說EXTI吧,
EXTI 控制器的主要特性:
- 每個中斷/事件線上都具有獨立的觸發和屏蔽
- 每個中斷線都具有專用的狀態位
- 支持多達23個軟體事件/中斷請求
- 檢測脈沖寬度低于APB2 時鐘寬度的外部信號
下圖是ST207的框架圖
下圖為翻譯版
從圖中看出和外部中斷有關的暫存器有:上升沿觸發選擇、下降沿觸發選擇、軟體中斷事件暫存器、中斷屏蔽暫存器、掛起請求暫存器、事件屏蔽暫存器和NVIC中斷控制暫存器等,此外就是對輸入線的理解了,
另外七根 EXTI 線連接方式如下
也就是說對于一個外部中斷線可以和多個GPIO相連,當你要使用哪一個IO的時候只要對SYSCFG_EXTICR對應的位設定就好了,在中斷屏蔽暫存器或事件屏蔽暫存器對應位可以設定使用哪一個中斷線
注:ST的使用SYSCFG_EXTICR來配置,GD的采用AFIO暫存器(在GPIO暫存器中)
EXTI是外部中斷吧,上面的主要是針對的這22條中斷線的說明,我們還知道還是有很多中斷的,比如定時器中斷,串口中斷等等,他們不屬于這22條中斷線,
我們可以在中斷向量表中看到
其他的中斷配置都在各個模塊的暫存器中了
2 NVIC控制器
在上面的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; }
其中我們查到
1、SCB->AIRCR在庫函式的地址是0XE000ED0C,不懂的如何查詢的,請自行百度
2、查到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)
3 code
一定要使能系統時鐘
因為配置GPIO和中斷線的映射關系需要SYSCFG
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource11);
只要用到外部中斷,就一定要打開SYSCFG時鐘
開源代碼地址:
https://github.com/strongercjd/STM32F207VCT6/tree/master/09-EXTI
點擊查看本文所在的專輯,STM32F207教程
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/253793.html
標籤:其他
上一篇:代碼如何隱藏 Linux 行程
