外部中断

  • 前言
  • 材料
  • NVIC
  • 新建及配置工程
    • 外部中断和事件中断
    • NVIC配置
  • 进入代码
    • 回调函数
  • HAL_Delay()分析
  • 下载验证
  • 结语

前言

学单片机的,相信对中断的概念都已经了如指掌了,中断具体是什么我在这里也就不再详细说明,不懂的上网找找也一大堆。那么在介绍实验之前我先跟大家简单讲讲STM32当中的NVIC(嵌套向量中断控制器)

材料

正点原子探索者开发板,芯片为STM32F407ZGT6
开发板的原理图
STM32CubeMX
keil MDK

NVIC

NVIC(嵌套向量中断控制器)。NVIC就是控制中断响应的。主要由三个参数,一个是中断使能,一个是抢占优先级,还有一个就是响应优先级。(优先级数值越小,优先级别越高)
中断使能很好理解,就是是否开启中断,如果开启中断,则满足中断触发条件时程序会跳到中断服务程序运行,否则不响应中断主程序继续运行。
抢占优先级是用来判断一个中断是否可以打断另外一个中断的中断服务程序抢先运行。例如A中断触发,正在运行A中断的服务程序,此时B中断也触发,如果B中断的抢占优先级比A的高,则程序会打断A的中断服务程序,去运行B的中断服务程序,即中断嵌套。等B的中断服务程序运行完后继续运行A的中断服务程序。如果B的抢占优先级没有高过A的抢占优先级,则程序不会打断A的中断服务程序,而是待定A的中断服务程序运行完成后才运行B的中断服务程序。
响应优先级是用来判断抢占优先级相同的几个中断那个中断会优先响应。如果几个抢占优先相同的中断同时触发,那么响应优先级高的最先运行。
判断中断的优先级,先看抢占优先级,抢占优先级高的中断优先级别高。抢占优先级相同的情况下,响应优先高的中断优先级别高。抢占优先级和响应优先级相同的情况下,更加中断向量表确定。

新建及配置工程

具体新建过程就不详细说了,还不懂的小朋友看《STM32CubeMX实战教程(一)——软件入门》。
那么首先进入时钟的配置,高低速时钟同样是选择外部晶振。

接下来配置一下时钟的分配系数,同样的本次实验对时钟频率要求不高,只需要选择好这两处并将频率配置在允许范围内即可。

那么接下来同样是打开我们STM32开发板的原理图,分别找到按键和LED的位置,可以看到有两个可编程LED,和四个按键,从中我们可以获得几点信息。

  • led接了上拉电阻,低电平导通
  • 三个按键下拉,低电平有效
  • 一个按键上拉,高电平有效
    此处先不管WK_UP,也就是其余三个按键在按下的一瞬间均会产生一个下降沿,所以引脚应该配置成下降沿触发的中断

    另外找到芯片对应的引脚号,LED分别是PF9、PF10,按键是PE2


    二话不说,把PF9、PF10配置成GPIO_Output,把PE2配置成GPIO_EXIT2也就是外部中断模式,这里的2是指该GPIO是挂载在中断线2上的


    然后进入GPIO配置界面,LED的配置就不多说了,不懂的可以看回《STM32CubeMX实战教程(二)——按键点个灯》接下来开始中断引脚PE2的配置,可以看到在PE2的配置中有三栏,其他两栏都已讲过,而这第一栏看得就有点晕头转向,点开GPIO mode居然有六个选项,其实这已经涵盖了所有外部中断事件的触发类型
  • 上升沿触发的外部中断
  • 下降沿触发的外部中断
  • 上升/下降沿触发的外部中断
  • 上升沿触发的事件中断
  • 下降沿触发的事件中断
  • 上升/下降沿触发的事件中断
    我们在这里选择的是第二项
    可能现在大家对事件中断和外部中断有什么区别还不太清楚,我这里就先简单讲一下,不懂也没关系,在后面的教程中我们将在实践中学习

外部中断和事件中断

从外部激励信号来看,中断和事件的产生源都可以是一样的.之所以分成2个部分,由于中断是需要CPU参与的,需要软件的中断服务函数才能完成中断后产生的结果;但是事件,是靠脉冲发生器产生一个脉冲,进而由硬件自动完成这个事件产生的结果,当然相应的联动部件需要先设置好, 比如引起DMA操作,AD转换等;

