页面加载中,请稍候
来源:果果小师弟发布时间:2022-04-12173浏览
询问 AI摘要:本文目的是讲述一个按键扫描处理的面向对象开发的设计思想,适用于裸机开发,通过按键扫描,检测到按键是否按下,松开等状态,并将该状态通过其他形式反馈给其他模块进行处理。初次使用按键时,最常用的办法就是如以下代码一样,硬延时抖动滤波,等待确认后做相应的处理。
void KEY_Scan(void)
{
if(KEY0 == 0)
{
delay_ms(10);//去抖动
if(KEY0 == 0)
{
// 处理想做的事情
}
}
}
以上方式最大的弊端就是硬延时去抖动,极大的浪费了 CPU 资源,对熟悉阻塞式和非阻塞式程序开发的人来说,这种写法是十分不可取的;程序框架稍微好的,会摒弃此种做法,采用分时调度(时间片论法)的形式按时(比如10ms)调用该函数,通过一定累计次数确定按键是否有动作,并处理相关数据。
一、设计需求大致将按键功能模块分为四类文件(一类文件含 .c 和 .h ):
由于按键不能通过软件延时去抖动的方式,则需: 计时器:按键扫描采样时间的计时器,当检测到按键首次按下时,则触发计时器计数,当满足去抖动时间时,则表示按键正常按下。
将按键扫描过程封装起来,则表示需要将过程和数据(操作状态)分离:
在禁止长按模式下的按键从按下到松开一系列动作识别过程如下图(短按有效时间中包含了去抖动时间):

长按模式
在使能长按模式下的按键动作识别过程有两种情况:
1、按下时间没有满足长按时间松开,和禁止长按模式的识别过程一致,如下图(短按有效时间中包含了去抖动时间):

2、按下时间满足了长按时间松开,识别过程如下图(短按有效时间中包含了去抖动时间):
三、示例代码源文件部分代码:
/**
* @brief 获取按键单击次数
*
* @note 调用该函数时不能有关于按键动作的限制条件
* @param[in] eKey 指定按键, 取值为 @reg IoKeyType_e
* @param[in] time 每次单击的间隔时间
* @retval 单击次数.
*/
uint8_t KEY_GetClickCnt(IoKeyType_e eKey, uint16_t time)
{
if (eKey >= IO_KEY_MAX_NUM)
{
return 0;
}
/* 连续单击后等间隔时间再进行回调通知, 目的在松开按键后再次触发得到单击次数 */
if (sg_tKeyManage[eKey].eKeyAction == KEY_ACTION_LOSSEN)
{
sg_tKeyManage[eKey].refreshNotifyTic = time;
}
if (sg_tKeyManage[eKey].eKeyActionBak != KEY_ACTION_PRESS && sg_tKeyManage[eKey].eKeyAction == KEY_ACTION_PRESS)
{
sg_tKeyManage[eKey].refreshNotifyTic = 0;
if (sg_tKeyManage[eKey].clickCnt < 0xFF)
{
sg_tKeyManage[eKey].clickCnt++;
}
}
if (sg_tKeyManage[eKey].eKeyAction == KEY_ACTION_NO_PRESS && sg_tKeyManage[eKey].uiLossenTic >= time)
{
uint8_t cnt = sg_tKeyManage[eKey].clickCnt;
sg_tKeyManage[eKey].clickCnt = 0;
return cnt;
}
return 0;
}
头文件部分代码:
/* Exported types ----------------------------------------------------------------------------------------------------*/四、代码获取
typedef enum
{
KEY_ACTION_NO_PRESS = 0, /*!< 没有按下 */
KEY_ACTION_PRESS, /*!< 持续按下 */
KEY_ACTION_LOSSEN /*!< 按下松开 */
} KeyAction_e;
typedef void (*KeyFunCB)(IoKeyType_e, KeyAction_e);
/* Exported constants ------------------------------------------------------------------------------------------------*/
/* Exported macro ----------------------------------------------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------------------------------------------------*/
extern void KEY_Init(void);
extern void KEY_Register(IoKeyType_e eKey, KeyFunCB pfnKeyFun);
extern void KEY_UnRegister(IoKeyType_e eKey);
extern void KEY_SetNotifyTime(IoKeyType_e eKey, uint16_t time);
extern uint8_t KEY_GetClickCnt(IoKeyType_e eKey, uint16_t time);
extern uint16_t KEY_GetPressTime(IoKeyType_e eKey);
extern uint16_t KEY_GetLossenTime(IoKeyType_e eKey);
extern void KEY_Scan(uint16_t cycleTime);
https://gitee.com/const-zpc/key

新闻来源:果果小师弟,文中所述为作者独立观点,不代表icspec立场。更多精彩资讯请下载icspec App。如对本稿件有异议,请联系微信客服specltkj。
暂无评论哦,快来评论一下吧!
2026-07-06