正点原子--STM32中断系统学习笔记(2)

引言

上篇帖子STM32中断系统学习笔记(1)是理论,这篇帖子开始实战,目标是通过按键实现LED的控制。

1.工程建立

以正点原子HAL库 实验1 跑马灯实验为基础,复制工程,在“Drivers--BSP”目录下建立EXTI文件夹,并创建exti.c和exti.h文件;

正点原子--STM32中断系统学习笔记(2)_第1张图片

2.导入C文件

第一步:

正点原子--STM32中断系统学习笔记(2)_第2张图片

第二步: 

 正点原子--STM32中断系统学习笔记(2)_第3张图片

第三步:添加exti.c 

正点原子--STM32中断系统学习笔记(2)_第4张图片 

正点原子--STM32中断系统学习笔记(2)_第5张图片

第四步:跳转到exti.h 

正点原子--STM32中断系统学习笔记(2)_第6张图片正点原子--STM32中断系统学习笔记(2)_第7张图片 添加这部分代码

#ifndef _EXTI_H
#define _EXTI_H

#include "./SYSTEM/sys/sys.h"

#endif

 3.查看原理图

正点原子--STM32中断系统学习笔记(2)_第8张图片

我们想要最终实现的效果是按下KEY0使LED0灯翻转,按下KEY1使LED1翻转。

 配置LED0和LED1引脚为推挽输出模式(之前工程已经配置过),KEY0和KEY1引脚为中断输入模式;

 4.编写代码

正点原子--STM32中断系统学习笔记(2)_第9张图片

按照正点原子给的步骤一步步来配置,最重要的是学习配置思路,一通百通!!

4.1 外部中断初始化

void exti_init(void)
{
	GPIO_InitTypeDef gpio_init_struct;
	__HAL_RCC_GPIOA_CLK_ENABLE();															/* 使能PA引脚时钟 */
	__HAL_RCC_GPIOC_CLK_ENABLE();															/* 使能PC引脚时钟 */
	
	gpio_init_struct.Pin = GPIO_PIN_15;               	/* 按键 KEY1 引脚 */
	gpio_init_struct.Mode =  GPIO_MODE_IT_FALLING;     	/* 外部中断下降沿触发 */
	gpio_init_struct.Pull = GPIO_PULLUP;                  /* 上拉 */
	HAL_GPIO_Init(GPIOA, &gpio_init_struct);         /* 配置初始化 */

	gpio_init_struct.Pin = GPIO_PIN_5;                /* 按键 KEY0 引脚 */
	gpio_init_struct.Mode =  GPIO_MODE_IT_FALLING;   /* 外部中断下降沿触发 */
	gpio_init_struct.Pull = GPIO_PULLUP;            /* 上拉 */
	HAL_GPIO_Init(GPIOC, &gpio_init_struct);       /* 配置初始化 */
	
	HAL_NVIC_SetPriority(EXTI15_10_IRQn,1,0);	/* 配置抢占优先级和响应优先级 */
	HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);			/* 使能中断 */
	
	HAL_NVIC_SetPriority(EXTI9_5_IRQn,2,0);		/* 配置抢占优先级和响应优先级 */
	HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);			/* 使能中断 */	
}

代码解释: 

①由原理图得知KEY0对应PC5,KEY1对应PA15,那么首先我们要使能PA和PC端口的时钟 ;

	GPIO_InitTypeDef gpio_init_struct;
	__HAL_RCC_GPIOA_CLK_ENABLE();															/* 使能PA引脚时钟 */
	__HAL_RCC_GPIOC_CLK_ENABLE();															/* 使能PC引脚时钟 */

②配置引脚号,引脚模式,有无上下拉电阻,以及配置完成初始化,这里需要注意一点的就是引脚模式配置为外部中断下降沿触发正点原子--STM32中断系统学习笔记(2)_第10张图片

	gpio_init_struct.Pin = GPIO_PIN_15;               	/* 按键 KEY1 引脚 */
	gpio_init_struct.Mode =  GPIO_MODE_IT_FALLING;     	/* 外部中断下降沿触发 */
	gpio_init_struct.Pull = GPIO_PULLUP;                  /* 上拉 */
	HAL_GPIO_Init(GPIOA, &gpio_init_struct);         /* 配置初始化 */

	gpio_init_struct.Pin = GPIO_PIN_5;                /* 按键 KEY0 引脚 */
	gpio_init_struct.Mode =  GPIO_MODE_IT_FALLING;   /* 外部中断下降沿触发 */
	gpio_init_struct.Pull = GPIO_PULLUP;            /* 上拉 */
	HAL_GPIO_Init(GPIOC, &gpio_init_struct);       /* 配置初始化 */

