前言
使用STM32CubeIDE实现外部中断实验。
硬件:STM32F103C8T6最小系统板 + 自制扩展板
软件:STM32CubeIDE
一、实验目的
使用外部中断线,实现扩展板上的KEY1控制LED1翻转,KEY2控制LED2翻转,KEY3控制蜂鸣器响停。
二、学习内容
- 使用外部中断线的方式来检测按键状态
三、实践操作
1.什么是中断?
打断CPU正常运行的程序,转而处理更加紧急的事件(程序),如下图所示:
打断主程序运行,去处理中断事件,处理完之后又回到主程序继续运行。
中断会影响整个代码的运行时间,因此执行中断一定要快,避免影响主程序的实时性。
中断执行机制大致有三步:
1.中断请求:外设产生中断请求(GPIO外部中断、定时器中断等);
2.相应中断:CPU停止执行当前程序,转而执行中断处理程序(ISR);
3.退出中断:执行中断完毕,返回被打断的程序处,继续往下执行程序。
2.外部中断介绍
检测GPIO口的电平变化(边沿检测),当检测到指定的电平变化时,可触发外部中断,执行中断服务函数。
触发方式:上升沿、下降沿、双边沿(字面意思,上升沿和下降沿都检测)、软件触发(目前不做介绍)
所有的GPIO都支持外部中断,但相同的Pin不能同时使用外部中断,例如PA1和PB1不能同时使用外部中断。
3.硬件介绍
硬件:STM32F103C8T6最小系统板 + 自制扩展板
自制扩展板中有一个蜂鸣器、LED灯与按键,LED1为蓝灯,LED2为橙灯;
蜂鸣器的IO为PA15,LED1的IO为PB3,LED2的IO为PB4,KEY1的IO为PB0,KEY2的IO为PB1,KEY3的IO为PB8,KEY4的IO为PB9;
蜂鸣器为高电平有效,LED1为低电平有效,KEY1~4均为检测低电平;
无外部上拉/下拉电阻(最好在硬件上进行上下拉操作),需在软件中进行弱上拉/下拉。
原理图如下图所示(仅介绍按键,其他外设在上一篇文章中有介绍):
由上图可以看出,若配置上拉电阻,当按键未按下时,IO口读取到高电平,当按键按下时,IO口读取到低电平,这就产生了下降沿信号(高电平 -> 低电平);再松开按键,IO口又读取到高电平,这就产生了上升沿信号(低电平 -> 高电平)。
实物图如下图所示:

KEY1对应EXTI0;KEY2对应EXTI1;KEY3对应EXTI8;KEY4对应EXTI9。
流程图大致如下:
4.软件介绍
首先新建工程并进行初始化配置:
在此不进行赘述,详细步骤可移步至之前文章:4.STM32CubeIDE按键实验
注意:STM32F103C8T6仅有:EXTI0~4、EXTI9_5,这6个外部中断服务函数,因此不对KEY4(PB9)进行配置
与上一篇文章不同的是,需要配置PB0(低电平检测)、PB1(低电平检测)、PB8(双边沿检测)为外部中断,如下图所示:
由上图可以看到,需要将按键IO配置为弱上拉;进行引脚重命名(用户标签);模式可选择上升沿、下降沿或者双边沿。
GPIO mode里有以下选项:
| 模式 | 含义 |
|---|---|
| External Interrupt Mode with Rising edge trigger detection | 上升沿触发的外部中断模式 |
| External Interrupt Mode with Falling edge trigger detection | 下降沿触发的外部中断模式 |
| External Interrupt Mode with Rising/Falling edge trigger detection | 双边沿触发的外部中断模式 |
| External Event Mode with Rising edge trigger detection | 上升沿触发的外部事件模式 |
| External Event Mode with Falling edge trigger detection | 下降沿触发的外部事件模式 |
| External Event Mode with Rising/Falling edge trigger detection | 双边沿触发的外部事件模式 |
外部中断模式与外部事件模式的区别
外部中断模式:硬件触发;会导致CPU暂停当前任务,转而执行与该中断相关联的中断服务程序(ISR);适用于需要CPU参与处理的情况,例如,当需要执行一段代码来响应某个硬件事件时。
外部事件模式:软件触发;不会导致中断服务程序的执行,可以触发其他外设的操作,如定时器或DMA(直接内存访问);适用于不需要CPU介入,而是需要直接通知或控制其他外设时。
除此之外还需要配置中断:
中断优先级有两个:抢占优先级和响应优先级。都是数字越小,优先级越高。当抢占优先级相同时,比较响应优先级。
接下来进行外部中断实验的代码编程
- 具体与之前的步骤相同,详细步骤可移步至之前文章。
- 由于采用外部中断,根据流程图,当有触发信号时,会执行中断服务函数
EXTIx_IRQHandler(),该函数是HAL库自带的,在你生成代码之后就有了(具体在stm32f1xx_it.c中)。
以EXTI0_IRQHandler为例:
void EXTI0_IRQHandler(void)
{
/* USER CODE BEGIN EXTI0_IRQn 0 */
/* USER CODE END EXTI0_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(KEY1_Pin);
/* USER CODE BEGIN EXTI0_IRQn 1 */
/* USER CODE END EXTI0_IRQn 1 */
}
函数中调用的是HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)函数,通过不同的GPIO_Pin来判断是哪个外部中断。
HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)函数:
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}
其中实现功能的主要为HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)中断回调函数,该函数为弱定义函数,我们可以对其进行二次定义。
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
}
接下来我们就可以在main.c中,自己定义中断回调函数了!
/* USER CODE BEGIN PFP */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch(GPIO_Pin)
{
case KEY1_Pin:
LED1_TOGGLE();
break;
case KEY2_Pin:
LED2_TOGGLE();
break;
case KEY3_Pin:
BEEP_TOGGLE();
break;
}
}
/* USER CODE END PFP */
}
在main()函数中,什么也不用写,就可以实现功能!
具体现象:按下KEY1(低电平检测),翻转LED1;按下KEY2(低电平检测),翻转LED2;按下KEY3(双边沿检测),蜂鸣器响,松开KEY3,不响。
注意:在中断回调函数中尽量不使用HAL_Delay(),因为HAL_Delay()的用滴答定时器实现的,滴答定时器的中断优先级默认设置为15,是最低的。
因此在中断回调函数中使用HAL_Delay()会使中断回调函数不被正常运行。
总结
本篇介绍了如何实现一个外部中断实验,分别从硬件方面与软件方面阐述,在硬件方面主要介绍了硬件组成与原理图分析,在软件方面主要介绍了利用中断回调函数实现逻辑功能。完美完成本文开篇提到的学习任务与功能!
对于实验复现,无需限制在本文使用的IO,了解原理之后,可以做出更有趣的功能!
上篇的形式属于轮询,代码实时性低;该篇的形式为中断模式,可以直接触发,代码实时性高。
本文详细介绍了如何在STM32F103C8T6开发板上,利用STM32CubeIDE实现外部中断实验,包括硬件配置、外部中断原理、中断服务函数编写,以及如何通过GPIO检测按键状态控制LED和蜂鸣器。通过中断模式提高了代码的实时性。
1万+

被折叠的 条评论
为什么被折叠?



