打印
[STM32F1]

stm32——基础篇外部中断 实验

[复制链接]
1423|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 aizaixiyuanqian 于 2017-12-7 22:34 编辑

这次实验,我们将学习如何使用 STM32 的外部输入中断。在前几次的学习中,我们掌握了 STM32 的 IO 口最基本的操作。 本次实验我们将介绍如何将STM32 的 IO 口作为外部中断输入,在本实验中,我们将以中断的方式,实现按键控制 LED 亮灭的功能 。 实验目标:
1、 了解 STM32 的中断模式 NVIC 。
2、 了解外部中断的使用方式 。
沙发
aizaixiyuanqian|  楼主 | 2017-12-8 11:50 | 只看该作者
中断的概念
如果学员有单片机的基础,那么就会知道中断的概念。所谓中断是指 CPU 在执行当前程序的过程中,由于某种随机出现的外设请求或 CPU 内部的异常事件,使 CPU 暂停正在执行的程序而转去 执行相应的服务处理程序;当服务处理 程序运行完毕后,CPU 再返回到暂停处继续执行原来的程序。 而有些中断还能够被其他高优先级的中断所中断,那么这种情况又叫做中断的嵌套。

使用特权

评论回复
板凳
aizaixiyuanqian|  楼主 | 2017-12-8 21:48 | 只看该作者
STM32  的中断1) STM32  中断分组
STM32 的中断一共有 68 个可屏蔽中断通道16 个可编程的优先等级;什么叫做可编程等级呢? 首先我们来看一下STM32 中断等级式,STM32 使用一个 4 位寄存器 来设置中断等级的,4 位长度可以设置 16 个优先等级(2 的 4 次方等于 16); 而这个优先等级是可以设置的,所以叫做可编程等级。而且呢,这个 4 位长 度的优先等级还可以分为两部分,一部分叫做抢占优先级,一部分叫做响应 优先(些资料也叫做亚优先级) (比如说: 4 位里面设置 1 位抢占优先级,3 位的响应优先级。)在这里大家可能有点糊涂了,分成抢占优先级和响应优先级又是什么用呢?
在 STM32 的 NVIC 中规定: 抢占优先级高的可以中断抢占优先级比它低 的中断函数,不过相同抢占优先级的之间是不能相互中断的。响应优先级 之间是不能相互中断的,有人或许既然都不能中断了,那响应优先级还有什 么意义呢?如果这两个中断同时到达,则中断控制根据他们的响应优先级 高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等, 则根据他们在中断表中的排位顺序决定先处理哪一个。


使用特权

评论回复
地板
aizaixiyuanqian|  楼主 | 2017-12-8 21:49 | 只看该作者
STM32 的中断分组可以有 5 种分组:如图

2.png (70.85 KB )

2.png

使用特权

评论回复
5
aizaixiyuanqian|  楼主 | 2017-12-8 21:51 | 只看该作者
STM32  中断分组库函数
NVIC_PriorityGroupConfig()
NVIC_PriorityGroup 这个参数是用来选择设置分组的参数,我们知道它一共 可以分为 5 个组别如下图

QQ截图20171208215125.png (179.54 KB )

QQ截图20171208215125.png

使用特权

评论回复
6
aizaixiyuanqian|  楼主 | 2017-12-8 21:54 | 只看该作者
EXTI  外部中断
STM32 的外部中断是有 16 条外部中断 通道,分别对应着每组 IO 口的 Px0 到 Px15。STM32 的每个 IO 口都能用作外部中断,一次性同时使用的外部 中断只能有16 个, 而且同时做外部中断的 IO 口序号也是不能相同的, 你使用 PA0做外部中断了,就不能同时使用 PB0 做外部中断了。

使用特权

评论回复
7
aizaixiyuanqian|  楼主 | 2017-12-8 21:55 | 只看该作者
外部中断的设置步骤:
1) 设置中断分组。
2) 配置 IO 口的模式。(比如你要使用下降沿触发,那么就选择上拉输入 模式,要使用上升沿触发,那么就选择下拉输入模式。)
3) 选择要用作外部中断的 IO 口作为输入。
4) 开启要使用的中断通道并设置外部中断的参数(中断优先级、中 断触发模式)

使用特权

评论回复
8
aizaixiyuanqian|  楼主 | 2017-12-8 22:03 | 只看该作者
关于外部中断库函数介绍
1) RCC_APB2PeriphClockCmd()  我们要打开 GPIOE 及管脚复用的时钟。
2) GPIO_Init() 函数   IO 模式设置为上拉输入:
3) GPIO_EXTILineConfig() 函数
这个函数用来设置作为输入的 IO 口,它有两个输入参数: 第一个参数是使用选择 GPIO 的组别,我们要使用的是 PE2,所以设 置为:GPIO_PortSourceGPIOE。 第二个参数是设置 IO 的序号,我们使用的是 PE2,所以我们为:
GPIO_PinSource2 所以设置代码为:
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource2);

4) NVIC_Init() 函数  设置中断的优先级和打开总中断
5) EXTI_Init() 函数  初始化外部中断
6) EXTI_GetITStatus() 函数
7) 外部中断的中断函数
   EXTI0_IRQHandler
   EXTI1_IRQHandler
   EXTI2_IRQHandler
   EXTI3_IRQHandler
8) EXTI_GetITStatus() 函数

9) EXTI_ClearITPendingBit() 函数




使用特权

评论回复
9
aizaixiyuanqian|  楼主 | 2017-12-8 22:05 | 只看该作者
1)  初始化函数
void exti_init() //外部中断初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* 开启 GPIO 时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitStructure.GPIO_Pin=k_left;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource2);//选择
GPIO 管脚用作外部中断线路
//此处一定要记住给端口管脚加上中断外部线路
/* 设置外部中断的模式 */
EXTI_InitStructure.EXTI_Line=EXTI_Line2;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* 设置 NVIC 参数 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //打开 EXTI2
的全局中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优
先级为 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应
优先级为 0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能
NVIC_Init(&NVIC_InitStructure);
}


使用特权

评论回复
10
aizaixiyuanqian|  楼主 | 2017-12-8 22:06 | 只看该作者
2)  中断函数
void EXTI2_IRQHandler() //外部中断 2 中断函数
{
if(EXTI_GetITStatus(EXTI_Line2)==SET)
{
EXTI_ClearITPendingBit(EXTI_Line0);//清除 EXTI 线路挂起位
delay_ms(10);//消抖处理
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==Bit_RESET)
//k_left 按键按下
{
if(GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_0)==Bit_RESET)
{
//LED 熄灭
GPIO_SetBits(GPIOC,GPIO_Pin_0);
}
else
{
//LED 发光
GPIO_ResetBits(GPIOC,GPIO_Pin_0);
}
}
while(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==0);
}
}

使用特权

评论回复
11
aizaixiyuanqian|  楼主 | 2017-12-8 22:07 | 只看该作者
主函数放到程序里面,大家可以去参考。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

1353

帖子

6

粉丝