文章内容
:
使用 STM32CubeMX 和 HAL 库完成编程练习:用 STM32F103 核心板的 GPIOA 端一管脚接一个 LED,GPIOB 端一管脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED 亮灯;接低电平时,LED 灭灯。
目录
1 何为中断
1.1 中断方式
-
中断方式
是处理器和外部设备的数据传输方式。一方通过申请中断的方式与另一方进行数据传输,收发双方可以并行工作。 -
中断全过程
① 中断发生:当 CPU 在处理某一事件A时,发生了另一事件 B,请求 CPU 迅速去处理
② 中断处理:CPU 暂停当前的工作,转去处理事件 B
③ 中断返回:当 CPU 将事件 B 处理完毕后,再回到事件 A 中被暂停的地方继续处理事件 A
-
中断的作用
速度匹配 、 分时操作、实时响应、可靠性高
1.2 中断优先级
- 中断允许嵌套,不同的中断有不同的优先级,处理器根据不同中断的重要程序设置不同的优先等级。
- 不同优先级中断的处理原则是:
高级中断可以打断低级中断;低级中断不能打断高级中断
- 下图是中断嵌套的执行示意图
- HAL 库初始化函数 HAL_Init 将优先级分组设置为第4组,即有0~15,共16级抢占优先级,没有子优先级。编号越小的优先级越高:0号为最高,15号为最低。
下图为 STM32 中断优先级
1.3 外部中断
- 什么是外部中断呢?
举个例子:
比如你和朋友相约下午一起出门看电影,他还有点事情要处理,没说具体时间,这时你想知道什么时候出发,你有两种方法:1、不停地问他,你的事办完了吗;2、等他办完了,让他通知你。
后者就是外部中断。 - 外部中断/事件控制器( EXTI )
EXTI(External interrupt/event controller)—–外部中断/事件控制器,管理了控制器的 20个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。
1.4 GPIO 引脚的外部中断
- GPIO 引脚的外部中断触发方式
上升沿触发、下降沿触发、双边沿触发 - 外部中断线
属于外部中断的线共有16条,引脚数量多于16,所以引脚要共用外部中断线。
尾号相同的引脚一组,接入1个外部中断线;同组引脚只能有一个设置为外部中断功能
2 中断实现开关 LED 灯
概述:用 STM32F103 核心板的 GPIOA 端一管脚接一个 LED,GPIOB 端一管脚接一个开关(这里用杜邦线模拟代替)。采用中断模式编程(即外部中断),当开关(GPIOB)接高电平时,LED 亮灯;接低电平时,LED 灭灯。
2.1 准备工作
- STM32 开发板(我的是 STM32F103C8T6 )
- STM32CubeMX 软件、 IDE: Keil5 软件
- STM32F1xx HAL 库
- 按键(中断)管脚:PB15
- LED 管脚: PA5
2.2 按键电路
(由于条件有限,实际电路中我们采用用杜邦线的连接模拟代替按键的开关)
- 上拉式按键:
按键按下(接低电平),引脚 PB15 读到低电平
按键释放(接高电平),引脚 PB15 读到高电平 - 触发方式:
按键按下瞬间,形成下降沿
按键释放瞬间,形成上升沿
2.3 CubeMX 生成工程
2.3.1 基础配置
- 点击
File->New Pioject
,创建新工程 - 选择
STM32F103C8
芯片,点击Start Project
进入工程即可 - 配置系统调试接口
SYS
,选择Serial Wire
- 配置外设
RCC
,选择 HSE (外部高速时钟)为Crystal/Ceramic Resonator
(晶振/陶瓷谐振器)
2.3.2 GPIO 配置
- 引脚分配
选择 LED 灯引脚 PA5,设置引脚为输出模式 GPIO_Output;
选择作为外部中断的引脚 PB15,设置为与中断线 GPIO_EXTI15 连接。
- 外设配置
① 将 GPIO_PA5 命名为 LD1
② 将 GPIO_PB15 命令为 B1_EXTI ,触发方式选择下降沿触发
③ 使能引脚对应的外部中断线 EXTI line[15:10]
④ 配置中断优先级
2.3.3 生成 Keil 5 工程
- 命名文件(尽量为英文,存放目录也是),选择 MDK V5 工具
- 点击
GENERATE CODE
,生成工程
2.4 添加代码
- 外部中断处理函数
外部中断处理逻辑与按键扫描一样,当检测到按键时, LED 状态变化。回调函数中无需处理中断标志位,是因为此项工作已经由 HAL_GPIO_EXTI_IRQHandler 完成。
将下面代码写入图中 main.c 的对应位置处
/*
* @brief EXTI line detection callbacks.
* @param GPIO_Pin: Specifies the pins connected EXTI line,
* @retval None
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if( GPIO_Pin == B1_EXTI_Pin ) // 判断外部中断源
{
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin); // 翻转LD1状态
}
}
注意
:本任务只设置一个外部中断引脚,因此不需要判断多个引脚。如果系统中设置了多个外部中断,建议使用 switch-case 进行多分支判断。有兴趣可以了解一下这位大佬的博客:HAL库教程4:外部中断
- 其余部分不用修改
主函数的死循环中,不处理任何业务,所以什么都不用填写,可以让芯片进入休眠模式。 - 分析生成的部分代码
函数 static void MX_GPIO_Init(void)
是 CubeMX 自动生成的引脚初始化函数,不需要做修改。
其中,设置了外部中断触发方式为:下降沿触发
。
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
设置了外部中断 EXTI15_10 的中断优先级为15,并使能这个外部中断。
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 15, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
2.5 编译烧录
- 编译生成 hex 文件
- 烧录
注意
:烧录前将板子上的 BOOT0 置1,BOOT1 置0;烧录后,将板子断电,将 BOOT0 置0,BOOT1 置0,再插电即可出现效果。
2.6 实际效果
从实际效果可以看到:GPIO_PB15 接高电平时,LED 亮;接低电平时,LED 灭。
3 总结
用中断模式控制 LED 亮灭,有 CubeMX 来辅助加成,总体做起来还是比较简单的。我们还是需要考虑中断的过程、优先级、引脚配置。按照要求实现中断。
在上面操作中,我们使用的是杜邦线代替按键开关,不存在按键的
消抖。
如果使用按键开关,就要考虑如何消除按键在闭合或松开时,产生的机械抖动。我们可以采用扫描输入参数中指定的引脚,检测其电平变化,并作延时
消抖处理,最终对按键消息进行确认。具体操作可以参考下面第二条博客。
文章内容如有错误或疑问,敬请读者斧正。
4 参考资料
1、HAL库教程4:外部中断
2、《嵌入式-STM32开发指南》第二部分 基础篇 - 第3章 按键(HAL库)
3、百度网盘资料链接:https://pan.baidu.com/s/1NPfFIrwgX80IC3Xz8D-EEw
提取码:luha