STM32中斷NVIC、EXTI外部中斷

目錄

1:NVIC(嵌套向量中斷控制器)

2:搶佔優先級&響應優先級

3:中斷管理的方法

4:EXTI外部中斷概述

5:外部中斷的一般配置步驟


eg:STM32F407ZGT6

1:NVIC(嵌套向量中斷控制器)

在參考手冊的描述中(我就直接Copy了哈):

嵌套向量中斷控制器 NVIC 包含以下特性:
STM32F405xx/07xx STM32F415xx/17xx 具有 82 個可屏蔽中斷通道,STM32F42xxx
    和 STM32F43xxx 具有多達 86 個可屏蔽中斷通道(不包括 Cortex™-M4F 的 16 根中 斷線)
16 個可編程優先級使用了 4 位中斷優先級)
低延遲異常和中斷處理
電源管理控制
系統控制寄存器的實現
 
嵌套向量中斷控制器 (NVIC) 和處理器內核接口緊密配合,可以實現低延遲的中斷處理和晚
到中斷的高效處理。
 
F4是用的CM4內核,而CM4內核支持256箇中斷,其中包含了16個內核中斷240個外部中斷,並且具用256級的可編程中斷設置
SO————STM32F407ZGT6用到的中斷資源只是CM4內核中斷資源的一部分
 

敲黑板:

STM32F40xx/STM32F41xx的92箇中斷裏面,包括10個內核中斷82個可屏蔽中斷,具有16級可編程的中斷優先級,而我們常用的就是這82個可屏蔽中斷。(具體的參數可以去看相應芯片的數據手冊)
 
 

2:搶佔優先級&響應優先級

就是兩種中斷的級別,可以組合。

  • 高優先級的搶佔優先級是可以打斷正在進行的低搶佔優先級中斷的
  • 搶佔優先級相同的中斷,高響應優先級不可以打斷低響應優先級的中斷
  • 搶佔優先級相同的中斷,當兩個中斷同時發生的情況下,哪個響應優先級高,哪個先執行
  • 如果兩個中斷的搶佔優先級和響應優先級是一樣的,那就看哪個先發生就安排哪個。

 

假設先設置中斷優先級分組爲2(下面會講中斷優先級分組)

然後設置中斷A的搶佔優先級爲2,響應優先級爲1

              中斷B的搶佔優先級爲3,響應優先級爲0

              中斷C的搶佔優先級爲2,響應優先級爲0

那麼這三個中斷的優先級順序爲: C>=A>B  (號子越小越牛逼) 

 

3:中斷管理的方法

首先,要對STM32中斷進行分組,組0~4。同時,對每個中斷設置一個搶佔優先級和一個響應優先級

 寫代碼的時候,先設置完一次中斷優先級分組後,就不要去改變了,隨意的分組會導致中斷管理混亂。且後面所有的中斷都要滿足你這個分組的要求,比如,我設置爲組2,那麼你後面所有的中斷搶佔和響應優先級都不能高於0x03

分組配置是在應用程序中斷及復位控制寄存器SCB->AIRCR中配置

  /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
  SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;

 OK,有了中斷優先級的概念後,再來看中斷設置的相關寄存器

typedef struct
{
  __IO uint32_t ISER[8];                 /*!< Offset: 0x000 (R/W)  中斷使能寄存器組 */
       uint32_t RESERVED0[24];
  __IO uint32_t ICER[8];                 /*!< Offset: 0x080 (R/W)  中斷失能寄存器組 */
       uint32_t RSERVED1[24];
  __IO uint32_t ISPR[8];                 /*!< Offset: 0x100 (R/W)  中斷掛起寄存器組 */
       uint32_t RESERVED2[24];
  __IO uint32_t ICPR[8];                 /*!< Offset: 0x180 (R/W)  中斷解掛寄存器組 */
       uint32_t RESERVED3[24];
  __IO uint32_t IABR[8];                 /*!< Offset: 0x200 (R/W)  中斷激活標誌位寄存器組 */
       uint32_t RESERVED4[56];
  __IO uint8_t  IP[240];                 /*!< Offset: 0x300 (R/W) 中斷優先級控制寄存器組(8Bit wide) */
       uint32_t RESERVED5[644];
  __O  uint32_t STIR;                    /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register     */
}  NVIC_Type;
  1.  IP[240]:Interrupt Priority Registers 中斷優先級控制的寄存器組240個8位寄存器,

每個中斷使用一個寄存器來確定優先級,前面介紹了,F40系列一共82個可屏蔽中斷,使用IP[81]~IP[0].

每個IP寄存器的高四位都用來設置搶佔和響應優先級(根據分組),低4位沒有用到

 

    2:ISER[8]:中斷使能寄存器組

