STM32 中斷和事件


中斷和事件(Interrupts and events)

嵌套向量中斷控制器(Nested vectored interrupt controller -NVIC)

  • 中斷是相對CPU而言的,因此例如IIC、定時器這些芯片內產生的中斷也被稱為外部中斷,不能狹隘的理解為由芯片外的信號觸發

  • EXTI被稱為外部中斷/事件控制器(External interrupt/event controller)

  • 什么是中斷?什么是事件

  • EXTI的23個中斷事件線與中斷的關系? 在同一時刻每個中斷線只能相應一個GPIO端口的中斷,不能夠同時相應所有端口的中斷事件

  • 優先級定義

    NVIC有一個專門的寄存器:中斷優先級寄存器NVIC_IPRx用來配置外部中斷的優先級,IPR寬度為8bit,原則上每個外部中斷可配置的優先級為0~255,數值越小,優先級越高。在STM32F4中使用了高4位設置中斷優先級,也就是有16個可編程優先級。
    中斷優先級被分組為搶占優先級子優先級。如果有多個中斷同時響應,搶占優先級高的就會搶占搶占優先級低的優先得到執行,如果搶占優先級相同,就比較子優先級。如果搶占優先級和子優先級都相同的話,就比較他們的硬件中斷編號,編號越小,優先級越高。

寄存器介紹

上面說到 NVIC 控制着芯片的中斷相關功能, 那么肯定有很多對應的寄存器,在固件庫 core_cm3.h 文件內定義了一個 NVIC 結構體,里面定義了相關寄存器,如下:

typedef struct
{
    __IO uint32_t ISER[8]; //中斷使能寄存器
    uint32_t RESERVED0[24];
    __IO uint32_t ICER[8]; //中斷清除寄存器
    uint32_t RSERVED1[24];
    __IO uint32_t ISPR[8]; //中斷使能懸起寄存器
    uint32_t RESERVED2[24];
    __IO uint32_t ICPR[8]; //中斷清除懸起寄存器
    uint32_t RESERVED3[24];
    __IO uint32_t IABR[8]; //中斷有效位寄存器
    uint32_t RESERVED4[56];
    __IO uint8_t IP[240]; //中斷優先級寄存器
    uint32_t RESERVED5[644];
    __O uint32_t STIR; //軟件觸發中斷寄存器
} NVIC_Type;

在配置中斷時,我們通常使用的只有 ISER、 ICER 和 IP 這三個寄存器,ISER是中斷使能寄存器,ICER是中斷清除寄存器,IP 是中斷優先級寄存器。在固件庫 core_cm3.h文件后面,還提供了一些對 NVIC 操作的庫函數,這些函數都是遵循 CMSIS 標准, 所以只要是基於 Cortex-M3 內核的芯片都可以用這些函數來操作 NVIC,只不過我們很少這樣做,甚至不使用這些函數,因為在后面我們會有更簡單的辦法來配置中斷。至於這些函數內容,大家如果有興趣的話,可以打開我們庫函數版本任意程序,找到 core_cm3.h 文件查看即可。

這里多提一點__IO的用法:

/* IO definitions (access restrictions to peripheral registers) */
#ifdef __cplusplus
  #define __I  volatile         /*!< defines 'read only' permissions                 */
#else
  #define __I  volatile const   /*!< defines 'read only' permissions                 */
#endif
#define   __O  volatile         /*!< defines 'write only' permissions                */
#define   __IO volatile         /*!< defines 'read / write' permissions              */ 

其實就是將volatile關鍵字進行了重定義,用來區分讀寫,僅僅是語法提醒層面,並不強制。

中斷配置

前面講解了那么多中斷知識, 如果大家不理解也沒有關系, 我們會應用即可,等到后面 STM32 熟練了,再回過頭深入了解自然就會明白。要使用中斷我們就需要先配置它,通常都需經過這幾步:

(1)使能外設某個中斷,這個具體是由外設相關中斷使能位來控制,比如

定時器有溢出中斷,這個可由定時器的控制寄存器中相應中斷使能位來控制。

(2)設置中斷優先級分組,初始化 NVIC_InitTypeDef 結構體,設置搶占

優先級和響應優先級,使能中斷請求。

NVIC_InitTypeDef 結構體如下:

typedef struct
{
  uint8_t NVIC_IRQChannel; //中斷源
  uint8_t NVIC_IRQChannelPreemptionPriority; //搶占優先級
  uint8_t NVIC_IRQChannelSubPriority; //響應優先級
  FunctionalState NVIC_IRQChannelCmd; //中斷使能或失能
} NVIC_InitTypeDef;

下面我們對 NVIC_InitTypeDef 結構體成員進行一下簡單介紹。

1.NVIC_IRQChannel:中斷源的設置,不同的外設中斷,中斷源不一樣,自

然名字也不一樣,所以名字不能寫錯,否則不會進入中斷。中斷源放在stm32f10x.h 文件的 IRQn_Type結構體內,由於內容太多,這里就不復制所有中斷源,只截取一部分,如下:


typedef enum IRQn
{
  //Cortex-M3 處理器異常編號
  NonMaskableInt_IRQn = -14,
  MemoryManagement_IRQn = -12,
  BusFault_IRQn = -11,
  UsageFault_IRQn = -10,
  SVCall_IRQn = -5,
  DebugMonitor_IRQn = -4,
  PendSV_IRQn = -2,
  SysTick_IRQn = -1,
  //STM32 外部中斷編號
  WWDG_IRQn = 0,
  PVD_IRQn = 1,
  TAMP_STAMP_IRQn = 2,
  // 限於篇幅,中間部分代碼省略,具體的可查看庫文件 stm32f10x.h
  DMA2_Channel2_IRQn = 57,
  DMA2_Channel3_IRQn = 58,
  DMA2_Channel4_5_IRQn = 59
}IRQn_Type;

2.NVIC_IRQChannelPreemptionPriority:搶占優先級,具體的值要根據優先級分組來確定,可以參考前面中斷優先級分組內容。

3.NVIC_IRQChannelSubPriority:響應優先級,具體的值要根據優先級分組

來確定,可以參考前面中斷優先級分組內容。

4.NVIC_IRQChannelCmd:中斷使能/失能設置,使能配置為 ENABLE,失能配置為 DISABLE。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM