按键在嵌入式开发中,是比较重要的,也是常见的外设,因此,很有必要学习,也要掌握编写基础的按键驱动,通常最基本的情况下,都是使用状态机的框架来出来,因为尽管硬件电路上有滤波电路,但还是要软件滤波的。(软件滤波很多采集系统中都是用到的)。 在学习过程中,可以自己尝试编写简单的单机,组合按键单机等,锻炼思维。当然网上有很多的按键驱动库,值得收藏,其中思想是比较好的,可以学习其思路,同事也可以在了解功能后,移植到自己的项目中。
我这里就自己网上看到的,公众号分享的一些文章,特意整理一下,算是一个收集,以后用到了可以直接参考。
1==、 MultiButton:是一个小巧简单易用的事件驱动型按键驱动模块,可无限量扩展按键,按键事件的回调异步处理方式可以简化你的程序结构,去除冗余的按键处理硬编码,让你的按键业务逻辑更清晰
https://github.com/0x1abin/MultiButton 官网 https://zhuanlan.zhihu.com/p/128961191 比较详细的移植文档
2==、 FlexibleButton:是一个基于标准C语言的小巧灵活的按键处理库,支持单击、连击、短按、长按、自动消抖,可以自由设置组合按键,可用于中断和低功耗场景。
该按键库解耦了具体的按键硬件结构,理论上支持轻触按键与自锁按键,并可以无限扩展按键数量。另外,FlexibleButton使用扫描的方式一次性读取所有所有的按键状态,然后通过事件回调机制上报按键事件。核心的按键扫描代码仅有三行,没错,就是经典的 三行按键扫描算法。使用C语言标准库API编写,也使得该按键库可以无缝兼容任意的处理器平台,并且支持任意 OS 和 non-OS(裸机编程)。
https://gitee.com/RT-Thread-Mirror/FlexibleButton 官网
https://mp.weixin.qq.com/s?src=11×tamp=1613181394&ver=2887&signature=WN8P7Q1GwWKEI22eOcETmIQqrarmkOT*cBYof1sb3jgsketPgtUrdd8f36e6762DQIYqjTpzrW0crZr-2C7irEYa1GPbbt10-DY3QDbCjAwXGyKIDvMubpKZoxdslH8V&new=1 微信公众号有分享文章
3==、key_board - 用于单片机中的小巧多功能按键支持库(来自痞子衡的半月刊) key_board 是网友 wei513723 维护的用于单片机中的小巧多功能按键支持库。
项目主页: https://gitee.com/wei513723/key_board
软件采用了分层的思想,并且做到了与平台无关,用户只需要提供按键的基本信息和读写io电平的函数即可,非常方便移植,同时支持多个矩阵键盘及多个单io控制键盘,目前已实现按下触发、弹起触发、长按自动触发、长按弹起触发、多击触发、连续触发等功能,并且能够随意组合(支持状态的同一时间轴和非同一时间轴),后续还会添加更多的功能。
4==、论坛里分享的驱动库 分享一个不错的【程序框架】+【按键状态机】+【LED状态机】程序: http://www.openedv.com/thread-295380-1-1.html 本帖隐藏的内容
用了几年的前后台程序框架,稳定可靠,保证每次执行的任务都为最高优先级任务,楼下会对该程序框架做一些说明。 按键状态机:支持短按,长按,双击处理,程序简洁,简单易懂。 LED状态机:支持各个频率的LED闪烁,常亮,常暗操作。 注:该程序是从基于2G通讯项目中截取下来的两个模块,项目源码不好分享,有兴趣可以加我Q:842936992。
解压密码:123456789 程序框架 LED KEY.zip
具体可以看看原子论坛的帖子,就是没有一个整理好的,需要自己去看
5==、支持长按,短按,连续周期,组合键的按键程序。配置简单,移植方便 http://www.openedv.com/forum.php?mod=viewthread&tid=314209&highlight=%B0%B4%BC%FC
主要实现功能:1、按键无冲,可以同时执行几个按键。 2、消抖不阻塞主程序,因此需要采用1个定时器的资源。 3、支持长按,短按识别。 4、支持连发,不连发模式。 5、移植真的很方便。 6、支持裸机和带实时系统使用。
移植说明:1、需要在key_app.h 的Key_Num枚举添加按键编号,有几个就添加几个。注意,最后的KeyCnt不能删除。 2、编写Key_BspInit函数进行按键硬件的初始化 3、编写Key_AddInit函数添加按键信息,里面的长按执行函数,短按执行函数自行编写。
附件是根据原子key示例代码改的,提供参考。好用的话可以给个赞吗?
更新日志: 1、增加组合按键,添加组合方法,在KeyGroup_Num枚举增加组合数,后调用Add_Change_KeyGP函数增加组合。 2、添加按键和组合函数都增加错误返回。 3、新增删除按键和删除组合函数,删除后重新添加则调用Add_Change_Key或者Add_Change_KeyGP进行添加。
4、按键和组合状态可以根据需要进行实时更新,调用Add_Change_Key或者Add_Change_KeyGP进行更新即可。 5、对应的按键状态都放入一个环形队列进行存储。 6、用户只需修改key_app.c,key.c不需要修改,增加部分注释。 Tips:目前这代码有小小bug,我已经修正了。过几天上传,你们先找找看吧。
更新日志: 1、修复一些bug 2、组合键增加按键顺序判断,由GetKeyNumStrict配置。若是ON,则按键组合必须按照配置组合顺序按下才能激活。若是OFF,则无顺序要求。---该功能暂时没测试,可以帮忙测试,发现bug可以回帖,我去修改。 3、按键硬件已经修改为原子mini板上的 IO,可直接用原子板子直接测试。把串口1连到电脑上,可以看打印信息。
ps:大家可以试下增大KeyCnt按键总数和KeyGPCnt组合数来试下多按键下的效果。我试了添加200个按键,效果也还行。有没有兄弟可以试下去做个机械键盘呢。
更新日志: 1、测试了严格判断按键顺序的组合键功能,修改bug。 2、移植只需修改key_app.c,具体修改地方已在注释中注明,主要是按键初始化函数和提供按键状态函数。主要移植文件为key.c,key_app.c和ringbuff.c。 Timer.c只是为了提供一个1ms循环的环境,在带操作系统的情况下,可以不用,直接用1个任务代替,任务延时为1ms,如截图所示。 3、按键的配置和组合的配置 基本和stm32配置GPIO一样。需要注意的是,添加按键或者组合,自己需要添加枚举。枚举名可以自定义,添加按键和删除按键都需要用到这个枚举名,枚举的最后一个元素 KeyCnt和KeyGPCnt不能删除。
PS:最后,如果大家还需要什么按键上的功能,可以回帖。如果我觉得可以做,就会更新代码。
解压密码:yezijun666 demo_key_V2.3.zip
6==、安福莱也有自己的按键驱动库 我看了v4开发板的代码,基本上了解了,运用了fifo,类似于Windows下的按键功能,http://www.armbbs.cn/forum.php?mod=forumdisplay&fid=2&filter=typeid&typeid=80 他里面没有使用状态机,而是软件定时器定时(10ms)扫描,具体没有移植测试过。
7==、ButtonDrive:杰杰大佬的作品,一个按键驱动,支持单双击、连按、长按;采用回调处理按键事件(自定义消抖时间),使用只需3步,创建按键,按键事件与回调处理函数链接映射,周期检查按键。 源码地址:https://github.com/jiejieTop/ButtonDrive https://github.com/jiejieTop/ButtonDrive
8==、Btn_State_Machine_Module:一直在做代码模块化的工作,分享一个自己写的按键扫描模块,欢迎大家试用。 本模块计划长期更新,本人能力有限,有错误之处欢迎指正交流,我将根据大家的反馈进行修改优化,提供更可靠的软件模块给大家。
更新说明 2016年6月15日: 本模块目前更新至V1.10,相比于采用switch状态机的V1.00版本,V1.10的状态机采用了状态转移表来实现,在增加状态数量和功能的前提下,不仅提高了执行效率,同时减少了10%的FLASH消耗。 https://gitee.com/ianhom/Btn_State_Machine_Module
9==、DTButton https://gitee.com/harmonyhub/dtbutton Description 实现按键“按下事件”和“释放事件”的通用框架
本仓库是如下教程文章的实例代码
https://harmonyos.51cto.com/posts/1512 https://harmonyos.51cto.com/posts/1607 https://harmonyos.51cto.com/posts/1705
10==、开源键扫例程--- 无须延时消抖等待,能稳定可靠地一体满足普通、短按(单击/双击)、长按、组合等应用需求的键盘扫描程序 http://www.openedv.com/forum.php?mod=viewthread&tid=277263 // 本键盘扫描模块的特点: 一、使用灵活:一体实现按键的普通、单击、双击、长按、保持以及组合等功能,无须事前为每个按键每种键值逐一进行宏定义,也无须逐一编写各事件的条件判断, 只须为需要的按键事件编写相应的响应代码即可,同时留有特殊键组合等的扩展接口; 可以选择每一按键事件的处理实时性,从而能够使强实时性的紧急按键优先得到处理,可自由选择中断处理及查询处理或二者混合的处理方式, 灵活适配使应用项目能够兼备按键的强实时性要求以及超长(主循环执行一遍的时间长达1秒以上的)程序的适应性。
二、注重通用:模块设计时注重通用性,按键事件(键值)依简单易懂的标准事件格式编写;除能满足几乎所有按键应用需求外,在按键数量上, 从少到2-4个按键直到最大32个按键(包括端口直联、行列式矩阵、矩阵加直联混合)都可适用。(注:新写了一个4*4矩阵加4键直联混合共20个键的例子参见153楼)
三、稳定可靠:后台智能抖动消除、按键干扰杂波滤除措施有力,获取按键稳定可靠,不会产生重复按键,即使在CPU非常繁忙时也不会漏失按键。
四、移植简便:所有可调整参数(数量不多)均以宏定义列出,除与硬件相关(按键个数及连接端口)的部分须根据具体系统修改外,其它均无须变化,很容易移植。 程序可读性强,注释详尽丰富,其中包括函数调用关系及详细运用修改说明,如有未尽事宜,可提出探讨,本人尽量解答修改。
五、高效节能:消抖无须延时等待,同时采取自适应变频扫键、键盘闲置检测、消抖读键双进程周期差异等多项智能措施尽量减少占用CPU的计算资源。
//本程序只供学习使用,未经作者许可,不得用于其它任何用途 //测试平台:ALIENTEK战舰STM32开发板 //按键驱动代码 //正点原子@ALIENTEK //引用请注明出处:http://www.openedv.com/forum.php?mod=viewthread&tid=277263,有问题可在本帖中提出讨论,谢谢。 //在网友@学习stm32f4 的建议下,部分源码上传到了https://github.com/ShuifaHe/STM32.git,新司机上路,请多关照。如果觉得对您有用的话,请按 “星” 号点一下赞。 //修改日期:2018/9/1 //版本:V2.2,本帖研讨过程详见2楼,鸣谢相关坛友,感谢@正点原子 的支持肯定。 //Made by warship // 下面给出经由原子试验3改造测试通过的程序范例: 回复后可获取解压密码,谢谢支持。解压密码:warship0901
ATOM_TEST_Key_New.rar
282.83 KB, 下载次数: 8047
(借楼) 本帖更新历程:
(2018年8月15日)受三行键盘扫描程序http://www.openedv.com/forum.php ... hlight=%C8%FD%D0%D0 的启发,使用SYSTICK系统嘀哒消抖,具体尝试了短按、长按、组合等实现方法,贴出源码供网友进行讨论;
(2018年8月18日) 应坛友@wdgao 的要求,将原子的按键实验(实验3)进行改写,分享完整工程,供网友下载测试;
(2018年8月23日) 最新附件优化了消抖代码,并采取了自适应变频扫键措施,在原子战舰开发板上反复测试通过,稳定可靠;
(2018年8月26日) 受到坛友@leiyitan 所提供信息https://github.com/0x1abin/MultiButton的启发,借鉴加入了可选的状态机组件,可以非常方便地实现单击、双击、 长按、保持等功能;
(2018年8月27日) 将读键变成后台队列处理,确保最大限度地容忍主循环长时间才查询一次所带来的影响,CPU非常忙碌时也绝对不丢键。 同时,统筹优化了自适应变频扫键、智能节省CPU算力等措施代码;
(2018年8月29日) 调整程序结构,使强实时性的紧急按键可优先得到处理,从而兼具按键的强实时性要求以及适应超长(主循环执行一遍的时间长达1秒以上的)程序。 弱化三行功能,采用带参宏一次性定义了几乎所有的按键宏值,使得移植者无须为各类按键定义大量宏值,直接处理标准化格式的按键事件即可。 和网友@xiatianyun探讨后进一步加固了消抖代码,最大限度地确保按键的稳定读取;
(2018年8月30日) 代码进行了一些小的调整,进一步增强通用性、可读性及可移植性。定版本为2.2;
(2018年9月1日) 增加了大量注释,其中包括详细的运用、移植修改方法;
(2018年9月2日) 新写了一个4*4矩阵加4键直联混合共20个键的例子(放在153楼/154楼),供使用行列式矩阵等复杂键盘开发者参考;
***********************************************************************************************************************0901X317 支持连续按与不支持连续按的区别:
支持连续按:按下不松开则认为是连续有效。具体过程:就是检测相应按键,只要是在键按下的状态,就执行相应的操作,持续按下则持续不断地(多次)执行用户相应的操作。
不支持连续按:按下不松开则认为是一次有效的。具体过程:就是检测相应按键,只有按键在松开后才被认为是一次有效按键,每次按键只执行一次用户相应的操作。
本按键扫描程序可轻松支持这两种模式。
我们一般的程序需求常常是后者,即每次按键只执行一次用户相应的操作。 而这种所谓不支持连续按(按键一次只执行一次操作)实际上又可以有两种实现方式: 一种是只要按下就执行操作(反正一般按键你总是要松开的,我先执行了再说,这种表现出来的就是响应速度快,用户体验好) 另外一种处理方式就是严格等按键释放后才被认为是一次按键,也就是说你按下键时是没有反应的,等你松开按键后才执行动作。显然用户的体验是反应速度慢。 这两种模式本键盘扫描程序都支持。 事实上等待按键释放后才被认为是一次按键还可以派生出一种按键,那就是长按,只有按下不松开超出指定时间(如2秒以上)就被认为是一次长按事件成立。 长按成立后又引申出两种模式:即长按超过指定时间后还不释放,是执行一次操作还是只要再不放就连续执行操作。而连续执行操作又可分为是真正连续操作还是每间隔一个短时间才执行一次操作(最后这种比较典型的应用就是大家熟悉的电子表调整时间的按键,比如“+”键,按下不放超过时间后变成连续增加,而这个连续增加实际是间隔比如100ms增加一次的,如果真正无间隔地连续你就来不及看清楚和反应了) 所有这些本键盘扫描程序都可轻松支持。
但从上面的描述可知,用户对按键的具体要求是千差万别的,我不可能把所有这些都罗列在例程里(并且不同需求之间还存在相互冲突),大家根据具体应用需求进行按键规划后,只须修改Get_Key()函数相应的判断条件就可以了。