自上篇文章STM32 非阻塞HAL_UART_ReceiveIT解析与实际应用,具体总结了HAL库下套娃函数中如何看清库函数的脉络,更细致的认识调用的过程,以解决潜在的问题。又又又遇到了新的问题(GPIO按键中断),感觉网络上和各种资料都没解释清楚的情况下。我又去扒了扒HAL库函数源码,提供不一样解决按键抖动的问题(个人认为除了那些通过配置具体寄存器的外;是从HAL库提供函数的基础上解决的)有别于那种在Callback返回函数中添加延迟和判断具体是否按下按键的方法(个人实际操作感觉这种方法效果也不好)。而是在HAL_GPIO库函数上的HAL_GPIO_EXTI_IRQHandler处理中断函数解决按键抖动带来的问题,是更根上解决问题的方法。

前言

Yume-知乎文章​www.zhihu.com

在这里,还是以我一贯的风格——不重复造轮子。具体如何配置STM32CubeMX初始化、生成工程目录之类的问题。包括关于STM32的Cortex-M3处理器的中断细节都不会在本文章中赘述,想了解的朋友可以自行去翻看“Cortex-M3 权威指南”、“Cortex-M3 技术手册”等相关技术文档,都有中文的翻译版本。本文的目的只在如何具体分析问题,解决问题。

1 STM32CubeMX中GPIO配置(基于正点原子的Stm32F1-Nano板)

像如何配置RCC、配置相关的时钟树、配置中断NVIC、配置中断输入等基础配置,生成工程文件的问题。这里就省略了,有需要的朋友可以参考其他网络上资料。重点就看看关于GPIO配置,便于后面分析讲解代码。

其中,PC0、PC1、PC2为LED灯,当按键触发中断时反转。PC8、PC9、PD2为共地按键(低电平有效),所以设置GPIO为Pull-up。按键的GPIO mode有两个为上升沿触发(Rising edge)和一个下降沿触发(Falling edge),这里其实上升沿或下降沿都没啥特别大的关系。

2 HAL库的GPIO中断响应过程

在初始化相关中断响应函数后,HAL库是如何进行中断响应的。其实和上篇文章

Yume:STM32 非阻塞HAL_UART_Receive_IT解析与实际应用​zhuanlan.zhihu.com

有很多相似的地方,可以借助上篇文章来理解。

同样的,GPIO的入口函数是什么呢?这里先引用“Cortex-M3权威指南”的一张图来简单说明Cortex-M3处理器的中断问题

可以看出Cortex-M3处理器有16个外部I/O中断,分别对应[0:15]端口上。也就是说每个中断端口号(0-15)可以在任一Port(A-G)上,然后通过选择器去决定中断端口采用哪个Port。当然这部分在STM32CubeMX上很容易就能配置并初始化好。自然就会有对应的Handler函数。那具体是啥,我们看看生成的工程文件中“Src”文件夹里的“stm32f1xx_it.c”中断文件中有这么一段注释

大致意思就是:STM32F1xx外部中断处理(Handlers)在“stratup file”中提及到了。有了这信息,再去看看在工程文件的根目录中“startup_stm32f103xb.s”文件(基于Nano版上的处理器)虽然里面是汇编语言,但通过查找“IRQHandler”可以看到

这7个就是外部I/O中断的入口函数(可以看出[0:4]端口是独立的入口,而[5:9]、[10-15]分别共用一个入口)。再看看“stm32f1xx_it.c”文件也能看到对应的函数定义

可以看到进入对应的I/O中断入口函数后就会传输GPIO_Pin口(用户配置的中断端口[0:15])到“HAL_GPIO_EXTI_IRQHandler()”中。那我们再看看这个IRQHandle函数

描述也很清晰地表明了这个函数功能是EXTI中断回应。那具体发生了什么呢?在函数里调用了“__HAL_GPIO_EXTI_GET_IT()”和“__HAL_GPIO_EXTI_CLEAR_IT()”后就调用“HAL_GPIO_EXTI_Callback”用户处理函数,有了解上篇文章

Yume:STM32 非阻塞HAL_UART_Receive_IT解析与实际应用

,应该已经清楚怎么回事了,这里就不赘述了。但关键问题是前面两个调用又是什么?

可以看到,这两并不是函数,而是一个宏。是干嘛的呢?大概可以看出是检查到底是哪个I/O端口触发中断的。所以这里就可以理解为啥[5:9]和[10:15]可以共用入口函数也不会出问题了。原因就在这里可以检查。

那再细致点的去看这两个宏定义,不难发现第一个是获取中断的标志位和确认中断是否产生,由谁产生。第二个则是清除标志位。通过查看“Cortex-M3 技术文档”的相关寄存器,也能更好地理解上面说的过程。