用來使能中斷的,32位寄存器,每個位控制一箇中斷的使能。一共82個可屏蔽中斷,所以只使用了其中的ISER[0]~ISER[2] (因爲是32位的) 

  •      ISER[0]的bit0~bit31分別對應中斷0~31。
  •      ISER[1]的bit0~27對應中斷32~63;
  •      ISER[2]的bit0~17對應於中斷64~81

 

  3:ICER[8]:中斷失能寄存器組

用來失能中斷 32位寄存器,每個位控制一箇中斷的失能,和2一樣。不多bb

 

4:中斷掛起控制寄存器組ISPR[8],中斷解掛控制寄存器組ICPR[8],都和前兩個一樣

 

5:IABR[8]:中斷激活標誌位寄存器組

只讀,通過它可以知道當前在執行的中斷是哪一個,如果對應位爲1,說明該中斷正在執行

/********************************************************************************************************************/

以上,就是中斷最基本的一些知識,不需要去記住,不管是標準庫,還是HAL庫,都有相應的函數去調用,刨開那些函數,調用的也就是上面的寄存器。

至於代碼,我就不貼了,網上一大堆

 

4:EXTI外部中斷概述

STM32F4的每個IO都可以作爲外部中斷輸入

STM32F4的中斷控制器支持22個外部中斷/事件請求:

  • EXTI線0~15:對應外部IO口的輸入中斷。
  • EXTI線16:連接到PVD輸出。
  • EXTI線17:連接到RTC鬧鐘事件。
  • EXTI線18:連接到USB OTG FS喚醒事件。
  • EXTI線19:連接到以太網喚醒事件。
  • EXTI線20:連接到USB OTG HS(在FS中配置)喚醒事件。
  • EXTI線21:連接到RTC入侵和時間戳事件。
  • EXTI線22:連接到RTC喚醒事件。

每個外部中斷線都可以獨立的配置觸發方式(上升沿,下降沿或雙邊沿觸發),觸發/屏蔽,專用的狀態位。

 

上面,我們可以看到,IO口的輸入中斷線只有16個,而F4的IO口有多達百個,前面也說了,32的每個IO口都可以觸發外部中斷,所以,這個裏面是有取捨的。

看這個圖,就很明確了,把PX0拉到EXT0上,把PX1拉到EXT1上,這樣,就可以用16根IO口外部中斷線來管理上百個IO了。

但是還沒結束,並不是16根中斷線就可以分配到16箇中斷服務函數

很吝嗇的是,只有7箇中斷服務函數

後面的EXTI9-5,EXTI15-10只能擠擠了。也就是說PX9~PX5共用一個外部中斷服務函數,PX15~PX10共用一個外部中斷服務函數

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);       //使能SYSCFG時鐘
 
 SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);//PA0 連接到中斷線0

  /* 配置EXTI_Line0 */
  EXTI_InitStructure.EXTI_Line = EXTI_Line0;              //LINE0
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;     //中斷事件
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  //上升沿觸發 
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;               //使能LINE0
  EXTI_Init(&EXTI_InitStructure);                         //配置

 /*配置一下外部中斷0的中斷優先級和使能通道*/
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;            //外部中斷0
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//搶佔優先級0
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;       //子優先級2
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //使能外部中斷通道
  NVIC_Init(&NVIC_InitStructure);//配置

  //外部中斷0服務程序
  void EXTI0_IRQHandler(void)
 {
	 EXTI_ClearITPendingBit(EXTI_Line0);                      //清除LINE0上的中斷標誌位 
  }	

看上面第一步,要使能系統配置控制器時鐘,這個很重要

#define RCC_APB2Periph_SYSCFG            ((uint32_t)0x00004000)

/*調用RCC_APB2PeriphClockCmd,實際上賦值給了APB2ENR寄存器*/
RCC->APB2ENR |= RCC_APB2Periph;

/*
位 14 SYSCFGEN:系統配置控制器時鐘使能 (System configuration controller clock enable)
由軟件置 1 和清零。
0:禁止系統配置控制器時鐘 
1:使能系統配置控制器時鐘
使能了系統配置控制器後,可以看看SYSCFG_EXTICRX寄存器的描述,你就懂了
*/

 

 

5:外部中斷的一般配置步驟

  1. 使能SYSCFG系統配置控制器時鐘
  2. 初始化IO口爲輸入
  3. 設置IO口與中斷線的映射關係
  4. 初始化線上中斷,設置觸發條件等
  5. 配置中斷分組(NVIC),並使能中斷
  6. 編寫中斷服務函數
  7. 清除中斷標誌位

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章