前言
中科蓝汛的SDK中按键的处理是封装的,所以处理多击+长按等一些复杂的按键UI的时候需要对按键重新写一个函数进行处理,或者有一些UI也能用一些其它的方法,有其它的好方法也欢迎进行交流,这里用565xa做一个重写后的三击+长按的演示,重写按键驱动基本市场上需要的按键UI基本都可以实现 。
中科蓝讯三击+长按
注释掉该行,然后我们重新写一个按键处理的函数。
在bsp_key.c中添加该函数、结构体和枚举类。(只有一个按键的处理,多个按键还需要更改) 状态图就不贴出来了
typedef enum {
KEY_STATE_NOTHING, // 按键无状态
KEY_STATE_PRESS, // 按键按下
KEY_STATE_LONG, // 按键长按
KEY_STATE_HOLD, // 按键长按保持
KEY_STATE_UP, // 按键抬起
KEY_STATE_DELY, // 按键抬起后多击延迟
}KEY_STATE_T;
typedef struct {
u16 key_up;
u16 key_cnt;
u16 key_val1;
u16 delay_cnt;
u8 press_cnt;
KEY_STATE_T KEY_STATE;
}adc_cb_t1;
adc_cb_t1 adc_cb1;
AT(.com_text.bsp.key)
static u16 key_deal(u8 key_val) {
u16 key_return = NO_KEY;
if (key_val != NO_KEY)
adc_cb1.key_val1 = key_val;
switch(adc_cb1.KEY_STATE) {
case KEY_STATE_NOTHING:
case KEY_STATE_UP:
if (key_val == NO_KEY) {
adc_cb1.key_cnt = 0; // 按下计时
adc_cb1.key_up = 0; // 抬起计时
adc_cb1.press_cnt = 0; // 按下次数
} else {
// 按下消抖
adc_cb1.key_cnt++;
adc_cb1.key_up = 0;
if (adc_cb1.key_cnt >= KEY_SCAN_TIMES) {
// 输出按下事件
key_return = adc_cb1.key_val1 | KEY_SHORT;
adc_cb1.KEY_STATE = KEY_STATE_PRESS;
}
}
break;
case KEY_STATE_PRESS:
if (key_val == NO_KEY) {
if (adc_cb1.key_up < KEY_UP_TIMES) {
// 抬起消抖
adc_cb1.key_up++;
adc_cb1.key_cnt = 0;
} else {
// printf("KEY_STATE_PRESS\n");
adc_cb1.key_up = 0;
adc_cb1.press_cnt += 1;
adc_cb1.KEY_STATE = KEY_STATE_DELY;
}
} else {
adc_cb1.key_cnt++;
adc_cb1.key_up = 0;
if (adc_cb1.key_cnt >= KEY_LONG_TIMES) {
// 输出长按事件
// printf("KEY_STATE_LONG\n");
key_return = adc_cb1.key_val1 | KEY_LONG;
adc_cb1.KEY_STATE = KEY_STATE_LONG;
// 无多击+长按,长按对多击次数重置
#if MULTI_LONG_PRESS_THINGS
adc_cb1.press_cnt = 0;
#endif // MULTI_LONG_PRESS
}
}
break;
case KEY_STATE_LONG:
if (key_val == NO_KEY) {
if (adc_cb1.key_up < KEY_UP_TIMES) {
// 抬起消抖
adc_cb1.key_up++;
} else {
// 输出长按抬起事件
// printf("KEY_STATE_LONG_UP\n");
if (adc_cb1.press_cnt) {
switch(adc_cb1.press_cnt) {
case 3:
key_return = adc_cb1.key_val1 | KEY_THREE_LONG;
break;
default:
key_return = adc_cb1.key_val1 | KEY_LONG_UP;
break;
}
} else {
key_return = adc_cb1.key_val1 | KEY_LONG_UP;
}
adc_cb1.press_cnt = 0;
adc_cb1.key_cnt = 0;
adc_cb1.KEY_STATE = KEY_STATE_UP;
}
} else {
adc_cb1.key_cnt++;
adc_cb1.key_up = 0;
if (adc_cb1.press_cnt) {
if (adc_cb1.key_cnt >= KEY_LONG_HOLD_TIMES) {
// 恢复长按,以便下次计算保持时长
adc_cb1.key_cnt = KEY_LONG_TIMES;
// 输出长按保持时间
key_return = adc_cb1.key_val1 | KEY_HOLD;
adc_cb1.key_cnt = KEY_LONG_TIMES;
}
}
}
break;
// 延迟等待多击输出时间
case KEY_STATE_DELY:
if (key_val == NO_KEY) {
adc_cb1.delay_cnt++;
adc_cb1.key_cnt = 0;
if (adc_cb1.delay_cnt >= key_cb.delay) {
// printf("adc_cb1.press_cnt = %d \n", adc_cb1.press_cnt);
switch(adc_cb1.press_cnt) {
case 1:
key_return = adc_cb1.key_val1 | KEY_SHORT_UP;
break;
case 2:
key_return = adc_cb1.key_val1 | KEY_DOUBLE;
break;
case 3:
key_return = adc_cb1.key_val1 | KEY_THREE;
break;
case 4:
key_return = adc_cb1.key_val1 | KEY_FOUR;
break;
case 5:
key_return = adc_cb1.key_val1 | KEY_FIVE;
break;
default:
break;
}
adc_cb1.press_cnt = 0;
adc_cb1.delay_cnt = 0;
adc_cb1.KEY_STATE = KEY_STATE_NOTHING;
}
} else {
adc_cb1.key_cnt++;
adc_cb1.delay_cnt = 0;
if (adc_cb1.key_cnt >= KEY_SCAN_TIMES) {
adc_cb1.KEY_STATE = KEY_STATE_PRESS;
}
}
break;
}
return key_return;
}
重写按键的驱动后剩下的部分就比较简单了。
在bsp_key.h中添加三击+长按的宏
#define KEY_THREE_LONG 0x1E00
...
...
...
#define KLTH_PLAY_USER_DEF (KEY_PLAY_PWR_USER_DEF | KEY_THREE_LONG)
#define KLTH_PLAY_PWR_USER_DEF (KEY_PLAY_USER_DEF | KEY_THREE_LONG)
在msg_bt.c中添加需要处理的事件
///三击长按按键处理
case KLTH_PLAY_USER_DEF:
case KLTH_PLAY_PWR_USER_DEF:
//if (user_def_key_msg(xcfg_cb.user_def_kd_sel)) {
//}
break;
以上是一个演示,按键根据UI有需要更改的地方,可以自己根据实际需求修改。