简单举例:外部I/O触发AD转换,来测量外部物品的重量;如果使用传统的中断通道,需要I/O触发产生外部中断,外部中断服务程序启动AD转换,AD转换完成中断服务程序提交最后结果;要是使用事件通道,I/O触发产生事件,然后联动触发AD转换,AD转换完成中断服务程序提交最后结果;相比之下,后者不要软件参与AD触发,并且响应速度也更块;要是使用事件触发DMA操作,就完全不用软件参与就可以完成某些联动任务了。

NVIC配置

配置完成GPIO之后我们进入NVIC的配置,可以直接点击GPIO界面内的NVIC来进入GPIO的中断控制器或是System Core下面的NVIC,进入全局中断控制器这里我先简要介绍一下该界面的功能

Priority Group优先级分组 STM32以4个比特位表示中断的抢占优先级响应优先级。中断优先级分组是为了给抢占式优先级响应优先级在中断优先级寄丛器的四个比特位分配各个优先级数字所占的位数。例如3位用于抢占优先级(优先级有23=8种优先级),1位用于响应优先级(优先级有21=2种优先级)。这里因为只用到一个中断,所有如何设置问题都不大
下面就是所有中断的使能及相应优先级设置,前面几个默认已经使能的为系统必须的中断,不可取消,另外我们这里需要对外部中断线2进行使能,这样才能进入中断服务函数进行中断处理

进入代码

配置完这些之后,目前来看是没什么问题了,那么生成代码,编译,认领两个鸭蛋。同样是来到main.h这里看一眼,几下已经我们定义好的引脚号。

/* Private defines -----------------------------------------------------------*/
#define Key_Pin GPIO_PIN_2
#define Key_GPIO_Port GPIOE
#define Key2_EXTI_IRQn EXTI2_IRQn
#define LED0_Pin GPIO_PIN_9
#define LED0_GPIO_Port GPIOF
#define LED1_Pin GPIO_PIN_10
#define LED1_GPIO_Port GPIOF

回调函数

在写代码前,先来介绍一下回调函数的概念,用过STM32中断的应该都知道,单片机再执行中断服务函数之前,Contex-M4内核先将现在使用到的寄存器和主程序中断点的地址压入堆栈(保护现场)。然后程序在中断向量表中找到中断对应的地址。这个地址存储的为中断服务函数的入口地址。然后程序转跳到中断服务函数执行。
那么我们怎么去找到这个中断服务函数呢,这就需要我们打开32的启动文件,翻到这个位置。

显然,这里都是各种中断服务函数的句柄,那么哪个才是我们要的呢,很明显我们刚刚使能的是EXIT2,所以这里对应的就是EXIT2_IRQHandler,而在用STM32CubeMX开发的过程中,我们并不需要去写这么一个函数,这也是与标准库所不同的地方。在代码生成的过程中STM32CubeMX已经帮我们写好了,现在,我们可以右键go to the definition去看看到底帮我们写了什么。

于是,我们便进入了stm32f4xx_it.c这个文件里面,那么本次实验的代码也将在这里完成,那么是不是将我们需要的中断服务内容添加到里面就可以了呢。别急,还没看完呢,它又调用了一个 HAL_GPIO_EXTI_IRQHandler 这个函数,难道就不好奇里面是什么?带着这份好奇,我们接着往里追。

紧接着就来到了这里,很明显在清楚标志位后又进入了一个
HAL_GPIO_EXTI_Callback(GPIO_Pin) 这个函数,这里就有一点需要注意了,它已经把本该是我们要去清除的标志位给清除了,也就是说,我们在使用STM32CubeMX开发的过程中,使用的任何中断都不需要去关心标志位的问题。这也可以很明显的反应出一点,就是STM32CubeMX在试图让我们少碰,或是不需要关心32开发过程中硬件层的问题,只用做好应用层的开发就足够了,这其实是一大进步。
至于 HAL_GPIO_EXTI_Callback(GPIO_Pin) 呢,就是传说中的回调函数了,好我们进去看看。

