You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

键盘驱动开发:Shift键按下可检测但释放无法识别的问题

问题分析与解决方案

你遇到的Shift释放检测失效,主要有两个核心原因,逐个排查即可解决:

1. SC_MAX的取值过滤掉了释放扫描码

键盘的释放扫描码是按下扫描码加上0x80(比如左Shift按下是0x2A,释放就是0x2A+0x80=0xAA),这类码值普遍大于普通按键的按下扫描码。如果你的SC_MAX定义的是普通按键的最大值(比如0x39),那么代码里if (scancode > SC_MAX) return;这一行会直接跳过所有释放扫描码的处理,自然不会触发shift_hold=false的逻辑。

解决方法:把SC_MAX的取值改为0xFF,确保能覆盖所有可能的键盘扫描码(包括普通通码、释放码和扩展码)。

2. 未处理右Shift的释放扫描码

你只处理了左Shift的释放(0xAA),但右Shift的释放扫描码是0xB6(按下是0x36)。如果测试时按的是右Shift,代码根本不会捕获到释放事件。

解决方法:补充右Shift的按下和释放逻辑。

修改后的代码示例

static void keyboard_callback(registers_t *regs) {
    uint8_t scancode = port_byte_in(0x60);
    if (scancode > 0xFF) return; // 替换原SC_MAX判断,直接用0xFF覆盖所有扫描码

    // 处理左Shift按下
    if (scancode == 0x2A) {
        shift_hold = true;
        print_string("Pressed!");
    } 
    // 处理左Shift释放
    else if (scancode == 0xAA) {
        shift_hold = false;
        print_string("Worked!");
    }
    // 处理右Shift按下
    else if (scancode == 0x36) {
        shift_hold = true;
        print_string("Pressed!");
    }
    // 处理右Shift释放
    else if (scancode == 0xB6) {
        shift_hold = false;
        print_string("Worked!");
    }

    // 恢复原有逻辑后即可配合Shift状态实现大写字母
    /*
    if (scancode == BACKSPACE) {
        if (backspace(key_buffer) == true) {
            print_backspace();
        }
    } else if (scancode == ENTER) {
        print_string("\n");
        execute_command(key_buffer);
        key_buffer[0] = '\0';
    } else {
        char letter = shift_hold ? scancode_to_shift[(int)scancode] : scancode_to_char[(int)scancode];
        append(key_buffer, letter);
        char str[2] = {letter, '\0'};
        print_string(str);
    }
    */
}

补充说明:键盘还存在带E0前缀的扩展扫描码,不过基础的Shift功能用上述修改就能实现,后续如果需要处理更多特殊按键再扩展即可。

内容的提问来源于stack exchange,提问作者audiotore

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 12:45:35