改键位不用翻文档,QMK 固件里只需要动一个 C 文件
【免费下载链接】qmk_firmwareOpen-source keyboard firmware for Atmel AVR and Arm USB families项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmware
QMK 固件是给 Atmel AVR 和 ARM 芯片写的开源键盘固件,仓库里自带 Planck 等上百把键盘的完整实现。想改键位、加灯光、写宏,起点都是keymaps/目录下同一个结构——一个描述按键的 C 文件。本文以仓库自带的 planck 键盘为例,带你从零烧录到自定义。
第一次烧录:三行命令跑通
没接触过 QMK 的人最容易卡在环境上,其实最短路径就四步:
- 克隆仓库:
git clone https://gitcode.com/GitHub_Trending/qm/qmk_firmware - 进入目录执行
qmk setup,自动装对应芯片的工具链 - 编译:
make planck:default - 烧录:
make planck:default:flash(键盘需先进入 DFU 模式,多数键盘是短接 RST-GND 或按板载复位键)
这三行命令完成"拉代码、装环境、编译加烧录"的全部动作:
git clone https://gitcode.com/GitHub_Trending/qm/qmk_firmware cd qmk_firmware && qmk setup make planck:default:flash跑通后终端会打印固件大小(planck 的 ATmega32U4 有 32KB flash,默认配置约占 60%),然后系统会"噔"一声断开重连——键盘已经用上新固件了,按一下任意键试试。
一个原理讲透:矩阵扫描就是轮流敲门
你不需要看懂整块 PCB 才能改键位,但花两分钟理解矩阵扫描,之后改keymap.c时就不会改出"错位一行"这种低级错误。
每颗机械轴其实是开关,接在一条行线和一条列线的交叉点上。芯片只有 14 个 GPIO 可用的时候,如果每根线都独立读,61 个轴要 61 个引脚;用矩阵,5 行 12 列就只需要 17 根线。
扫描逻辑说白了就是"轮流敲门问每间屋子有没有人":先把第 1 行拉低,读全部列,看哪几列被拽下来了——那就是这一行被按住的键;再换第 2 行重复。一个完整循环几十微秒,你完全感觉不到。
这段伪代码就是 quantum/matrix.c 里matrix_scan()干的事:
// 一次完整的矩阵扫描 for (row = 0; row < MATRIX_ROWS; row++) { row_output(row, false); // 拉低当前行 for (col = 0; col < MATRIX_COLS; col++) { register_km(col, read(col)); // 读列电平,记录交叉点 } row_output(row, true); // 恢复该行 }改完键位重新编译后你会看到:按物理位置没变,但打出来的字符完全是你新排的那套——因为芯片只是把"第 3 行第 7 列被按了"照新表翻译成别的键码。
理解了这个,下面的每个场景都只是"填表"。
场景一:把键位改成你习惯的样子
你要干什么:把 QWERTY 的 F 键挪走,把 Tab 和 Esc 对调。
改哪个文件:keyboards/planck/keymaps/default/keymap.c,找到keymaps大数组里[_QWERTY]那一段。每个位置对应矩阵里的一个交叉点,从左到右、从上到下填:
[_QWERTY] = LAYOUT_planck_grid( KC_TAB, KC_Q, KC_W, KC_E, /* ... 省略一行 */ KC_BSPC, KC_ESC, KC_A, /* ... 省略一行 */ KC_QUOT, /* ... 省略两行 */ BACKLIT, KC_LCTL, /* ... 省略一行 */ KC_RGHT ),改完效果:重新执行make planck:default:flash,约 10 秒后按键即按新布局工作。
常见走错的一步:这个文件里_QWERTY下面还排着_COLEMAK、_DVORAK好几层,别手滑改到别的层去了;另外别按物理位置数格子,要按LAYOUT_planck_grid里逗号的分隔来数,空格键在表里占了两格。
场景二就不只是换字符了,而是给键盘加一整套隐藏的"第二套键"。
场景二:加一个按住的 Fn 功能层
你要干什么:按住某个键再按别的键,临时切到 F1-F12 层——Planck 默认布局里空格左边就是干这个的。
改哪个文件:还是keymap.c。层的入口就是几行宏定义,MO(_LOWER)的意思是"按住时进入 _LOWER 层,松开立即回来":
enum planck_layers { _QWERTY, _COLEMAK, _DVORAK, _LOWER, _RAISE, _ADJUST }; #define LOWER MO(_LOWER)然后在[_LOWER]那一段表格里把KC_1换成KC_F1就行,一共 32 个层位随便挑。
改完效果:按住 LOWER 键再按数字行,打出来是 F1-F12;松开 LOWER,一切恢复原样。
常见走错的一步:把MO写成TG。TG(_LOWER)是"按一下切过去、再按一下切回来"的开关式,写错之后你会困惑"为什么我按数字行出来的是 F 键,我明明没按住任何东西"。
场景三:把声音、RGB 等开关打开
你要干什么:加按键音或 WS2812 灯带。这类功能不是改代码,是改开关。
改哪个文件:keymap 目录下的keymap.mk(没有就新建一个)。常用开关一览:
| 变量 | 设为yes的效果 | 代价 |
|---|---|---|
AUDIO_ENABLE | 按键发声,可自定义音色 | 占用一个 GPIO |
RGBLIGHT_ENABLE | 24bit RGB 灯效 | 约 2-3KB flash |
MOUSEKEY_ENABLE | 键盘当鼠标用 | 约 1KB flash |
CONSOLE_ENABLE | 用 USB HID 看调试打印 | 调试时再开 |
改完效果:重新编译后终端会显示固件体积变化,比如从 18.2KB 涨到 21.7KB——32KB 的 flash 里还有富余,放心开。
常见走错的一步:开关写了keymap.mk却没接灯。RGBLIGHT_PIN要定义在键盘的 config.h 里,两个文件各管一半,缺一边功能就静默失效。
烧录和引脚问题,多数翻车点其实都能预判。
踩坑速查表
| 你看到的现象 | 大概率原因 | 一行修复 |
|---|---|---|
| 烧录后键盘完全不认 | 没进 bootloader 就烧了 | 短接 RST-GND 一次,等系统识别新设备再 flash |
| 编译报键盘或 keymap 找不到 | 路径大小写拼错 | 到keyboards/下核对目录名,qmk list-keyboards可查 |
| 按键整体错一行 | keymap.c里行列顺序和矩阵不符 | 对照键盘config.h的MATRIX_ROWS/COLS和实际接线重排 |
| 报 flash 空间不足 | 调试打印没关 | keymap.mk里加NO_DEBUG或CONSOLE_ENABLE = no |
| 自定义键码按了没反应 | 用了旧前缀QK_ | 全量替换成KC_,如QK_A改KC_A |
如果你的键盘是 ARM 芯片,遇到"引脚定义"问题就翻这张图对照——每个脚除了名字还有功能编号,改config.h时按编号写才不会接到没电的脚上。
下一步去哪
- 层系统全貌:MO/TG/LF 的区别和 32 层的叠加规则
- keymap.c 的写法规范与 LAYOUT 宏
- 不同 bootloader 的烧录方式对照(DFU、Teensy、QMK 等)
写在最后
回到开头那个场景:用默认键位三周之后开始怀疑人生,现在你手里有一个 10 秒生效的改键流程。打开keymap.c,先把最碍手的那一个键挪了位置——改一个键和改整个布局用的是同一套方法,熟练之后后者也就是填表的事。
【免费下载链接】qmk_firmwareOpen-source keyboard firmware for Atmel AVR and Arm USB families项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmware
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考