本帖最后由 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改造测试通过的程序范例:
回复后可获取解压密码,谢谢支持。游客,如果您要查看本帖隐藏内容请
回复
不用再考虑松开,按下,连按,组合等逻辑判断细节,并且不会出现重复按键,代码实现结构清晰,增减按键定义很容易。
不同的按键组合对应不同的键值,只处理键值。
我把我写的延时程序贴出来,给些意见。
[mw_shl_code=c,true]// 延时器,配合SysTick使用。
static struct {
u32 uTimer_ms; // ms延时器,用于查询延时。
bool bPlus_ms; // ms脉冲信号,1msON,1msOFF.
}Timer;
// 脉冲型定时器结构
typedef struct {
u32 uEt; // 定时计数当前值。
bool bTemp; //脉冲暂存信号。
bool bQ; //定时时间到标识。
}TimerType;[/mw_shl_code]
这是两个结构,一个是静态结构变量Timer,是由SysTick中断处理的对象,一个是定时器结构类型TimerType,可以构造多个自定义定时器,这些定时器在程序中需要时定义,并由下面的定时器函数操作。
// 延时接通定时器
// 当bEnb为TRUE时开始定时,定时单位为1ms。
// 当bEnb为FALSE时复位定时器。
// 当定时到达后如果没有复位定时器则定时器当前计数值uEt保持不变。
bool TimeON(bool bEnb, u32 uPt, TimerType *timer);
下面是一key0键检测为例说明如何防抖。
[mw_shl_code=c,true]//key0 扫描程序
//bSusKey==TRUE:连续按下可以扫描到连续多个值。
//bSusKey==FALSE:连续按下只扫描到一个按键值。
bool key0_Scan( bool bSusKey )
{
static bool bsLastKey = FALSE; //按键上次状态。
//经过防抖处理后检测到按键压下。
bool bKey;
//防抖动检测定时器。
static TimerType timer;
//返回值。
bool bRet = FALSE;
assert_param(Is_BOOL(bSusKey));
// 防抖处理。
bKey = TimeON(KEY0_CODE, 150U, &timer); //KEY0_CODE是宏,当读取到硬件有键输入时值为键值,否则是0。防抖时间150ms。
bRet = bKey & (bKey ^ bsLastKey); //沿检测到键按下.
//如果是连续按键模式。
if(bSusKey)
bsLastKey = FALSE; //当是连续模式时,把上次按键状态置为FALSE。
//如果是单按键模式。
else
bsLastKey = bKey;
return bRet;
}[/mw_shl_code]
经过TimeON()的防抖处理,只有连续按下超过150ms才能被检测到键按下,期间有抖动导致KEY0_CODE为0均会复位timer。
定时器的其他用法类似,比如需要延时200ms,可以采用等待延时delay_ms(200),也可以采用如下的方法:
[mw_shl_code=applescript,true]// 定义定时器。
static TimerType Timer1;
while(1)
{
TimeON(bT1_Enb, 200U, &Timer1); //保证能够被循环执行。
if(!Timer1.bQ)
{
...................
}
}[/mw_shl_code]
可否提供一份稳定,简单的按键程序
一周热门 更多>