找回密码
 立即注册
查看: 955|回复: 6

蓝桥杯问题解决指南(非堵塞式按键防抖和多按键状态识别)

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:458
  • 最近打卡:2025-05-01 07:48:22
已绑定手机
已实名认证

110

主题

2219

回帖

5452

积分

版主

积分
5452
发表于 2024-3-14 11:34:29 | 显示全部楼层 |阅读模式
按键防抖,一直以来都是个非常重要的优化,除却硬件上并联电容的防抖。更加常见的则是软件上的防抖。
通常来说,软件防抖一般使用一个延时函数来实现,但是如果使用简单暴力的计算堵塞延时。就会导致系统的实时响应性不好,甚至会因为按键的延时意外中断一些高实时性的数据交互操作,例如串口数据的响应、传感器数据的读取。严重时,甚至会因为干扰了其他通讯时序,从而读出错误的数据,进而导致系统出现致命性的异常。
所以,在进行按键延时防抖的时候,一般会采用定时器的非堵塞式防抖。从而达到不影响系统的高实时性。
截图202403141131551175.jpg
通过对常见的微动开关进行示波器波形测试,可以看到,电平的变化并非常简单的高低电平变化,而是出现了连续的震荡才逐渐变得稳定(这通常是因为导线和单片机内的电容形成了一个小的RC震荡),因为现在的单片机运行速度普遍较高,这些震荡的信号就很有可能被单片机读取到,进而产生误动作。
截图202403141132171488.jpg
关于矩阵键盘识别,这里我提供两个思路,一个是使用行列式扫描,即先将行IO拉到低电平,此时如果没有按下按键,读列IO应该全是高电平,如果出现了低电平,就证明按键是被按下了。此时需要设定一个延时(5~10ms,推荐5ms,根据开关类型试一下,按键大,震动毛刺多的就延时长一点。按键小,响声清脆的就延时小一点),然后再次判断是否有按下动作,如果仍然存在。就证明这是一次真实有效的按下动作,此时就可以先存下列IO的电平状态,然后将列IO拉到低电平,读行IO,并且同样存下电平状态,将两个电平状态拼接起来,就获得了一个按键的唯一状态编码。此时,通过查询编码就可以知道当前按下的按键。如果没有查到,就说明是一次多按键触发,可以不予处理。这个方法好处是便于理解,但是没法处理多按键按下的情况,或者说处理多按键按下所需要的编码表数量过多。
截图202403141132348274.jpg
而第二种方法则是一种优化过的单按键扫描方式,不仅可以处理多个按键同时按下的情况,还可以通过新的架构识别出来单击、双击、长按三种状态,从而实现各种新的组合。

但是,由于矩阵键盘的结构问题,如果出现一个按键周围三个连续按键的按下就会导致错误的识别到这个按键的按下,如下图所示
截图202403141132509053.jpg
在这个图中, S7按键会因为S11、S10、S6的按下而造成误识别。所以,这种单按键扫描方式我设定仅允许识别至多两个和部分三个按键的情况,如果识别到有四个及以上的按键(如果识别到四个实际可能是三个,主要是为了避免这个问题),就直接放弃本次识别。
而这种单按键扫描方法,运用的其实就是单点扫描点阵屏的一种方法,既然程序可以对点阵屏幕进行单个灯的扫描,用以减少功耗和控制灵活度,算是一种将显示颗粒度细化的方案。而我的这种单按键扫描方式同样是对于单个按键使用逐个判断的方式,先将第一行的IO拉低,判断是否有其他拉低引脚(按下),然后再将第一列的IO拉低,判断是否有其他拉低引脚。以此类推,如果两次都检测到了拉低,说明当前行列对应的这个按键就被按下了,然后就可以对当前这个按键进行按下计时,超过20ms就算做一次按下稳定,此时如果抬起了,就设定为单击,如果等待200ms之内没有再次按下,则设定为空状态。如果按下了,并且又持续了20ms,则算作一次双击状态,如果第一次按下没有松开,一直持续了700ms,则算作一次长按。所有的状态在逻辑线程里面使用过后都会回到空状态,如果没有回到空状态。则认为需要保留当前状态到逻辑线程内,就暂时不进行这个按键的状态检测了。等待逻辑线程使用过后再进行识别操作。
当然,如果比赛的时候一般来说是不会要求这种多按键重叠状态检测的。此时如果需要追求速度,可以使用第一种思路
如果需要识别重叠按键,可以使用第二种思路的前半部分,作为第一种思路的变体。不过需要注意的是,如果检测到了四个按键的情况(如上图状况的就是按下三个蓝色电路的按键就能检测到四个按键按下),那么就有可能是硬件的“鬼影”,需要在程序中剔除掉。

