按键长按和连击检测

[复制链接]
查看628 | 回复8 | 2024-1-13 22:43:53 | 显示全部楼层 |阅读模式
void key_scan_task(uint8_t key_pin) {
    uint32_t timer_cnt = 0, countdown = 0;
    uint32_t click_cnt = 0;// 短按次数
    bool long_press = false;
    // 10ms定时扫描
    #define JITTER_CNT 5 // 抖动时间,大约50ms
    #define LONG_PRESS_CNT 100 // 长按检测时间,长按不参与前后连击检测
    #define COUNTDOWN_INIT 20 // 连击检测倒计时
    bflb_gpio_init(gpio, key_pin, GPIO_INPUT | GPIO_FLOAT | GPIO_SMT_EN | GPIO_DRV_0);
    while(1) {
        if(bflb_gpio_read(gpio, key_pin)) {// 高电平时计数
            if(timer_cnt < 10000000) timer_cnt++;// 避免一直长按时溢出
        }
        else {// 低电平时判断状态
            if(countdown > 0) countdown--;// 倒计时
            if(timer_cnt >= LONG_PRESS_CNT) long_press = true;
            else if(timer_cnt >= JITTER_CNT) {
                click_cnt++;
                countdown = COUNTDOWN_INIT;// 重新倒计时
            }
            // 状态输出
            if(long_press) {// 长按
                printf("long_press:%d\r\n", timer_cnt);
                long_press = false;
                click_cnt = countdown = 0;// 重置,丢弃前面的连击
            }
            else if(click_cnt > 0 && countdown == 0) {// 点击1次或多次
                printf("%d click\r\n", click_cnt);
                click_cnt = 0;
            }
            // else {} // 未按键,抖动,连击检测倒计时未结束
            timer_cnt = 0;// 重置
        }
        vTaskDelay(10);
    }
}

定时扫描GPIO的电平,统计高电平的持续时间,如果超过特定值则为长按,小于特定值为按键抖动,介于两个特定值之间为短按,短按后开启倒计时,在指定时间内再次短按,判断为连击

利用M61-32板子上的烧录键进行测试

xTaskCreate(key_scan_task, "key_scan_task", 1024, GPIO_PIN_2, 16, &key_scan_task_hd);

image.png

回复

使用道具 举报

WT_0213 | 2024-1-13 23:29:34 | 显示全部楼层
回复

使用道具 举报

san | 2024-1-13 23:44:46 | 显示全部楼层
回复

使用道具 举报

1084504793 | 2024-1-14 08:11:58 | 显示全部楼层
回复

使用道具 举报

timo | 2024-1-14 10:15:08 | 显示全部楼层
回复

使用道具 举报

干簧管 | 2024-1-14 20:21:14 | 显示全部楼层
回复

使用道具 举报

曹县 | 2024-1-14 20:52:19 | 显示全部楼层
回复

使用道具 举报

bzhou830 | 2024-1-15 08:54:30 | 显示全部楼层
很棒,学习学习
选择去发光,而不是被照亮
回复 支持 反对

使用道具 举报

爱笑 | 2024-1-15 09:29:19 | 显示全部楼层
用心做好保姆工作
回复

使用道具 举报

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

本版积分规则