那现在应该很清楚发生了什么事了。发生中断响应时,通过入口函数“EXITx_IRQHandler”进入到“HAL_GPIO_EXTI_IRQHandler()”确认中断端口后,重置对应中断的标志位,进入到“HAL_GPIO_EXTI_Callback用户处理函数中去。那我们只需要在用户处理函数中用switch语句选择不同I/O中断端口GPIO_Pin([0:15])对应不同中断处理任务就行了。例:

3 按键抖动问题分析与解决方案

那如果单纯在用户函数中类似上例中这么写,肯定会发现很严重的问题。发现按下去触发中断时可能会产生两次任务(预期是按下去就触发一次任务)。因为按键时会有抖动的,导致进入了两次中断,相信这不用我来解释为何按键抖动会引发这类的问题。

解决方案大家应该也清楚,要么通过计算添加合适大小电容消除抖动产生的影响,那另一种方案,也是最常见的方案就是添加去抖延迟。在网上也有很多类似的教程,甚至也是针对STM32的。会发现,他们都是在用户处理函数“HAL_GPIO_EXTI_Callback中添加延迟,然后读取确认按键。那问题来了,通过上面一步一步分析HAL库的I/O中断处理过程,就知道在用户处理函数之前的“HAL_GPIO_EXTI_IRQHandler()”确认中断端口中就已经将中断标志位消除了(在用户处理函数之前),意味着抖动仍然能触发中断。然后再通过阅读相关文档,发现STM32中断是依靠向量表机制,也就是说只要触发了中断,一般情况下总是要去响应和清除相应的中断标志位。所以我认为在用户处理函数这么做可能可以解决问题,但以我个人经验,效果并不是很好,原因就是解决问题的方法不太对。

个人认为更正确的做法是在清除标志位之前延迟等待抖动消失,防止因抖动在此将中断标志位置为有效。即需要修改HAL库(Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c)中的“HAL_GPIO_EXTI_IRQHandler”函数。如图,在“__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);”之前添加延迟“HAL_Delay((uint32_t)20);”

然后再用户处理函数中返回前添加延迟。就能比较好的解决按键抖动带来可能重复进入中断的问题。(虽然在我摧残下,还是有可能出现问题,但感觉基本上是能达到预期的,毕竟鼠标都可能因为微动问题出现双击呢)


想说的话

网络上有人批判HAL库效率、为非EE专业设计的,将所有东西都抽象了等一系列问题。但我想说的是,对于大多数普通用户或相关工作者。处理效率固然重要,但开发效率、移植效率也是需要实际考察的。会想起刚接触C51用汇编操作寄存器能时,我也会有点批判高级程序语言的效率各种不如汇编,不如汇编一步一步清晰。但问题是现在微处理器计算性能、寄存器数量也是远远超过以前。面对复杂的项目时,需要操作32位甚至64位总线宽度时,你还能处理各种复杂的关系么。

虽然我有时也觉得怎么一个中断都能套娃般弄得如此复杂,明明感觉有更简便的方法。但也意识到,之所以会弄这么复杂,一方面是为了提高开发者的开发效率,方便移植,另一方面也减少因为手误配置错寄存器,导致不可预知的后果。随着项目复杂度的上升,人为出错的概率也会上升,而用库相比去配置寄存器,出错的概率我认为是更低的。更别说在抽象后高层级的去思考能更好的完成某件任务的逻辑,而不是苦与寄存器相互如何作用的问题发愁。

总的来说,如果认为HAL库牺牲效率,甚至出现感觉不符合预期的Bug出现时无法像配置寄存器类似的方法排错。那我感觉可能就只是片面的去看HAL库函数就是黑盒,实际上这些函数都是能去追溯到具体的寄存器,在追溯的过程中慢慢的可能也能找到Bug的原因,在针对实际场景做修改也不是不可以的。

也许很多地方我表达的不专业,还请多多包涵。


Yume:STM32 非阻塞HAL_UART_Receive_IT解析与实际应用​zhuanlan.zhihu.com

