STM32CubeIDE基础学习-EXTI外部中断实验
文章目录
- STM32CubeIDE基础学习-EXTI外部中断实验
- 前言
- 第1章 硬件介绍
- 第2章 工程配置
- 2.1 工程外设配置部分
- 2.2 生成工程代码部分
- 第3章 代码编写
- 第4章 实验现象
- 总结
前言
中断概念:让CPU打断正在执行的程序,进而去执行紧急的程序,退出中断后回到原打断中断处继续执行。
前面学习了GPIO作为输入功能的实验,现在来学习使用中断的方式实现GPIO功能的控制,直接在KEY的工程基础上进行添加中断的功能代码就行,其它的功能不用修改。
外部中断实验和KEY按键实验的现象是一样的,只是本实验采用的是中断的方式实现而已,前面按键使用的查询方式,比较耗CPU。
这里说明一下:
前面按键使用的是轮询的方式,本实验将采用中断的方式来实现功能的控制,本实验之所以可以用按键来控制蜂鸣器和LED,是因为刚好按键的引脚和中断线是重合的,所以就很好的借用了按键来触发边沿检测进而触发中断,实质和按键关系不是很大。当没有接按键,用杜邦线把该引脚接3.3V 或 GND也可以实现功能,有兴趣可以测试下。
STM32CubeIDE基础知识学习回顾
实验目的:
学习外部中断功能的使用,实现按键控制BEEP和LED状态翻转功能。
第1章 硬件介绍
本实验使用的开发板主控芯片是STM32F103C8T6,其核心原理图如下:
时钟来源使用的是外部高速8M晶振作为高速时钟。
KEY_UP按键接到芯片的PA0引脚上,KEY按键接到芯片的PA2引脚上,原理图如下图所示:
第2章 工程配置
本实验直接采用上一个按键实验的工程作为基础模板,直接拷贝粘贴即可,然后在上面添加EXTI和NVIC的相关功能配置即可,其它不用修改,就不用再新建工程了。
2.1 工程外设配置部分
配置GPIO,鼠标左键点击该引脚,前面按键输入实验设置的功能是输入的,现在是外部中断的实验,那么就需要设置为EXTI的方式了。如下图所示:
选择完成后如下图所示:
这个软件有一个好处就是能实时检测同一个中断线不能多个共存,当你选择了EXTI2后,其它EXTI2的引脚就选不了这个外部中断功能了,比如选了PA2引脚再选择PB2引脚,则会把PA2选择的功能覆盖掉只留下PB2的,这样就说明它们是不能同时使用的,后面就不会存在引脚冲突的问题了。
接下来就可以配置具体端口功能了。
端口功能配置如下:
1、模式配置为上升沿、下降沿和双边沿触发模式。
2、更据硬件原理图来设置输出上拉或下拉。
3、User Label建议定义一个自己喜欢见名知意的名字,方便写程序时查看和方便使用。
模式配置说明如下:
后面几个事件模式本实验没有用到,这里就不展开描述了。
注意:
为了确保能稳定正确读取到按键的触发电平,这里KEY_UP是需要配置下拉输入。
为了确保能稳定正确读取到按键的触发电平,这里KEY是需要配置上拉输入。
配置EXTI0和EXTI2具体的引脚配置如下图所示:
KEY_UP引脚采取上升沿的触发方式,配置为下拉输入。
KEY引脚采取下降沿的触发方式,配置为上拉输入。
配置完EXTI了之后,就可以进行配置NVIC了,主要设置中断使能、中断分组、中断优先级等信息。如下图所示:
设置后如上图所示:要注意标号2处的抢占优先级选择问题,默认是15的,后面代码需要用到延时消抖,如果选择了默认15的话,优先级是最低的,触发中断后会一直卡死在延时里面而出不来,所以这里需要设置的优先级比外部中断的都要高才行,不然就会让程序出问题的。
一般情况下的程序不建议在中断里面放阻塞函数,比如延时、printf等,避免程序执行出错,而且中断执行需要遵循快进快出的原则,不用过多的嵌套复杂代码。
RCC时钟、调试接口都不用修改,保持默认配置即可。
最终配置的功能如下图所示:
到此,整个工程需要新增的功能就配置完成了,接下来就可以生成代码工程进行代码编写了。
2.2 生成工程代码部分
可以按快捷键ALT+K,或者点击生成图标按钮生成代码工程。
生成后最终会显示下图这样的代码:
可以看到继承了前面的外设功能代码,接着就可以在上面添加自己需要实现的中断控制功能的代码了。
第3章 代码编写
进入main函数后如下图所示:
可以看到有这个stm32f1xx_it.c文件,里面存放了生成中断相关的函数代码,可以双击进去看具体的函数定义。如下图所示:
可以看到有两个中断服务处理函数,接着就发现两个中断处理服务程序都调用了HAL_GPIO_EXTI_IRQHandler()函数,函数里面的参数是中断所在的引脚号,那么再跳进去HAL_GPIO_EXTI_IRQHandler()函数里面看具体定义,可以看到下面这个函数的定义情况。如下图所示:
进入之后,可以看到这个中断服务程序先判断中断线的,然后清除中断标志,最后就调用HAL_GPIO_EXTI_Callback()函数。
接着再进去HAL_GPIO_EXTI_Callback()这个函数,发现该函数在库里面是弱定义的,提示需要用户自己重新定义才行。如下图所示:
接着就可以在这个函数里面编写自己的代码了,可以看到这个函数是库提供的,是一个弱定义的函数,说明如果用户没有定义和该函数一样名字的函数,则执行这里面的代码,有检测到定义则执行用户定义的函数功能。
一般情况下都不会直接在这个函数这里面写功能代码的,需要拷贝这个函数到其它地方或其它文件进行编写,具体位置没有强制要求,但一般习惯拷贝到stm32f1xx_it.c里面其它位置进行功能代码编写。
编写完中断处理代码内容如下图所示:
代码片示例如下:
/* USER CODE BEGIN 1 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
HAL_Delay(10); /* 延时消抖 */
switch(GPIO_Pin)
{
case KEY_UP_Pin :
if(HAL_GPIO_ReadPin(KEY_UP_GPIO_PORT, KEY_UP_GPIO_PIN) == GPIO_PIN_SET)/* KEY_UP按下 */
{
HAL_GPIO_TogglePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN); /* BEEP翻转 */
break;
}
case KEY_Pin :
if(HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY_GPIO_PIN) == GPIO_PIN_RESET)/* KEY按下 */
{
HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_GPIO_PIN); /* LED翻转 */
break;
}
}
}
/* USER CODE END 1 */
中断执行逻辑方式和前面按键查询方式是差不多的,当中断线被触发了之后就执行里面的功能代码。KEY_UP是上升沿触发中断,KEY是下升沿触发中断。
到此,采用中断方式控制BEEP和LED的代码就写完了,编译下载后按下对应的按键就可以看到蜂鸣器和LED翻转情况了。
附加部分
前面学习了按键使用宏定义的方式,那么也可以引入到这里来,可以让代码量看上去少了很多。如下图所示:
代码片示例如下:
/* USER CODE BEGIN 1 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
HAL_Delay(10); /* 延时消抖 */
switch(GPIO_Pin)
{
case KEY_UP_Pin :
if(KEY_UP == GPIO_PIN_SET) /* KEY_UP按下 */
{
HAL_GPIO_TogglePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN);/* BEEP翻转 */
break;
}
case KEY_Pin :
if(KEY == GPIO_PIN_RESET) /* KEY按下 */
{
HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_GPIO_PIN);/* LED翻转 */
break;
}
}
}
/* USER CODE END 1 */
要注意,这里使用了相关的外设,则还要把相关头文件引入到这个stm32f1xx_it.c里面才行,不然会报错找不到定义的。如下图所示:
实现这个外部中断的功能就只需要在这个stm32f1xx_it.c文件里面完成代码编写即可,main函数的while里面以及其它所有的文件都不需要再添加写任何的代码了。
到此,整个中断控制的代码就全部写完了。
第4章 实验现象
编译下载代码后,按开发板的KEY_UP按键,可以听到蜂鸣器的状态发生了变化,当再一次按下按键时,蜂鸣器的状态也会翻转。当按下开发板的KEY按键后,可以看到LED灯的状态翻转了,再一次按下时,LED的状态又发生了翻转。当长按按键不松手,则程序会一直保持该执行的状态,能看到这些现象之后则说明这个代码编写逻辑是没有问题的。
总结
这个外部中断的内容不是特别难理解,代码逻辑和按键实验的差不多,当检测到IO的电平发生变化时,即可触发外部中断,进而执行中断服务函数。重点是理解中断线和回调函数的使用问题。
中断执行流程:
按键按下 > 检测到边沿信号从而触发外部中断线 > 跳转到中断服务程序执行该中断 > 最后进行执行中断回调函数。
注意事项:
1)STM32所有IO都支持外部中断功能,但是不同的端口(PORTA ~ PORTC)相同的PIN(PIN0 ~ PIN15)引脚就不能同时使用外部中断。
2)前面判断中断线时,在case里面用了if判断,这个是用于确认按键按下的,目的是为了更准确的判断该中断是否真正的被触发,如果不要这个if判断也是没有问题的,想要程序执行稳定,建议加上的。