看似一个很简单的函数却有着两个从没见过的用法,其实也很简单,__weak 是一个弱化标识,带有这个的函数就是一个弱化函数,什么意思呢,就是你可以在其他地方写一个名称和参数都一模一样的函数,编译器就会忽略这一个函数,而去执行你写的那个函数;而UNUSED(GPIO_Pin)这就是一个防报错的定义,当传进来的GPIO端口号没有做任何处理的时候,编译器也不会报出警告
到这里,我就分析的一遍回调函数,其实总结一下就是:我们在开发的时候已经不需要去理会中断服务函数了,只需要找到这个中断回调函数并将其重写即可
而这个回调函数还有一点非常便利的地方这里没有体现出来,就是当同时有多个中断使能的时候,STM32CubeMX会自动地将几个中断的服务函数规整到一起并调用一个回调函数,也就是无论几个中断,我们只需要重写一个回调函数并判断传进来的端口号即可,还是非常方便的。
那么接下来我们就在stm32f4xx_it.c这个文件的最下面添加这段代码


/* USER CODE BEGIN 1 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if(GPIO_Pin==Key_Pin){HAL_Delay(100);if(HAL_GPIO_ReadPin(Key_Pin_Port,Key_Pin)==0){HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);}}
}
/* USER CODE END 1 */
  • 重写回调函数
  • 判断端口号
  • 延时消抖
  • 翻转LED状态
    代码很简单,一目了然,编译一遍,没有任何问题,那么是不是就结束了呢,还为时过早,现在下载进单片机只会让它在按键按下后没有任何反应,这又是为什么呢,其实问题出在HAL_Delay()上

HAL_Delay()分析

这时候下载的代码,用keil单步执行不难看出,在进入回调函数之后就一直在HAL_Delay陷入了死循环中,怎么也出不来,小小的延时函数为什么会出现这种情况呢?百度一下HAL_Delay函数卡死,相关帖子层出不穷,真正说出原因并提供解决方法的几乎没有。但其实原因并不难,进来HAL_Delay函数看看就知道。

/*** @brief This function provides minimum delay (in milliseconds) based *        on variable incremented.* @note In the default implementation , SysTick timer is the source of time base.*       It is used to generate interrupts at regular time intervals where uwTick*       is incremented.* @note This function is declared as __weak to be overwritten in case of other*       implementations in user file.* @param Delay specifies the delay time length, in milliseconds.* @retval None*/
__weak void HAL_Delay(uint32_t Delay)
{uint32_t tickstart = HAL_GetTick();uint32_t wait = Delay;/* Add a freq to guarantee minimum wait */if (wait < HAL_MAX_DELAY){wait += (uint32_t)(uwTickFreq);}while((HAL_GetTick() - tickstart) < wait){}
}

这是延时函数的原型,同样,有着 __weak 的标识,意味着你可以自己写一个延时函数并用同样的函数名。但这不是重点,可以看到函数上方有说明,第二条注意事项清楚地说道:计时器的时基来源是 SysTick定时器,且在固定时间间隔内产生中断Interrupt这一词是问题的关键,既然是中断,势必就有优先级,如果在中断里面HAL_Delay会卡死,而main函数则不会,那么有没有可能是Systick优先级太低造成的呢。带着这个问题我们回到STM32CubeMX中重新找到NVIC

这时候我们注意到在默认使能的中断里面有一个System tick的中断,这就是给HAL_Delay函数提供时基的定时器中断了。显然,这个中断的抢占优先级外部中断抢占优先级是一样的,那么在外部中断触发时肯定不能接着触发systick中断了,问题已经找到,只需要简单地将外部中断的抢占优先级改低即可

下载验证

重新生成代码编译就可以下载验证了,最后我的工程已上传在《HAL库外部中断实验》,工程与讲解有些许不同,是初始化了三个按键的外部中断
非常抱歉由于CSDN官网上传的资源必须要设定积分,否则几乎无法通过审核,这里就没有办法免费开发给大家,不过源码在教程里已经非常详细了。

结语

非常感谢大家的阅读,如有不当或者错误的地方,欢迎指正,谢谢支持。小编一个字一个字敲出来不容易,如果觉对你有帮助的,别忘了点个赞~
祝大家事业蒸蒸日上!

奥里给~

