STM32F1迷你板外部中斷

開始學習外部中斷的基本知識

中斷優先級分組管理

CortexM3內部支持256箇中斷,其中包含了 16 個內核中斷和 240 個外部中斷,並且具有 256
級的可編程中斷設置。STM32F1系列有 84 箇中斷,包括 16 個內核中斷和 68 個可屏蔽中斷,具有 16 級可編程的中斷優先級。而我們常用的就是這 68 個可屏蔽中斷, 但是 STM32 的 68 個可屏蔽中斷,在 STM32F103 系列
上面,可屏蔽中斷又只有 60 個(在 107 系列纔有 68 個)。

中斷管理辦法:
首先,對STM32中斷進行分組,分成5個組:組0~4,該分組的設置是由 SCB->AIRCR 寄存器的 bit10~8 來定義的。 同時,對每個中斷設置一個搶佔優先級和一個響應優先級。
有4個位來分配搶佔優先級和響應優先級。
下面是AIRCR 中斷分組設置表

AIRCR[10: 8] bit[7: 4]分配情況 分配結果
0 111 0: 4 0 位搶佔優先級, 4 位響應優先級
1 110 1: 3 1 位搶佔優先級, 3 位響應優先級
2 101 2: 2 2 位搶佔優先級, 2 位響應優先級
3 100 3: 1 3 位搶佔優先級, 1 位響應優先級
4 011 4: 0 4 位搶佔優先級, 0 位響應優先級

每個中斷,可以設置搶佔優先級爲 0~7,響應優先級爲 1 或 0。搶佔優先級的級別高於響應優先級。而數值越小所代表的優先級就越高。搶佔優先級相同的中斷,當兩個中斷同時發生,哪個響應優先級高,哪個先執行。

這裏需要注意兩點:第一,如果兩個中斷的搶佔優先級和響應優先級都是一樣的話,則看哪個中斷先發生就先執行;第二,高優先級的搶佔優先級是可以打斷正在進行的低搶佔優先級中斷的。而搶佔優先級相同的中斷,高優先級的響應優先級不可以打斷低響應優先級的中斷。

中斷優先級分組設置函數NVIC_PriorityGroupConfig

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
	assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
	SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}

分組可以在下面選

(((GROUP) == NVIC_PriorityGroup_0) ||
((GROUP) == NVIC_PriorityGroup_1) || \
((GROUP) == NVIC_PriorityGroup_2) || \
((GROUP) == NVIC_PriorityGroup_3) || \
((GROUP) == NVIC_PriorityGroup_4))

設置好了系統中斷分組,那麼對於每個中斷我們又怎麼確定他的搶佔優先級和響應優先級呢?通過中斷初始化函數void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)

解析一下上式用到的結構體NVIC_InitTypeDef

typedef struct
{
uint8_t NVIC_IRQChannel;
uint8_t NVIC_IRQChannelPreemptionPriority;
uint8_t NVIC_IRQChannelSubPriority;
FunctionalState NVIC_IRQChannelCmd;
} NVIC_InitTypeDef;

成員變量的含義
NVIC_InitTypeDef 結構體中間有三個成員變量,這三個成員變量的作用是:
NVIC_IRQChannel:定義初始化的是哪個中斷,這個我們可以在 stm32f10x.h 中找到每個中斷對應的名字。例如 USART1_IRQn。
NVIC_IRQChannelPreemptionPriority:定義這個中斷的搶佔優先級別。
NVIC_IRQChannelSubPriority:定義這個中斷的子優先級別。
NVIC_IRQChannelCmd:該中斷是否使能。

比如我們要使能串口 1 的中斷,同時設置搶佔優先級爲 1,子優先級位 2,初始化的方法是

NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口 1 中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 搶佔優先級爲 1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 子優先級位 2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能
NVIC_Init(&NVIC_InitStructure); //根據上面指定的參數初始化 NVIC 寄存器

NVIC 寄存器結構體NVIC_Type

