天天看點

STM32學習筆記一一外部中斷前言:

前言:

為了友善檢視部落格,特意申請了一個公衆号,附上二維碼,有興趣的朋友可以關注,和我一起讨論學習,一起享受技術,一起成長。

STM32學習筆記一一外部中斷前言:

github:my github

注:部落格所涉及的關于 stm32 的代碼,均在倉庫【stm32f013_study】下,包括底層驅動和應用測試代碼。

本文設計的檔案包含:

(1)源檔案:

drvexti.c:外部中斷驅動實作

(2)頭檔案:

drvexti.h : 外部中斷驅動頭檔案

1. STM32 外部中斷簡介

STM32 的每個 IO 都可以作為外部中斷的中斷輸入口。 STM32F103 的中斷控制器支援 19 個外部中斷/事件請求。每個中斷設有狀态位,每個中斷/事件都有獨立的觸發和屏蔽設定。代碼主要分布在固件庫的 stm32f10x_exti.h 和 stm32f10x_exti.c 檔案。

STM32F103的 19 個外部中斷為:

IO 對應中斷
線 0~15 對應外部 IO 口的輸入中斷
線 16 連接配接到 PVD 輸出
線 17 連接配接到 RTC 鬧鐘事件
線 18 連接配接到 USB 喚醒事件
線 19 連接配接到 以太網 喚醒事件

觸發方式:STM32 的外部中斷是通過邊沿來觸發的,不支援電平觸發。

2. 外部中斷分組

STM32 的每一個 GPIO 都能配置成一個外部中斷觸發源,STM32 通過根據引腳的序号不同将衆多中斷觸發源分成不同的組。

比如:PA0,PB0,PC0,PD0,PE0,PF0,PG0 為第一組。

依此類推,我們能得出一共有16 組,STM32 規定,每一組中同時隻能有一個中斷觸發源工作,那麼,最多工作的也就是16個外部中斷。

STM32學習筆記一一外部中斷前言:

3. 使用 IO 口外部中斷的配置步驟

3.1 初始化 IO 口為輸入

設定作為外部中斷輸入的 IO 口的狀态,可以設定為上拉 / 下拉輸入 / 浮空輸入,但浮空的時候外部一定要帶上拉,或者下拉電阻。否則可能導緻中斷不停的觸發。在幹擾較大的地方,就算使用了内部上拉/下拉,也建議使用外部上拉/下拉電阻,這樣可以一定程度防止外部幹擾帶來的影響。

3.2 開啟 IO 口複用時鐘,設定 IO 口與中斷線的映射關系

STM32 的 IO 口與中斷線的對應關系需要配置外部中斷配置寄存器 EXTICR,這樣我們要先開啟複用時鐘,然後配置 IO 口與中斷線的對應關系。才能把外部中斷與中斷線連接配接起來。

3.3 開啟與該IO口相對的線上中斷/事件,設定觸發條件

配置中斷産生的條件,STM32 可以配置成上升沿觸發,下降沿觸發,或者任意電平變化觸發,但是不能配置成高電平觸發和低電平觸發。同時要開啟中斷線上的中斷。

注意: 如果使用外部中斷,并設定該中斷的 EMR 位的話,會引起軟體仿真不能跳到中斷,而硬體上是可以的。而不設定 EMR,軟體仿真就可以進入中斷服務函數,并且硬體上也是可以的。建議不要配置 EMR 位。

3.4 配置中斷分組NVIC

配置中斷的分組,以及使能,對 STM32 的中斷來說,隻有配置了 NVIC 的設定,并開啟才能被執行,否則是不會執行到中斷服務函數裡面去的。

3.5 編寫中斷服務函數

這是中斷設定的最後一步,中斷服務函數,是必不可少的,如果在代碼裡面開啟了中斷,但是沒編寫中斷服務函數,就可能引起硬體錯誤,進而導緻程式崩潰!是以在開啟了某個中斷後,一定要記得為該中斷編寫服務函數。在中斷服務函數裡面編寫你要執行的中斷後的操作。

4. 例程分析

4.1 配置外部中斷對應IO

//---------------------------------------------------------------------------------------------------------------------------------------------
//	函 數 名: exti_gpio_config
//	功能說明: 外部中斷GPIO參數配置
//	形    參: 無
//	返 回 值: 無
//	日    期: 2020-04-25
//  備    注: 
//	作    者: by 霁風AI
//---------------------------------------------------------------------------------------------------------------------------------------------
static void exti_gpio_config(void)
{
	GPIO_InitTypeDef gpio_init_config;

 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PORTA時鐘
	
	gpio_init_config.GPIO_Pin  		= GPIO_Pin_0;//PA0
	gpio_init_config.GPIO_Mode 		= GPIO_Mode_IPD; //PA0設定成輸入,預設下拉	  
	GPIO_Init(GPIOA, &gpio_init_config);//初始化GPIOA.0
}
           

