本帖最后由 warship 于 2018-9-18 14:09 编辑
//////////////////////////////////////////////////////////////////////////////////
本键盘扫描模块的特点:
一、
使用灵活:一体实现按键的普通、单击、双击、长按、保持以及组合等功能,无须事前为每个按键每种键值逐一进行宏定义,也无须逐一编写各事件的条件判断,
只须为需要的按键事件编写相应的响应代码即可,同时留有特殊键组合等的扩展接口;
可以选择每一按键事件的处理实时性,从而能够使强实时性的紧急按键优先得到处理,可自由选择中断处理及查询处理或二者混合的处理方式,
灵活适配使应用项目能够兼备按键的强实时性要求以及超长(主循环执行一遍的时间长达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改造测试通过的程序范例:
回复后可获取解压密码,谢谢支持。游客,如果您要查看本帖隐藏内容请
回复
问题在两次取样
具体做法其实就是边沿检测:如果前后两次检测到的按键值相同,则异或值为0,也就是FALSE,此时按键可能处于按下也可能处于没有按下状态。如果前后两次检测到不同的按键值,则异或值不为0,是TRUE,此时按键可能从松开跳变到按下也可能从按下跳变到松开,此时就是检测到了边沿。
检测到边沿后如何知道是按下还是没有按下呢,就是用这个边沿状态&按下状态值或松开状态值,这样就检测到了按下或松开的跳变了。
短按检测就这样可以了,长按下如何检测呢?那就在检测到边沿状态后强制把存储上一次按键值的变量赋值为松开值,也就是让每次检测时都认为上次是松开状态,这样如果处于按下状态时(不处于跳变边沿),每次检测都会检测到边沿状态。
道理简单,但不简单的是代码只有三行作边沿检测,核心就是异或。
至于防抖处理,我个人有更好的措施,利用SysTick滴答定时器改造下就可以了。
设计一个静态的定时结构TimeStruct,里面存储两个变量:一个是计数累计值u32Time_ms,一个是等宽脉冲信号bPlus。
SysTick每次中断除了让u32Time_ms--外,让bPlus=!bPlus,这样,bPlus就是周期为2倍SysTick周期的信号了。利用这个bPlus的边沿作为其他定时器的计数时钟。
我这里的“其他定时器”不是系统定时器,而是自定义的各个计数器。
说到这里大家可能明白我怎么做了。就是检测bPlus边沿,这样就产生了边沿信号,用计计数器来累计边沿信号,这样计数器值就是开始定时到此时的时间了。
利用这个可以生成多个计数器,也就是可以有多个独立定时器,互不干扰。
这样防抖利用这个定时计数器,不用等待,每次描述到时检测定时时间是否到达即可。但要保证定时计数器能够被及时执行到,也就是while(1)执行时间不要超过一个SysTick周期即可,这个在定时要求不高的防抖处理中应该能够做到。
也可以在SysTick中断中来累计自定义定时器的计数值,不过这样需要每增加一个定时器就修改一次中断程序,比较啰嗦,删除定时器也需要同步删除中断里面的相应程序。
u32Time_ms的作用和教程一样处理,用于delay_ms()。
一周热门 更多>