typedef struct
{
	__IO uint32_t ISER[8]; /*!< Interrupt Set Enable Register */
	uint32_t RESERVED0[24];
	__IO uint32_t ICER[8]; /*!< Interrupt Clear Enable Register */
	uint32_t RSERVED1[24];
	__IO uint32_t ISPR[8]; /*!< Interrupt Set Pending Register */
	uint32_t RESERVED2[24];
	__IO uint32_t ICPR[8]; /*!< Interrupt Clear Pending Register */
	uint32_t RESERVED3[24];
	__IO uint32_t IABR[8]; /*!< Interrupt Active bit Register */
	uint32_t RESERVED4[56];
	__IO uint8_t IP[240]; /*!< Interrupt Priority Register, 8Bit wide */
	uint32_t RESERVED5[644];
	__O uint32_t STIR; /*!< Software Trigger Interrupt Register */
} NVIC_Type;

外部中斷

STM32每一個IO口都可以作爲外部中斷輸入。
STM32的中斷控制器支持19個外部中斷/事件請求。
線0~15:對應外部IO口的輸入中斷

每個外部中斷線可以獨立配置觸發方式(上升沿,下降沿或者雙邊沿觸發),觸發/屏蔽,專用的狀態位。
GPIO的管腳和中斷線有一個對應關係,每個中斷線最多對應7個IO口。以線0爲例,它對應了GPIOA.0,GPIOB.0,GPIOC.0,GPIOD.0,GPIOE.0,GPIOF.0,GPIOG.0。中斷線每次只能連接到一個IO口,所以需要在7個IO口中進行選擇。

映射關係
在這裏插入圖片描述
圖片來源:正點原子

外部中斷的一般配置步驟
初始化IO口爲輸入GPIO_Init()
開啓IO口複用時鐘RCC_APB2PeriphClockCmd(RCC_APB2Perith_AFIO,ENABLE);
設置IO口與中斷線的映射關係void GPIO_EXTILineConfig()
初始化線上中斷,設置觸發條件等EXTI_Init()
配置中斷分組(NVIC),並使能中斷NVIC_Init()
編寫中斷服務程序EXTIx_IRQHandler()
清除中斷標誌位EXTI_ClearTPendingBit()

IO口和中斷線的映射
在庫函數中,配置 GPIO 與中斷線的映射關係的函數 GPIO_EXTILineConfig()來實現的:
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
該函數將 GPIO 端口與中斷線映射起來,使用範例是:
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);
將中斷線 2 與 GPIOE 映射起來,即GPIOE.2 與 EXTI2 中斷線連接了。我們要是用的是PE4(對應的是KEY0),所以這裏是

GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);

然後我們對中斷進行初始化

	 //初始化中斷
	 EXTI_InitStructure.EXTI_Line=EXTI_Line4;//線號
	 EXTI_InitStructure.EXTI_LineCmd=ENABLE;//使能
	 EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//中斷還是事件
	 EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//下降沿觸發
	 EXTI_Init(&EXTI_InitStructure);

這裏筆者有個問題?這裏爲什麼選擇下降沿觸發呢?原來是因爲KEY0接的是低電平,所以讓它有效的話,必須是到低電平。

配置中斷分組NVIC

 //NVIC中斷分組的設置
	 NVIC_InitStructure.NVIC_IRQChannel=EXTI4_IRQn;
	 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE:
	 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
	 NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
	 NVIC_Init(&NVIC_InitStructure);

前五步的初始化函數如下

 
 void EXITX_Init(){
 
	 
		EXTI_InitTypeDef EXTI_InitStructure;//結構體變量
	 NVIC_InitTypeDef NVIC_InitStructure;
	 KEY_Init();//初始化GPIO
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	 //key0對應PE4
	 //PE4映射到中斷線4
	 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4 );
	 
	 //初始化中斷
	 EXTI_InitStructure.EXTI_Line=EXTI_Line4;//線號
	 EXTI_InitStructure.EXTI_LineCmd=ENABLE;
	 EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//中斷
	 EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//下降沿觸發
	 EXTI_Init(&EXTI_InitStructure);
	 
	 //NVIC中斷分組的設置
	 NVIC_InitStructure.NVIC_IRQChannel=EXTI4_IRQn;
	 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE:
	 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
	 NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
	 NVIC_Init(&NVIC_InitStructure);
 }
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章