STM32CubeMX实战教程(三)——外部中断(中断及HAL_Delay函数避坑)相关推荐

  1. STM32CubeMX 实战教程:定时器中断实验(LL 库)

    1.资源的获取:关注博主并点赞对应博客,并在文章下留言邮箱索取: 2.资源的类型:获取资源仅限于免费公开文章或粉丝免费专享文章,不包括付费文章:   博主分享不易,请给三连哦(关注 + 点赞 + 收藏 ...

  2. STM32CubeMX实战教程(七)——TFT_LCD液晶显示(附驱动代码)

    液晶显示 前言 材料 TFT_LCD FSMC接口 原理图 工程配置 进入代码 驱动程序引入 代码分析 TFTLCD_Init LCD_Drawxxx LCD_Fill LCD_Showxxxx 功能 ...

  3. 昆仑通态人机界面与单片机通信实战教程三:脚本驱动与HDMI工程的关联

    大家好,我是『芯知识学堂』的SingleYork,前面给大家介绍了"昆仑通态人机界面与单片机通信实战教程二:脚本驱动的设计",今天笔者就要来给大家介绍"昆仑通态人机界面与 ...

  4. stm32cubeide外部中断_【STM32】HAL库 STM32CubeMX教程三----外部中断(HAL库GPIO讲解)

    前言 上一节我们讲解了STM32CubeMX的基本使用和工程的配置,那么这一节我们正式来学习CubeMX配置STM32的各个外设功能了 今天我们会详细的带你学习STM32CubeMX配置外部中断,并且 ...

  5. STM32CubeMX实战教程(一)——软件入门

    软件入门 前言 新建工程 界面简介 MCU 外设配置 时钟树 工程设置 工具 生成代码 代码分析 main.c gpio.c stm32f4xx_it.c 程序下载 现象 结语 前言 STM32Cub ...

  6. esp8266 米家_【保姆级教程】米家全屋智能家居避坑指南+新手必购单品推荐(2020版)_智能家居...

    2020-11-06 18:13:5915点赞95收藏20评论 前方超级干货预警!请先按[⭐]收藏备用! 关于小米智能家居的内容很多.可随着米家产品的迭代,很多教程已经成为了时代的眼泪.恰好今年新入坑 ...

  7. 分布式场景实战第二节 分布式场景下es和mysql避坑指南

    03 Elasticearch 注意要点:这三点你不得不知 02 讲中我们提到 Elasticsearch 能在短时间内搜索.分析大量数据,并作为查询数据的存储系统.坦白地说,Elasticsearc ...

  8. editor修改样式 vue_手摸手Electron + Vue实战教程(三)

    系列文章: 手摸手Electron + Vue实战教程(一) 手摸手Electron + Vue实战教程(二) ❝ 上一篇我们已经完成了左侧菜单栏的基本样式功能,这一篇我们就主要来开发右侧的Markd ...

  9. STM32CubeMX实战TFT_LCD液晶显示-探索者专用(转发)

    STM32CubeMX实战教程(七)--TFT_LCD液晶显示(附驱动代码) 会开发的喵 2020-07-30 16:10:53 2636 收藏 53 分类专栏: STM32CubeMX--HAL库开 ...

最新文章

  1. 解决 Android : Can't convert value at index 4 to dimension: type=0x1
  2. 给asterisk写app供CLI调用
  3. gcc 安装在服务器的问题总结
  4. shell初学之PHP
  5. zend7 常用快捷键
  6. C++中头文件iostream介绍
  7. [源码和文档分享]基于Android的家庭学校联系平台APP开发与实现
  8. (XWZ)的python学习笔记Ⅶ——正则表达式
  9. 4条地铁线,乘船到西站!杭州西站枢纽综合交通规划设计方案出炉
  10. HTML——<blockquote>与<q>的区别
  11. JQ ajax 请求事件处理
  12. 操作系统----大内核与微内核
  13. 郭敬明最经典的45句话
  14. 计算机上的计算器在那里了,电脑上的计算器在哪里打开(电脑快捷调出计算器的方法)...
  15. 利用动态气泡图进行数据分析
  16. The Tomcat server configuration at\...详细步骤
  17. verilog复习与vhdl入门
  18. 洛谷P2265 路边的水沟
  19. 轻松入门Python爬取基金数据
  20. python 字符串转图片_python用base64库进行图片与字符串的转换

热门文章

  1. RHCE笔记--第三天
  2. 肇庆的海运集装箱港口分布
  3. 电磁场仿真——均匀平面波在真空中的三维传播情况的仿真
  4. VMware平台部署KVM网络无法通信
  5. java ehcache lru_ehcache缓存淘汰浅析
  6. Java Array、List、Set互相转化
  7. Python+Vue计算机毕业设计食品质量安全追溯平台yoh8h(源码+程序+LW+部署)
  8. 自动驾驶中间件之三:活跃玩家盘点
  9. 谈谈java中的==和equals
  10. 亚马逊:了不起的中国卖家,搞定亚马逊关联买家秀视频爆单