STM32f10x 外部中断及中断分组

Nora ·
更新时间:2024-09-20
· 850 次阅读

利用外部中断来实现按键控制LED灯的亮灭。
实验工具:MDK5,STM32F103ZET6开发板
使用固件库编程
LED灯引脚PD13,按键PE0

首先了解一下32的外部中断

STM32 的每个 IO 都可以作为外部中断的中断输入口,STM32F103 的中断控制器支持 19 个外部中断/事件请求。每个中断设有状位,每个中断/事件都有独立的触发和屏蔽设置。

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

所以这次要用到的就是线 0~15
下图是IO口语中断线的一一映射关系
图一
以线 0 为例:它对应了 GPIOA.0、 GPIOB.0、 GPIOC.0、GPIOD.0、GPIOE.0、 GPIOF.0、 GPIOG.0

使用外部中断的配置过程

图二
在此之前先写一个LED与按键KEY的程序
led.c

#include "led.h" void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStrtuct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE); GPIO_InitStrtuct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStrtuct.GPIO_Pin = GPIO_Pin_13; GPIO_InitStrtuct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD,&GPIO_InitStrtuct); }

key.c

#include "key.h" void KEY_Init(void) { GPIO_InitTypeDef GPIO_InitStrtucter; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); GPIO_InitStrtucter.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStrtucter.GPIO_Pin = GPIO_Pin_0; GPIO_Init(GPIOE,&GPIO_InitStrtucter); } uint8_t Key_scan(void) { if (KEY == 1) { //松手检测 while(KEY == 1) return 1; } else return 0; }

然后就可以根据上面的步骤一步步配置中断了

#include "exti.h" #include "key.h" #include "delay.h" #include "led.h" void EXTIX_Init(void) { EXTI_InitTypeDef EXTI_InitStruct; NVIC_InitTypeDef NVIC_InitStructer; RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断,需要使能AFIO时钟 KEY_Init();//初始化按键 //中断线的映射以及中断初始化配置 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource0);//中断线映射函数 EXTI_InitStruct.EXTI_Line = EXTI_Line0; EXTI_InitStruct.EXTI_LineCmd = ENABLE; EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 模式为interrupt EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发 EXTI_Init(&EXTI_InitStruct); //配置中断分组并使能中断 NVIC_InitStructer.NVIC_IRQChannel = EXTI0_IRQn; //使能按键所在的外部中断通道 NVIC_InitStructer.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_InitStructer.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2 NVIC_InitStructer.NVIC_IRQChannelSubPriority = 0x02; //子优先级1 NVIC_Init(&NVIC_InitStructer); } //中断服务函数 void EXTI0_IRQHandler() { delay_ms(10); //消抖 if(KEY==1) { LED=!LED; } EXTI_ClearITPendingBit(EXTI_Line0); //清除EXTI0线路标志位 } 说明一下

NVIC_InitStructer.NVIC_IRQChannel = EXTI0_IRQn;
它的配置是在stm32f10x.h里面,
PxN管脚共用外部中断线EXTIN和外部中断向量EXTIN_IRQn和中断服务程序入口EXTIN_IRQHandler,但是需要注意[9…5]共用EXTI9_5_IRQn和EXTI9_5_IRQHandler、[15…10]共用EXTI15_10_IRQn和EXTI15_10_IRQHandler。
而中断服务函数void EXTI0_IRQHandler()是在 startup_stm32f10x_hd.s 里面

有关中断分组

具体的分配关系如表 所示:
参考原子哥,易于理解
抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。
这里需要注意两点:
第一,如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;
第二,高优先级的抢占优先级是可以打断正在进行的低抢占优先级
中断的。而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。
结合实例说明一下:
假定设置中断优先级组为 2,然后设置中断 3(RTC 中断)的抢占优先级为 2,响应优先级为 1。中断 6(外部中断 0)的抢占优先级为 3,响应优先级为 0。中断 7(外部中断 1)的抢占优先级为 2,响应优先级为 0。
那么这 3 个中断的优先级顺序为:中断 7>中断 3>中断 6。
上面例子中的中断 3 和中断 7 都可以打断中断 6 的中断。而中断 7 和中断 3 却不可以相互打断!

结论:
1.抢占优先级越小,优先级越高;相同抢占优先级的中断不能相互打断;
2.相同抢占优先级N个中断发生时,响应优先级越小的中断首先执行,如果响应优先级也均相同,则根据各中断对应向量表的位置来确定,向量表中越靠前的中断先响应。

相关程序链接:
https://pan.baidu.com/s/1fH0TareZkEfV4zeOPz_d1w
提取码:hfvw


作者:鱼撞烟花



外部中断 中断 f1 分组

需要 登录 后方可回复, 如果你还没有账号请 注册新账号