正点原子--STM32中断系统学习笔记(2)_第11张图片

为什么要配置为上拉电阻:由原理图知,当我们按下KEY0时,GND导通,此时KEY0是低电平,我们接一个内置上拉电阻,那么KEY0在空闲状态时就是高电平。当按键按下时,KEY0的电平从高---->低,就是一个下降沿,这时我们配置引脚模式为下降沿触发,就能让外部中断信号顺利进入NVIC中断管家里。

正点原子--STM32中断系统学习笔记(2)_第12张图片

③ 配置中断分组,中断优先级,使能中断

在stm32f1xx_hal.c里HAL_Init函数里,已经默认配置好了中断分组为2,所以我们只需要配置中断优先级以及使能中断就行;

正点原子--STM32中断系统学习笔记(2)_第13张图片

	HAL_NVIC_SetPriority(EXTI15_10_IRQn,1,0);	/* 配置抢占优先级和响应优先级 */
	HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);			/* 使能中断 */
	
	HAL_NVIC_SetPriority(EXTI9_5_IRQn,2,0);		/* 配置抢占优先级和响应优先级 */
	HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);			/* 使能中断 */	

 HAL_NVIC_SetPriority,第一个参数是中断向量,选中它后按F12就能来到枚举类型的中断向量。正点原子--STM32中断系统学习笔记(2)_第14张图片

正点原子--STM32中断系统学习笔记(2)_第15张图片

由EXTI和IO的重映射关系我们得知,PC5对应的EXTI线是EXTI5,PA5对应的EXTI线是EXTI15,所以我们要在IRQn_Type里找到我们所需要的中断向量, EXTI0~EXTI4有各自对应的中断向量,而EXTI5~EXTI9共用一个中断向量EXTI9_5_IRQn,EXTI10~EXTI15共用一个中断向量EXTI15_10_IRQn;

之后再配置抢占优先级和响应优先级即可,还有使能中断。

正点原子--STM32中断系统学习笔记(2)_第16张图片

4.2 中断处理函数

思路:由HAL库中断回调处理机制得知,当发生中断后,首先进入到对应的中断服务函数里,比如KEY0(对应PC5引脚)按键按下,就会进入EXTI9_5_IRQHandler函数里,并调用HAL库中断处理公用函数HAL_GPIO_EXTI_IRQHandle(),在中断处理公用函数里会进行清中断标志位,调用中断回调函数HAL_GPIO_EXTI_Callback()的操作。

正点原子--STM32中断系统学习笔记(2)_第17张图片

/* KEY1按键中断处理函数 */
void EXTI15_10_IRQHandler(void)
{
	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15);		/* 公共处理函数 */
	
	/* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
	__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_15);		
}

/* KEY0按键中断处理函数 */
void EXTI9_5_IRQHandler(void)
{
	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5);		/* 公共处理函数 */
	
	/* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
	__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_5);
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	delay_ms(20);    /* 延时消除按键抖动 */
	switch(GPIO_Pin)
	{
		case GPIO_PIN_15 :
			if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15) == 0)    /* 检测KEY1是否按下 */
			{ HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8);		/* 翻转LED0 */ }break;
			
		case GPIO_PIN_5 :
			if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_5) == 0)     /* 检测KEY0是否按下 */
			{ HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_2);		/* 翻转LED1 */ }break;
		default:
				break;	
	}
}

正点原子--STM32中断系统学习笔记(2)_第18张图片

而 HAL_GPIO_EXTI_Callback()是虚函数,最后按照我们的思路编写HAL_GPIO_EXTI_Callback()就好了。正点原子--STM32中断系统学习笔记(2)_第19张图片

main函数里只添加exti_init()外部中断初始化。

正点原子--STM32中断系统学习笔记(2)_第20张图片 

OK,外部中断的原理和实验到此结束,完结撒花*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。


本篇完。

本人博客仅代表个人见解方便记录成长笔记。

若有不足,请指出,感谢您的阅读!

你可能感兴趣的:(stm32,学习,笔记,单片机,正点原子)