hal库开启中断关中断_[STM32]HAL库下GPIO按键中断与去抖问题分析(分析源码解决问题)...相关推荐

  1. java mysql外文文献_基于Java环境下的高校跳蚤市场商城系统毕业论文+开题报告+设计源码+Mysql文件+外文翻译及原文...

    摘  要 本次设计采用采用了B/S的模式,使用了SSH框架,利用MyEclipse开发工具.Tomcat服务器和MySQL数据库来进行实现的,在前端页面开发中也采用了jsp的相关技术.建立高校跳蚤市场 ...

  2. STM32毕业设计——基于STM32+JAVA+Android的六足机器人控制系统设计与实现(毕业论文+程序源码)——六足机器人控制系统

    基于STM32+JAVA+Android的六足机器人控制系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于STM32+JAVA+Android的六足机器人控制系统设计与实现,文章末尾附有 ...

  3. STM32低功耗模式下GPIO如何配置最节能?

    目录 1.将未使用的GPIO 配置为模拟输入模式 2.调节GPIO 速度 3.GPIO不使用时禁用寄存器时钟 4.避免悬空未使用的引脚 STM32低功耗模式下GPIO如何配置最节能,这里总结了一下四点 ...

  4. STM32毕业设计——基于STM32+MQTT+WiFi技术的智能家居系统设计与实现(毕业论文+程序源码)——智能家居系统

    基于STM32+MQTT+WiFi技术的智能家居系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于STM32+MQTT+WiFi技术的智能家居系统设计与实现,文章末尾附有本毕业设计的论文 ...

  5. 基于stm32、0.96寸OLED实现的俄罗斯方块小游戏(详细源码注释)

    概述:本实验基于stm32最小系统.0.96寸OLED(68*128)和摇杆实现一个经典的俄罗斯方块小游戏.项目源码地址:点击下载. 硬件要求: 普通摇杆,两个电位器和一个开关组成,左右摇动控制一个电 ...

  6. java爬虫代码示例_那些让你代码思维和能力有较大的提升Java源码

    来源:www.cnblogs.com/jiagou/p/9270070.html 对于学习J2EE的框架有很大的帮助,代码里使用了各种设计模式.事件机制.Java8语法.代码量也很小,web服务使用N ...

  7. ioca0中断 pic单片机_用PIC对PT2262进行三态解码(6561个地址),地址码设置方便。...

    //************************PT2262三态解码程序****************************// // //                          ...

  8. 龙芯2k按键中断驱动_字符设备驱动-高级篇按键中断程序驱动

    驱动源码: #include "linux/module.h" #include"linux/kernel.h" #include"linux/fs. ...

  9. v42.05 鸿蒙内核源码分析(中断切换) | 系统因中断活力四射 | 百篇博客分析鸿蒙源码

    子曰:"知者不惑,仁者不忧,勇者不惧." <论语>:子罕篇 百篇博客系列篇.本篇为: v42.xx 鸿蒙内核源码分析(中断切换篇) | 系统因中断活力四射 硬件架构相关 ...

最新文章

  1. 三层交换机原理:02怎么用三层交换机?
  2. 五分钟学会HTML5!(二)
  3. C# Newtonsoft.Json JsonSerializerSettings 全局序列化设置
  4. mybatis实现自定义SQL并且请求参数是集合
  5. 使用Nodejs实现的小说爬虫
  6. 51Nod 蜥蜴和地下室(搜索)
  7. 【蓝桥杯官网试题 - 基础练习】 矩形面积交 (几何)
  8. cfree运行程序错误的原因_Python入门教程 | 第 8 章 错误、调试和测试
  9. 新年UI的拆红包源码/5级代理功能/会员中心充值接口完善
  10. iOS Coding Style Guide 代码规范
  11. 17岁高中生详述如何攻破 GitHub Private Pages 并获$3.5万赏金
  12. 三包围结构的字是什么样的_清桦学书之结构篇——包围结构。
  13. 软件测试:功能测试(1)----测试范围和测试策略
  14. swapfile.sys文件的作用及如何禁用Hibernate.sys和Pagefile.sys
  15. 【机器学习算法】集成学习-1 强学习器的融合学习
  16. 和面试官面对面—常见接口测试面试题汇总(附参考答案)
  17. 《纽约客》特写Jeff Dean与Sanjay:谷歌唯二11级工程师,同一台电脑上写代码
  18. 干掉Session?这个跨域认证解决方案真的优雅
  19. fasterRCNN系列
  20. linux批量重命名脚本,Mac / Linux Shell 批量重命名的方法总览

热门文章

  1. MaxCompute,基于Serverless的高可用大数据服务
  2. 解决WPF中重载Window.OnRender函数失效问题
  3. 微服务实践分享(4)配置中心
  4. 微信发布2017国庆长假出游情况大数据报告
  5. 特征点的基本概念和如何找到它们
  6. CSS3盒子阴影box-shadow
  7. HttpContext.Current:异步模式下的疑似陷阱之源
  8. T4文本模板转换过程
  9. 使用DPM 2012 Sp1保护SQL server 2012 Sp1
  10. 批量安装zabbix-agent脚本