STM32中斷及NVIC概述

         參考資料《STM32F4xx 中文參考手冊》第十章-中斷和事件、《 ARM Cortex™-M4F 技術參考手冊》-4.3 章節:NVIC 和 4.4章節:SCB—4.4.5的 AIRCR。

           對51單片機有一定了解的都知道51單片機有5箇中斷源,2個優先級,而STM32的中斷非常強大,每個外設都可以產生中

斷,F429在內核水平上搭載了一個異常響應系統, 支持爲數衆多的系統異常和外部中斷。其中系統異常有 10 個,外部中斷有

91個。除了個別異常的優先級是固定的外,其它異常的優先級都是可編程設置的。有關具體的系統異常和外部中斷可在標準庫文

件 stm32f4xx.h這個頭文件查詢到,在 IRQn_Type 這個結構體裏面包含了 F4系列全部的異常聲明。

下表即爲STM32F42系列的中斷向量表(瞭解即可)

灰色部分即爲內核的系統異常,灰色以外的其他部分即爲片上所有外設可以產生的中斷。priority值越小,優先級越高。

NVIC(Nested Vectored interrupt  controller)嵌套向量中斷控制器,控制着整個芯片中斷相關的功能,通過對NVIC寄存器進行配

置可以實現對內核和片上外設的中斷的控制。但是各個芯片廠商在設計芯片的時候會對 Cortex-M4內核裏面的 NVIC進行裁剪,

把不需要的部分去掉,所以說 STM32的 NVIC 是 Cortex-M4的 NVIC 的一個子集,只是用到了NVIC的一部分功能,其餘的保留

以後備用。

 NVIC 結構體定義,來自固件庫頭文件:core_cm4.h

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]; // 中斷優先級寄存器(8Bit wide)
   uint32_t RESERVED5[644];
   __O uint32_t STIR; // 軟件觸發中斷寄存器
 } NVIC_Type;

 掛起:當置位中斷掛起寄存器的時候,相應的中斷將會被掛起,這是這個中斷將不會立即執行,而是等待可執行的時候再執行;

比如高低級別的中斷同時產生,就先掛起低級別的中斷,等高級別的中斷執行完畢,解除並執行低級中斷

在配置中斷的時候我們一般只用 ISER、ICER 和 IP 這三個寄存器,ISER用來使能中斷,ICER用來失能中斷,IP 用來設置中斷

優先級。

優先級定義

在 NVIC 有一個專門的寄存器:中斷優先級寄存器 NVIC_IPRx(在 F429 中,x=0...90)用來配置外部中斷的優先級,IPR寬度爲

8bit,原則上每個外部中斷可配置的優先級爲0~255,數值越小,優先級越高。但是絕大多數 CM4芯片都會精簡設計,以致實際

上支持的優先級數減少,在 F429中,只使用了高 4bit,如下所示:

用於表達優先級的這 4bit,又被分組成搶佔優先級和子優先級。如果有多箇中斷同時響應,搶佔優先級高的就會 搶佔 搶佔優先

級低的優先得到執行,如果搶佔優先級相同,就比較子優先級。如果搶佔優先級和子優先級都相同的話,就比較他們的硬件中斷

編號(position),編號越小,優先級越高。

優先級的分組由內核外設 SCB的應用程序中斷及復位控制寄存器 AIRCR的PRIGROUP[10:8]位決定,F429分爲了 5組,具體如

下:主優先級=搶佔優先級,x代表主優先級位數,y代表子優先級位數。

設置優先級分組可調用庫函數 NVIC_PriorityGroupConfig() 實現,有關 NVIC 中斷相關的庫函數都在庫文件 misc.c 和 misc.h

中。

中斷優先級分組庫函數

/**
* 配置中斷優先級分組:搶佔優先級和子優先級
* 形參如下:
* @arg NVIC_PriorityGroup_0: 0bit for 搶佔優先級
*                            4 bits for 子優先級
* @arg NVIC_PriorityGroup_1: 1 bit for 搶佔優先級
*                            3 bits for 子優先級
* @arg NVIC_PriorityGroup_2: 2 bit for 搶佔優先級
*                            2 bits for 子優先級
* @arg NVIC_PriorityGroup_3: 3 bit for 搶佔優先級
*                            1 bits for 子優先級
* @arg NVIC_PriorityGroup_4: 4 bit for 搶佔優先級
*                            0 bits for 子優先級
* @注意 如果優先級分組爲 0,則搶佔優先級就不存在,優先級就全部由子優先級控制
*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
 // 設置優先級分組
 SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
 }

優先級分組真值表

中斷編程

在配置每個中斷的時候一般有 3個編程要點:

1、使能外設某個中斷,這個具體由每個外設的相關中斷使能位控制。比如串口有發送完成中斷,接收完成中斷,這兩個中斷都

由串口控制寄存器的相關中斷使能位控制。

2、初始化 NVIC_InitTypeDef結構體,配置中斷優先級分組,設置搶佔優先級和子優先級,使能中斷請求。

NVIC 初始化結構體

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

1)NVIC_IROChannel:用來設置中斷源,不同的中斷中斷源不一樣,且不可寫錯,即使寫錯了程序不會報錯,只會導致不想要

中斷。具體的成員配置可參考 stm32f4xx.h頭文件裏面的 IRQn_Type 結構體定義,這個結構體包含了所有的中斷源。

2)NVIC_IRQChannelPreemptionPriority:搶佔優先級,具體的值要根據優先級分組來確定,具體參考表格 優先級分組真值表

3)NVIC_IRQChannelSubPriority:子優先級,具體的值要根據優先級分組來確定,具體參考表格優先級分組真值表 。

4)NVIC_IRQChannelCmd:中斷使能(ENABLE)或者失能(DISABLE)。操作的是 NVIC_ISER 和 NVIC_ICER 這兩個寄存

器。

3、編寫中斷服務函數

在啓動文件 startup_stm32f429_439xx.s 中我們預先爲每個中斷都寫了一箇中斷服務函數,只是這些中斷函數都是爲空,爲的只

是初始化中斷向量表。實際的中斷服務函數都需要我們重新編寫,中斷服務函數我們統一寫在 stm32f4xx_it.c這個庫文件中。關

於中斷服務函數的函數名必須跟啓動文件裏面預先設置的一樣,如果寫錯,系統就在中斷向量表中找不到中斷服務函數的入口直

接跳轉到啓動文件裏面預先寫好的空函數,並且在裏面無限循環,實現不了中斷。

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