STM32学习笔记(2.1建立一个简单的中断)

STM32学习笔记

第二章 1.建立一个简单的中断


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

建立一个按键触发的中断


提示:以下是本篇文章正文内容,下面案例可供参考

一、stm32f1系列的中断简介

STM32F103 的中断控制器支持 19个外部中断/事件请求:

EXTI 线 0~15:对应外部 IO 口的输入中断
EXTI 线 16:连接到 PVD 输出。
EXTI 线 17:连接到 RTC 闹钟事件。
EXTI 线 18:连接到 USB 唤醒事件。
EXTI 线 19:连接到以太网唤醒事件。

从上面可以看出,STM32F1 供 IO 口使用的中断线只有16 个,但是 STM32F1 的 IO 口却远远不止 16 个,于是就只能复用,EXTI0链接(GPA0~GPG0)的所有中断,而中断线每次只能连接到 1 个 IO 口上
EXTI负责的管脚图

二、建立一个按键中断

总结:初始化引脚xx触发->配置中断优先级->EXTI0_IRQHandler(void) EXTI0线接口清零标志位且调用下面函数
->HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_n) 判断具体引脚执行具体功能


1) 使能 IO 口时钟,初始化 IO 口为输入

//外部中断初始化

	 GPIO_InitTypeDef GPIO_Initure;
	 __HAL_RCC_GPIOA_CLK_ENABLE(); //开启 GPIOA 时钟
	 __HAL_RCC_GPIOE_CLK_ENABLE(); //开启 GPIOE 时钟
	 GPIO_Initure.Pin=GPIO_PIN_0; //PA0
	 GPIO_Initure.Mode=GPIO_MODE_IT_RISING; //上升沿触发
	 GPIO_Initure.Pull=GPIO_PULLDOWN;
	 HAL_GPIO_Init(GPIOA,&GPIO_Initure); 
	 GPIO_Initure.Pin=GPIO_PIN_3|GPIO_PIN_4; //PE3,4
	 GPIO_Initure.Mode=GPIO_MODE_IT_FALLING; //下降沿触发
	 GPIO_Initure.Pull=GPIO_PULLUP;
	 HAL_GPIO_Init(GPIOE,&GPIO_Initure); 
	 

2) 配置中断优先级(NVIC),并使能中断

//配置三个中断线的优先级
//中断线 0-PA0
 HAL_NVIC_SetPriority(EXTI0_IRQn,2,0); //抢占优先级为 2,子优先级为 0
 HAL_NVIC_EnableIRQ(EXTI0_IRQn); //使能中断线 0
 //中断线 3-PE3
 HAL_NVIC_SetPriority(EXTI3_IRQn,2,2); //抢占优先级为 2,子优先级为 2
 HAL_NVIC_EnableIRQ(EXTI3_IRQn); //使能中断线 2
 //中断线 4-PE4
 HAL_NVIC_SetPriority(EXTI4_IRQn,2,3); //抢占优先级为 2,子优先级为 3
 HAL_NVIC_EnableIRQ(EXTI4_IRQn); //使能中断线 4

3) 在各个EXTI接口中调用外部中断共用入口函数

中断服务函数的名字是在 HAL 库中事先有定义的。这里需要说明一下,STM32F1 的IO 口外部中断函数只有 7个,分别为:

void EXTI0_IRQHandler();
void EXTI1_IRQHandler();
void EXTI2_IRQHandler();
void EXTI3_IRQHandler();
void EXTI4_IRQHandler();
void EXTI9_5_IRQHandler();
void EXTI15_10_IRQHandler();

这几个接口都调用外部中断共用入口函数 HAL_GPIO_EXTI_IRQHandler

//中断服务函数
void EXTI0_IRQHandler(void)
{
 	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); //调用中断处理公用函数
}
void EXTI3_IRQHandler(void)
{
 	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3); //调用中断处理公用函数
}
void EXTI4_IRQHandler(void)
{
 	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4); //调用中断处理公用函数
}

//这就是中断处理公用函数
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
	 if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
	 {
		 __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);	//清理标志位
		 HAL_GPIO_EXTI_Callback(GPIO_Pin);		//执行通用回调函数
	 } 
 }

4) 编写外部中断回调函数HAL_GPIO_EXTI_Callback

//中断服务程序中需要做的事情
//在 HAL 库中所有的外部中断服务函数都会调用此函数
//GPIO_Pin:中断引脚号
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	 delay_ms(100); 		//消抖
	 switch(GPIO_Pin)
	 {
	 	case GPIO_PIN_0:
			 if(WK_UP==1) 
			 {
				LED0=!LED0; //控制 LED0 反转
			 }
	 	break;
	 	case GPIO_PIN_3:
		 	if(KEY1==0) 	//控制 LED1 反转
			 {
				LED1=!LED1;
			 }
		 break;
		 case GPIO_PIN_4:
			 if(KEY0==0) 
			 {
				LED0=!LED0;
				LED1=!LED1; 
			 }
		 break;
		 default :
		 break;
		 }

三、思考

外部中断回调函数 HAL_GPIO_EXTI_Callback,该函数用来编写真正的外部中断控制逻辑。
该函数有一个入口参数就是 IO 口序号。所以我们在该函数内部,一般通过判断 IO 口序号值来确定中断是来自哪个 IO 口,也就是哪个中断线,然后编写相应的控制逻辑。
所以在该函数内部,我们通过 switch 语句判断 IO 口来源,例如是来自 GPIO_PIN_0,那么一定是来自PA0,因为中断线一次只能连接一个 IO 口,而四个 IO 口中序号为 0 的 IO 口只有 PA0,所以中断线 0 一定是连接 PA0,也就是外部中断由 PA0 触发。

思考:如果GPA0和GPB0都有外部中断需求,用switch判断就无法区分,该如何处理同一个EXTI线下的中断处理呢?
答案是:做不到,GPA0和GPB0用的都是中断线0,故只有最后那个配置的有效。画pcb时也要留意这个;

总结

欢迎指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值