外部中斷

一.基本概念

 

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喚醒事件。 每個外部中斷線可以獨立的配置觸發方式(上升沿,下降沿或者雙邊沿觸發),觸發/屏蔽,專用的狀態位。

 

2.中斷線與IO口的對應關係

中斷線只有16根,因此

將PIOx.0映射到EXTI0

GPIOx.1映射到EXTI1

.......

GPIOx.15映射到EXTI15 

每一根中斷線接收多個端口的映射,就解決了中斷線不夠用的情況

3.對於每個中斷線,可以設置相應的觸發方式(上升沿觸發,下降沿觸發,邊沿觸發)以及使能。

IO口外部中斷在中斷向量表中只分配了7箇中斷向量,也就是隻能使用7箇中斷服務函數

從表中可以看出,外部中斷線5~9分配一箇中斷向量,共用一個服務函數外部中斷線10~15分配一箇中斷向量,共用一箇中斷服務函數。 

4.中斷服務函數列表:

EXTI0_IRQHandler        

EXTI1_IRQHandler

EXTI2_IRQHandler          

EXTI3_IRQHandler          

EXTI4_IRQHandler          

EXTI9_5_IRQHandler        

EXTI15_10_IRQHandler      

外部中斷常用庫函數:

①void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex);    //設置IO口與中斷線的映射關係    exp: SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2);     //將PE2映射到2號中斷線

②void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);  //初始化中斷線:觸發方式等

③ITStatus EXTI_GetITStatus(uint32_t EXTI_Line); //判斷中斷線中斷狀態,是否發生

④void EXTI_ClearITPendingBit(uint32_t EXTI_Line); //清除中斷線上的中斷標誌位

⑤RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG時鐘 //這個函數非常重要,在使用外部中斷的時候一定要先使能SYSCFG時鐘

 

二、中斷編寫

1.中斷配置一般過程

①使能SYSCFG時鐘:          RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

②   初始化IO口爲輸入。        GPIO_Init();

③設置IO口與中斷線的映射關係。         void SYSCFG_EXTILineConfig();

④初始化線上中斷,設置觸發條件等。        EXTI_Init();

⑤配置中斷分組(NVIC),並使能中斷。        NVIC_Init();

⑥編寫中斷服務函數。       EXTIx_IRQHandler();

⑦清除中斷標誌位       EXTI_ClearITPendingBit();

 

2.硬件連接

3.

中斷服務函數:delay_ms(10)用於判斷按鍵按下若超過10ms,就說明是真的按下了,也就是消除抖動的作用。

void EXTIx_IRQHandler(void)
{
	delay_ms(10);	
	if(WK_UP==1)	 
	{
		BEEP=!BEEP; 
	}		 
	 EXTI_ClearITPendingBit(EXTI_Linex); 
}	

 4.初始化線上中斷,映射到2號中斷線,設置模式爲中斷,下降沿觸發,初始使能。

 EXTI_InitStructure.EXTI_Line=EXTI_Line2;	 
 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
 EXTI_InitStructure.EXTI_LineCmd = ENABLE;
 EXTI_Init(&EXTI_InitStructure);

5.配置中斷分組(NVIC),並使能中斷。設置中斷通道,搶佔優先級,子優先級,使能外部中斷通道。

  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

 

 

6.完整exti代碼:

其中

key0對應蜂鳴器響停,搶佔優先級:0,響應優先級:2,中斷線0,中斷處理函數EXTI0_IRQn

key1對應LED0翻轉,搶佔優先級:3,響應優先級:2,中斷線2,中斷處理函數EXTI2_IRQn

key2對應LED1翻轉,搶佔優先級:2,響應優先級:2,中斷線3,中斷處理函數EXTI3_IRQn

key3對應LED0,LED1同時翻轉,搶佔優先級:1,響應優先級:2,中斷線4,中斷處理函數EXTI4_IRQn

 




void EXTI0_IRQHandler(void)
{
	delay_ms(10);	
	if(WK_UP==1)	 
	{
		BEEP=!BEEP; 
	}		 
	 EXTI_ClearITPendingBit(EXTI_Line0); 
}	

void EXTI2_IRQHandler(void)
{
	delay_ms(10);	
	if(KEY2==0)	  
	{				 
   LED0=!LED0; 
	}		 
	 EXTI_ClearITPendingBit(EXTI_Line2);

void EXTI3_IRQHandler(void)
{
	delay_ms(10);	
	if(KEY1==0)	 
	{
		LED1=!LED1;
	}		 
	 EXTI_ClearITPendingBit(EXTI_Line3);   
}

void EXTI4_IRQHandler(void)
{
	delay_ms(10);	
	if(KEY0==0)	 
	{				 
		LED0=!LED0;	
		LED1=!LED1;	
	}		 
	 EXTI_ClearITPendingBit(EXTI_Line4); 
}
	   

void EXTIX_Init(void)
{
	NVIC_InitTypeDef   NVIC_InitStructure;
	EXTI_InitTypeDef   EXTI_InitStructure;
	
	KEY_Init();
 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
	
 
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2);
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
	

  EXTI_InitStructure.EXTI_Line = EXTI_Line0;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; 
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
	
  EXTI_InitStructure.EXTI_Line = EXTI_Line2 | EXTI_Line3 | EXTI_Line4;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
 
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//×ÓÓÅÏȼ¶2
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	   
}












7.總結

在進行STM32F407外部中斷按鍵實驗時,通過key0綁定蜂鳴器,key1綁定led0(亮滅),key2綁定led1(亮滅),key3綁定led0和led1(同時反轉),樣例給定時延爲10ms,在進行按鍵檢測時,發現並未體現函數中的搶佔優先級,思考過後可能是由於時延太短,無法在10ms內看出其中的差別,因此我首先將時延設置爲1000ms,給予充分的觀察時間,設立優先級:

首先保持子優先級(響應優先級)相同,全部設爲2,對於搶佔優先級:

0級:key0(蜂鳴器)

1級:key1(LED0)

2級:key2(LED1)

3級:key3(LED0和LED1)

在進行試驗時,按下key0與key1,在按下的時候有意的略微早一點按下key1,然後再按下key0,按照優先級搶佔原則,key1的優先級爲1,key0的優先級爲0,雖然先按下key1,先進入key1的中斷處理,但是由於key0的搶佔優先級高於key1,於是將會先響應key0的中斷,再響應key1的中斷,最後實驗發現確實如此,蜂鳴器先響,然後led0才亮,此後嘗試了key2,key3均符合該原理。

 

另設優先級:

key0,key1搶佔優先級設爲0,子優先級(響應優先級)設爲1,3

key2,key3搶佔優先級設爲1,子優先級(響應優先級)設爲2,2

實驗發現:

搶佔優先級等級高於子優先級(響應優先級),子優先級低的搶佔優先級高的會先響應,在搶佔優先級相同的情況下,子優先級(響應優先級)高的將會先響應,兩個優先級均相同的情況下,先來的會先響應。

發佈了56 篇原創文章 · 獲贊 48 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章