中科蓝讯按键UI多击+长按


前言

中科蓝汛的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有需要更改的地方,可以自己根据实际需求修改。

### 中科蓝讯芯片按键IO口映射配置方法 对于中科蓝讯芯片上的按键IO口映射,通常涉及通过特定寄存器来设定哪些引脚作为按键输入。根据提供的资料,在BT8918D设备中有关于ADKEY按键模块的描述[^3]。 在该设备里,为了获取已配置的第一组ADKEY按键定义,会调用`get_adkey_configure()`函数并传入参数`num`表示要查询的具体按键编号: ```c ptr = get_adkey_configure(num); if (ptr != NULL) { if ((num > 11) || (adkey_table[num].adc_val == 0xff)) { return NO_KEY; } return key_config_table[*(ptr+num)]; } ``` 这段代码展示了如何读取预先存储好的按键配置表,并返回相应的键值给应用程序处理逻辑。然而这并不是直接针对IO口映射的操作而是用于解析已经完成映射后的按键事件。 对于实际的IO口映射操作,则一般会在初始化阶段由开发者依据硬件设计需求指定具体的GPIO功能分配。虽然上述片段未提供详细的IO映射过程,但在实践中,这类设置往往涉及到修改特定外设控制寄存器中的相应位域以激活所需的功能模式(比如将某个通用I/O线路切换成ADC通道),从而实现物理连接至按钮开关等外部组件与内部信号路径之间的关联。 至于更详尽的关于中科蓝讯系列产品的具体IO映射指南,建议查阅官方文档或数据手册获得最权威的信息源。这些资源能够给出精确到每一位寄存器字段含义及其影响范围的内容,确保开发人员可以按照既定规格正确无误地完成必要的配置工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值