STM32F103 高階應用(2)——中斷應用

青梅煮久發表於2020-12-29

一、應用簡介

本文接著上一章講中斷應用。

二、GPIO輸入中斷

2.1 原理圖

在這裡插入圖片描述

2.2 NVIC配置

static void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;

	/* 配置 NVIC 為優先順序組 1 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

	/* 配置中斷源:按鍵 1 */
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
	/* 配置搶佔優先順序:1 */
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	/* 配置子優先順序:1 */
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	/* 使能中斷通道 */
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
 
	/* 配置中斷源:按鍵 2,其他使用上面相關配置 */
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_Init(&NVIC_InitStructure);
}

2.3 EXTI與IO配置

void EXTI_Key_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;
	
	/*開啟按鍵 GPIO 口的時鐘*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO,ENABLE);
	
	/* 配置 NVIC 中斷*/
	NVIC_Configuration();
	
	/*--------------------------KEY1 配置---------------------*/
	/* 選擇按鍵用到的 GPIO */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	/* 配置為浮空輸入 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	/* 選擇 EXTI 的訊號源 */
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
	EXTI_InitStructure.EXTI_Line = EXTI_Line0;
	
	/* EXTI 為中斷模式 */
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	/* 上升沿中斷 */
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	/* 使能中斷 */
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
	
	/*--------------------------KEY2 配置------------------*/
	/* 選擇按鍵用到的 GPIO */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
	/* 配置為浮空輸入 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	
	/* 選擇 EXTI 的訊號源 */
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);
	EXTI_InitStructure.EXTI_Line = EXTI_Line13;
	
	/* EXTI 為中斷模式 */
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	/* 下降沿中斷 */
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	/* 使能中斷 */
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
}

2.4 中斷服務函式

#define KEY1_IRQHandler EXTI0_IRQHandler
#define KEY2_IRQHandler EXTI15_10_IRQHandler
void KEY1_IRQHandler(void)
{
	//確保是否產生了 EXTI Line 中斷
	if (EXTI_GetITStatus(EXTI_Line0) != RESET) 
	{
		// LED1 取反
		static uint8_t tmp = 0;
		/*LED1 反轉*/
		if(tmp == 0)
		{
			UseLibSetOutput(GPIOB, GPIO_Pin_0,0);
			tmp = 1;
		}
		else
		{
			UseLibSetOutput(GPIOB, GPIO_Pin_0,1);
			tmp = 0;
		}
		//清除中斷標誌位
		EXTI_ClearITPendingBit(EXTI_Line0);
	}
}
 
void KEY2_IRQHandler(void)
{
	//確保是否產生了 EXTI Line 中斷
	if (EXTI_GetITStatus(EXTI_Line13) != RESET) 
	{
		// LED2 取反
		static uint8_t tmp1 = 0;
		/*LED1 反轉*/
		if(tmp1 == 0)
		{
			UseLibSetOutput(GPIOB, GPIO_Pin_5,0);
			tmp1 = 1;
		}
		else
		{
			UseLibSetOutput(GPIOB, GPIO_Pin_5,1);
			tmp1 = 0;
		}
	//清除中斷標誌位
	EXTI_ClearITPendingBit(EXTI_Line13);
	}
}

3 例項程式碼

board_gpi.c

static void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;

	/* 配置 NVIC 為優先順序組 1 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

	/* 配置中斷源:按鍵 1 */
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
	/* 配置搶佔優先順序:1 */
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	/* 配置子優先順序:1 */
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	/* 使能中斷通道 */
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
 
	/* 配置中斷源:按鍵 2,其他使用上面相關配置 */
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_Init(&NVIC_InitStructure);
}

void EXTI_Key_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;
	
	/*開啟按鍵 GPIO 口的時鐘*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO,ENABLE);
	
	/* 配置 NVIC 中斷*/
	NVIC_Configuration();
	
	/*--------------------------KEY1 配置---------------------*/
	/* 選擇按鍵用到的 GPIO */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	/* 配置為浮空輸入 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	/* 選擇 EXTI 的訊號源 */
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
	EXTI_InitStructure.EXTI_Line = EXTI_Line0;
	
	/* EXTI 為中斷模式 */
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	/* 上升沿中斷 */
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	/* 使能中斷 */
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
	
	/*--------------------------KEY2 配置------------------*/
	/* 選擇按鍵用到的 GPIO */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
	/* 配置為浮空輸入 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	
	/* 選擇 EXTI 的訊號源 */
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);
	EXTI_InitStructure.EXTI_Line = EXTI_Line13;
	
	/* EXTI 為中斷模式 */
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	/* 下降沿中斷 */
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	/* 使能中斷 */
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
}
#define KEY1_IRQHandler EXTI0_IRQHandler
#define KEY2_IRQHandler EXTI15_10_IRQHandler
void KEY1_IRQHandler(void)
{
	//確保是否產生了 EXTI Line 中斷
	if (EXTI_GetITStatus(EXTI_Line0) != RESET) 
	{
		// LED1 取反
		static uint8_t tmp = 0;
		/*LED1 反轉*/
		if(tmp == 0)
		{
			UseLibSetOutput(GPIOB, GPIO_Pin_0,0);
			tmp = 1;
		}
		else
		{
			UseLibSetOutput(GPIOB, GPIO_Pin_0,1);
			tmp = 0;
		}
		//清除中斷標誌位
		EXTI_ClearITPendingBit(EXTI_Line0);
	}
}
 
void KEY2_IRQHandler(void)
{
	//確保是否產生了 EXTI Line 中斷
	if (EXTI_GetITStatus(EXTI_Line13) != RESET) 
	{
		// LED2 取反
		static uint8_t tmp1 = 0;
		/*LED1 反轉*/
		if(tmp1 == 0)
		{
			UseLibSetOutput(GPIOB, GPIO_Pin_5,0);
			tmp1 = 1;
		}
		else
		{
			UseLibSetOutput(GPIOB, GPIO_Pin_5,1);
			tmp1 = 0;
		}
	//清除中斷標誌位
	EXTI_ClearITPendingBit(EXTI_Line13);
	}
}

main.c

int main()
{
	int i;
	LedGpioInit();
	EXTI_Key_Config();
	while (1) 
	{

	}

	return 0;
}

• 由 青梅煮久 寫於 2020 年 12 月 29 日

相關文章