4.2 配置外部中斷參數

//---------------------------------------------------------------------------------------------------------------------------------------------
//	函 數 名: exti_config
//	功能說明: 外部中斷參數配置
//	形    參: 無
//	返 回 值: 無
//	日    期: 2020-04-25
//  備    注: 
//	作    者: by 霁風AI
//---------------------------------------------------------------------------------------------------------------------------------------------
static void exti_config(void)
{
	EXTI_InitTypeDef exti_init_config;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);	//外部中斷,需要使能AFIO時鐘
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);	//PA0設定為外部中斷
	
	exti_init_config.EXTI_Line		= EXTI_Line0;
  	exti_init_config.EXTI_Mode 		= EXTI_Mode_Interrupt;	
  	exti_init_config.EXTI_Trigger 	= EXTI_Trigger_Rising;//上升沿觸發
  	exti_init_config.EXTI_LineCmd 	= ENABLE;
  	
	EXTI_Init(&exti_init_config);	 	//根據EXTI_InitTypeDef中指定的參數初始化外設EXTI寄存器
}
           

4.3 配置中斷向量

//---------------------------------------------------------------------------------------------------------------------------------------------
//	函 數 名: exit_nvic_config
//	功能說明: 中斷向量參數配置
//	形    參: 無
//	返 回 值: 無
//	日    期: 2020-04-25
//  備    注: 
//	作    者: by 霁風AI
//---------------------------------------------------------------------------------------------------------------------------------------------
static void exti_nvic_config(void)
{
	NVIC_InitTypeDef nvic_init_config;
	
	nvic_init_config.NVIC_IRQChannel 					= EXTI0_IRQn;//使能按鍵所在的外部中斷通道
	nvic_init_config.NVIC_IRQChannelPreemptionPriority 	= 0x02;//搶占優先級2
	nvic_init_config.NVIC_IRQChannelSubPriority 		= 0x02;//子優先級1
	nvic_init_config.NVIC_IRQChannelCmd 				= ENABLE;
	
	NVIC_Init(&nvic_init_config);
}
           

4.4 統一外部中斷調用接口

//---------------------------------------------------------------------------------------------------------------------------------------------
//	函 數 名: exti_init
//	功能說明: 外部中斷初始化
//	形    參: 	exti_no:中斷号
//	返 回 值: 無
//	日    期: 2020-04-25
//  備    注: 外部調用此函數,實作EXTI的初始化配置
//	作    者: by 霁風AI
//---------------------------------------------------------------------------------------------------------------------------------------------
void exti_init(uint8_t exti_no)
{
	if (exti_no == 0)
	{
		exti_gpio_config();
		exti_config();
		exti_nvic_config();
	}
}
           

4.5 編寫中斷服務函數

//---------------------------------------------------------------------------------------------------------------------------------------------
//	函 數 名: EXTI0_IRQHandler
//	功能說明: 外部中斷0服務函數
//	形    參: 無
//	返 回 值: 無
//	日    期: 2020-04-25
//  備    注: 
//	作    者: by 霁風AI
//---------------------------------------------------------------------------------------------------------------------------------------------
void EXTI0_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line0) != RESET)  
	{
		g_exti_cnt++;
		
		if (g_exti_cnt % 2)
		{
			Bsp_LedOn(0);	//點亮OLED0
		}
		else 
		{
			Bsp_LedOff(0);	//熄滅OLED0
		}
		
		if (g_exti_cnt > 200)
		{
			g_exti_cnt = 0;
		}
		
		EXTI_ClearITPendingBit(EXTI_Line0);	//清除EXTI0線路挂起
	}
}
           

補充:

在編寫中斷服務函數的時候會經常使用到兩個函數。

(1)第一個函數是判斷某個中斷線上的中斷是否發生(标志位是否置位):

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
           

這個函數一般使用在中斷服務函數的開頭判斷中斷是否發生。

(2)第二個是清除某個中斷線上的中斷标志位:

void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
           

這個函數一般應用在中斷服務函數結束之前,清除中斷标志位。

參考:

  1. STM32-外部中斷實驗
  2. STM32-外部中斷學習筆記
  3. STM32之EXTI——外部中斷

繼續閱讀