优化该按键驱动的状态机
增加长按连续触发功能
github.com/L231/ry_key
后台回复开源获取全路径资料
概述
当前版本解决了组合键与独立按键的事件冲突问题,新增长按连续触发功能。
与旧版本的结构差异,4个状态精简为2个状态:
新的状态机
两个状态
新增长按连续触发模式
状态机的代码实现
uint8_t ry_key_state_machine(ry_key_t *key)
{
__key_level_scan(key);
/* 计时大于超长按阈值,就不要累加时间了 */
if(key->scan.tick <= __KEY_LONG_LONG_LIMIT)
key->scan.tick++;
switch(key->status)
{
case KEY_DOWN_STATUS :
/* 弹起事件 */
if(key->scan.level != key->scan.valid_level)
{
__key_event_mark(key, KEY_UP_EVENT);
key->status = KEY_UP_STATUS;
/* 记录连击次数 */
if(key->scan.tick < __KEY_DOUBLE_CLICK_LIMIT)
key->scan.click_cnt++;
}
/* 时基 >= 长按连续触发的阈值 */
else if(key->scan.tick >= __KEY_LONG_PRESS_KEEP_TRIGGER_LIMIT)
{
/* 连续触发 */
if(key->long_press_keep_trigger)
{
__key_event_mark(key, KEY_DOWN_EVENT);
/* 时基清零,保证周期性触发 */
key->scan.tick = 0;
}
/* 长按事件 */
else if(key->scan.tick == __KEY_LONG_LIMIT)
__key_event_mark(key, KEY_LONG_PRESS_EVENT);
/* 超长按事件 */
else if(key->scan.tick == __KEY_LONG_LONG_LIMIT)
__key_event_mark(key, KEY_LONG_LONG_PRESS_EVENT);
/* 长按,则连击事件应该消除 */
key->scan.click_cnt = 0;
}
break;
case KEY_UP_STATUS :
/* 按下事件 */
if(key->scan.level == key->scan.valid_level)
{
/* 先清零,表明是非连续触发的按下事件 */
key->scan.tick = 0;
__key_event_mark(key, KEY_DOWN_EVENT);
key->status = KEY_DOWN_STATUS;
}
/* 从按键按下开始计时,若时间超过连击时间阈值,则认为连击结束 */
else if(key->scan.tick > __KEY_DOUBLE_CLICK_LIMIT && key->scan.click_cnt > 0)
{
if(1 == key->scan.click_cnt)
__key_event_mark(key, KEY_SINGLE_CLICK_EVENT);
else if(2 == key->scan.click_cnt)
__key_event_mark(key, KEY_DOUBLE_CLICK_EVENT);
else if(3 == key->scan.click_cnt)
__key_event_mark(key, KEY_THREE_CLICK_EVENT);
key->scan.click_cnt = 0;
}
break;
default :
key->status = KEY_UP_STATUS;
break;
}
__key_down_mark(key);
return key->event;
}
创建按键、扫描任务
场景说明:
一个电源按键,注册长按事件
一个功能按键,注册按压、连击事件
组合键为“电源键” + “功能键”
void drv_key_create(void)
{
__KEY_REG(KEY_POWER, KEY_LONG_PRESS_NO_KEEP_TRIG);
__KEY_REG(KEY_CTRL, KEY_LONG_PRESS_KEEP_TRIG);
__KEY_COMPOUND_REG(KEY_COMPOUND1);
__KEY_COMPOUND_INSERT_SN(KEY_COMPOUND1, KEY_POWER);
__KEY_COMPOUND_INSERT_SN(KEY_COMPOUND1, KEY_CTRL);
/* 注册独立key事件 */
drv_set_key_event_handler(KEY_CTRL, KEY_DOWN_EVENT, __key_ctrl_down_callback);
drv_set_key_event_handler(KEY_CTRL, KEY_SINGLE_CLICK_EVENT, __key_ctrl_1_click_callback);
drv_set_key_event_handler(KEY_CTRL, KEY_DOUBLE_CLICK_EVENT, __key_ctrl_2_click_callback);
drv_set_key_event_handler(KEY_CTRL, KEY_THREE_CLICK_EVENT, __key_ctrl_3_click_callback);
drv_set_key_event_handler(KEY_POWER, KEY_LONG_PRESS_EVENT, __key_power_long_press_callback);
drv_set_key_event_handler(KEY_POWER, KEY_LONG_LONG_PRESS_EVENT, __key_power_long_long_press_callback);
/* 注册组合键的事件 */
drv_set_key_compound_event_handler(KEY_COMPOUND1, __key_compound_callback);
/* 注册一个key扫描任务 */
ry_task_reg(&__taskKey, /* 任务控制块 */
ry_key_scan, /* 任务主体 */
RY_TASK_MODE_NORMAL, /* 普通模式,周期性运行即可 */
RY_TASK_READY, /* 就绪态 */
"key", /* 任务名字 */
KEY_SCAN_CYCLE); /* 定时周期 */
}
验证效果
功能键连击如下:
组合键、长按连续触发的效果如下:
-END-