如果需要独立按键识别状态,可以参考第二种思路的后半部分。

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:435
  • 最近打卡:2025-04-30 08:43:23

33

主题

2351

回帖

4860

积分

论坛元老

积分
4860
发表于 2024-3-16 16:19:25 | 显示全部楼层
一说按键扫描,,我记得论坛还有种不使用定时器的,,,大道至简啥啥来着的 一种软定时按键扫描,,用到这里试一试呗,,比较比较

点评

那个好用的,我试过。 这个只是简述一下常规的按键扫描和识别单击双击长按的思路。 这个我连代码都没贴,算是科普  详情 回复 发表于 2024-3-16 16:40
参考例程并不是对技术参 考手册的补充,而是对技术参 考手册的解释。
技术参 考手册不应该需要参考例程作为补充,而是解释成了参考例程的样子
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:458
  • 最近打卡:2025-05-01 07:48:22
已绑定手机
已实名认证

110

主题

2219

回帖

5452

积分

版主

积分
5452
发表于 2024-3-16 16:40:44 | 显示全部楼层
_奶*** 发表于 2024-3-16 16:19
一说按键扫描,,我记得论坛还有种不使用定时器的,,,大道至简啥啥来着的 一种软定时按键扫描,,用到这 ...

那个好用的,我试过。
这个只是简述一下常规的按键扫描和识别单击双击长按的思路。
这个我连代码都没贴,算是科普
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:435
  • 最近打卡:2025-04-30 08:43:23

33

主题

2351

回帖

4860

积分

论坛元老

积分
4860
发表于 2024-3-16 17:33:34 | 显示全部楼层
王*** 发表于 2024-3-16 16:40
那个好用的,我试过。
这个只是简述一下常规的按键扫描和识别单击双击长按的思路。
这个我连代码都没贴, ...

可以可以 他那个双击组合键之类的都好实现么,,只要都能正确识别就可以 还省了个定时器

点评

单击长按可以,双击没试过 组合的话,按键不冲突应该是可以的  详情 回复 发表于 2024-3-16 17:43
参考例程并不是对技术参 考手册的补充,而是对技术参 考手册的解释。
技术参 考手册不应该需要参考例程作为补充,而是解释成了参考例程的样子
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:458
  • 最近打卡:2025-05-01 07:48:22
已绑定手机
已实名认证

110

主题

2219

回帖

5452

积分

版主

积分
5452
发表于 2024-3-16 17:43:42 | 显示全部楼层
_奶*** 发表于 2024-3-16 17:33
可以可以 他那个双击组合键之类的都好实现么,,只要都能正确识别就可以 还省了个定时器 ...

单击长按可以,双击没试过
组合的话,按键不冲突应该是可以的
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:391
  • 最近打卡:2025-04-30 00:26:42

0

主题

336

回帖

1490

积分

金牌会员

积分
1490
发表于 2024-3-16 18:48:17 | 显示全部楼层
用状态机的方法基本各种按键方式都能实现
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:435
  • 最近打卡:2025-04-30 08:43:23

33

主题

2351

回帖

4860

积分

论坛元老

积分
4860
发表于 2024-3-18 09:25:57 | 显示全部楼层
王*** 发表于 2024-3-16 17:43
单击长按可以,双击没试过
组合的话,按键不冲突应该是可以的

啊 只是单击 长按啊,,功能简单了一点儿,,emmm 也差不多了,,我对那个的预期也就到这里了 可以了
参考例程并不是对技术参 考手册的补充,而是对技术参 考手册的解释。
技术参 考手册不应该需要参考例程作为补充,而是解释成了参考例程的样子
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 04:16 , Processed in 0.112708 second(s), 86 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表