给Kinesis Advantage键盘上QMK、Vial固件

背景

我在2016年12月的时候,在闲鱼上买到一块没线的 Kinesis Contoured 键盘,其实我在写这篇文章之前,并没有仔细查过准确型号,我一直以为我买到的是 Kinesis Advantage 之类的,毕竟造型几乎一样,但是从接口和残余键帽的颜色来判断,应该是Kinesis Contoured,这已经是1992年发布的老古董了,不过其实也可以算得上是 Advantage 系列,更像是这个系列改名了,现在都有无线的 Kinesis Advantage 360 了,499美刀,贵到离谱。

在此前的2016年6月,我正开始接触人体工学键盘,并了解到TMK这一类自定义固件(那时候QMK还不是主流?),当时折腾键盘买了乱七八糟的单片机,也尝试做了几块飞线键盘,手上还有一块80块钱买的 Teensy ++ 2.0,有48个IO接口,128KB闪存。

当时对TMK这类固件实在是折腾不明白,做键盘用的固件是 Easy AVR ,相对TMK来说算比较简单。

最后就用 Kinesis Contoured + Teensy ++ 2.0 + EasyAVR 做了这块键盘,还买了膜重新贴了一下表面,后面这把键盘也拿到公司去用了相当长的一段时间。

现在又打算重新折腾新的键盘,了解到 Vial 这种不需要每次改建都重刷的免刷固件,打算尝试一下,刚好 Teensy ++ 2.0 的闪存还够大,先拿这个老伙计练练手。

Kinesis Contoured 键盘正面

硬件信息

基础结构

精减原电路板处理后的 Kinesis Contoured 键盘。保留了外壳、按键及PCB结构、加了点热熔胶修复、重新贴了膜。

Kinesis Contoured 键盘内侧

开发板

Teensy ++ 2.0 开发板

Teensy ++ 2.0 开发板

连线结构

因为保留了原有的PCB,所以是直接飞线接到了PCB上面,使用了PCB原来的布局,所以并不是严格直观的行列划分。

一共使用了 7行 12列

行(Row)端口:D1、D2、D3、D4、D5、D6、D7

列(Col)端口:C1、C2、C3、C4、C5、C6、F1、F2、F3、F4、F5、F6

二极管方向:行到列,Row2Col

键盘矩阵及连线结构

QMK

参考资料:QMK 教程 - docs.qmk.fm

搭建环境

Windows用户折腾QMK,请先安装 QMK MSYS ,默认选项一路下一步就可以了。

本文撰写时,QMK MSYS 版本为 1.11.0,QMK MSYS 安装教程:开始安装 QMK MSYS

安装完成,在开始菜单找到 QMK MSYS,打开后效果如图

QMK MSYS 安装完成

在打开 QMK MSYS 后,运行 qmk setup 命令:

BASH
 1[Xin@DESKTOP-XXXXXXX ~]$ qmk setup
 2
 3☒ Could not find qmk_firmware!
 4Would you like to clone qmk/qmk_firmware to C:/Users/Xin/qmk_firmware? [y/n] y
 5正克隆到 '/c/Users/Xin/qmk_firmware'...
 6正在更新文件:   0% (148/22285)
 7...
 8正在更新文件: 100% (22285/22285), 完成.
 9...
10Ψ Successfully cloned https://github.com/qmk/qmk_firmware to C:/Users/Xin/qmk_firmware!
11Ψ Added https://github.com/qmk/qmk_firmware as remote upstream.
12Ψ QMK Doctor is checking your environment.
13Ψ CLI version: 1.1.8
14Ψ QMK home: C:/Users/Xin/qmk_firmware
15Ψ Detected Windows 10 (10.0.19044).
16Ψ QMK MSYS version: 1.11.0
17Ψ Userspace enabled: False
18Ψ Git branch: master
19Ψ Repo version: 0.29.12
20...
21Ψ Submodule status:
22Ψ - lib/chibios: 2025-05-15 08:25:11 +0000 --  (8bd61b8043)
23Ψ - lib/chibios-contrib: 2025-01-08 21:03:31 +0100 --  (3ac181e4)
24Ψ - lib/googletest: 2021-06-11 06:37:43 -0700 --  (e2239ee6)
25Ψ - lib/lufa: 2022-08-26 12:09:55 +1000 --  (549b97320)
26Ψ - lib/vusb: 2022-06-13 09:18:17 +1000 --  (819dbc1)
27Ψ - lib/printf: 2022-06-29 23:59:58 +0300 --  (c2e3b4e)
28Ψ - lib/pico-sdk: 2025-04-20 21:24:29 +1000 --  (d0c5cac)
29Ψ - lib/lvgl: 2022-04-11 04:44:53 -0600 --  (e19410f8)
30Ψ QMK is ready to go
点击展开查看更多

注意它克隆到的路径,我这里是 C:/Users/Xin/qmk_firmware 这就是我QMK相关的文件夹了,后续产生的文件都基本在这个目录下。

创建新键盘

在 QMK MSYS 中,运行 qmk new-keyboard 命令来创建新键盘,并按提示填写参数,输错了可以直接 Ctrl+C 结束重来。

BASH
1[Xin@DESKTOP-XXXXXXX ~]$ qmk new-keyboard
2Ψ Generating a new QMK keyboard directory
3
4Ψ Name Your Keyboard Project
5Ψ For more information, see:
6https://docs.qmk.fm/hardware_keyboard_guidelines#naming-your-keyboard-project
7Keyboard Name? 
点击展开查看更多

提示输入键盘名,我这里取名叫 kinesis_advantage_teensy_pp2 就是键盘布局+主控型号

BASH
1Keyboard Name? kinesis_advantage_teensy_pp2
2Ψ Attribution
3Ψ Used for maintainer, copyright, etc.
4Your GitHub Username? 
点击展开查看更多

提示输入GitHub名字,我这里输入的是 tjxwork,接着又问你的真实名字,直接回车就会使用上面输入的GitHub名字

BASH
1Your GitHub Username? tjxwork
2Ψ More Attribution
3Ψ Used for maintainer, copyright, etc.
4Your Real Name? [tjxwork]
5Ψ Pick Base Layout
6Ψ As a starting point, one of the common layouts can be used to
7bootstrap the process
点击展开查看更多

接着会问你的键盘配列布局,因为我用的不是人家已经提交上去的方案,所以直接回车选择默认的 65. none of the above “以上都不是”

BASH
 1bootstrap the process
 2Default Layout?
 3        1. 60_abnt2
 4        2. 60_ansi
 5        3. 60_ansi_arrow
 6        4. 60_ansi_wkl
 7        5. 60_hhkb
 8...
 9        61. tkl_iso_wkl
10        62. tkl_jis
11        63. tkl_nofrow_ansi
12        64. tkl_nofrow_iso
13        65. none of the above
14Please enter your choice: [65]
点击展开查看更多

接下来问你没有使用开发板,有y,没有n,虽然我的确有使用开发板,但是QMK里面没有 Teensy ++ 2.0 这张开发板的选项,只能输入n

BASH
1Ψ What Powers Your Project
2Ψ Is your board using a separate development board, such as a Pro Micro,
3or is the microcontroller integrated onto the PCB?
4
5For more information, see:
6https://docs.qmk.fm/compatible_microcontrollers
7Using a Development Board? [y/n] n
点击展开查看更多

输入n,选择没有使用开发板后,会出让你选择微控制器的选项列表,前面已经介绍过 Teensy ++ 2.0 是使用的 AT90USB1286,所以我这里选择对应的 2

BASH
 1Using a Development Board? [y/n] n
 2Ψ Select Microcontroller
 3Ψ For more information, see:
 4https://docs.qmk.fm/compatible_microcontrollers
 5Microcontroller?
 6        1. AT32F415
 7        2. at90usb1286
 8        3. at90usb1287
 9        4. at90usb162
10        5. at90usb646
11        6. at90usb647
12        7. atmega16u2
13        8. atmega16u4
14        9. atmega328
15        10. atmega328p
16        11. atmega32a
17        12. atmega32u2
18        13. atmega32u4
19        14. attiny85
20        15. GD32VF103
21        16. MK20DX128
22        17. MK20DX256
23        18. MK64FX512
24        19. MK66FX1M0
25        20. MKL26Z64
26        21. RP2040
27        22. STM32F042
28        23. STM32F072
29        24. STM32F103
30        25. STM32F303
31        26. STM32F401
32        27. STM32F405
33        28. STM32F407
34        29. STM32F411
35        30. STM32F446
36        31. STM32G0B1
37        32. STM32G431
38        33. STM32G474
39        34. STM32H723
40        35. STM32H733
41        36. STM32L412
42        37. STM32L422
43        38. STM32L432
44        39. STM32L433
45        40. STM32L442
46        41. STM32L443
47        42. WB32F3G71
48        43. WB32FQ95
49Please enter your choice: [13] 2
50Ψ Created a new keyboard called kinesis_advantage_teensy_pp2.
51Ψ Build Command: qmk compile -kb kinesis_advantage_teensy_pp2 -km default.
52Ψ Project Location: C:/Users/Xin/qmk_firmware/keyboards/kinesis_advantage_teensy_pp2.
53Ψ Now update the config files to match the hardware!
点击展开查看更多

好了,到这里基础的创建引导就结束了,QMK会帮忙创建一个包含基础内容的键盘项目,返回的信息告诉我们:

编译固件命令:qmk compile -kb kinesis_advantage_teensy_pp2 -km default
键盘项目路径:C:/Users/Xin/qmk_firmware/keyboards/kinesis_advantage_teensy_pp2

BASH
1Ψ Created a new keyboard called kinesis_advantage_teensy_pp2.
2Ψ Build Command: qmk compile -kb kinesis_advantage_teensy_pp2 -km default.
3Ψ Project Location: C:/Users/Xin/qmk_firmware/keyboards/kinesis_advantage_teensy_pp2.
4Ψ Now update the config files to match the hardware!
点击展开查看更多

键盘映射定义

接下来就要用文本编辑器来编辑,刚刚生成的键盘项目源代码文件了,推荐使用 Visual Studio Code 或者任意你顺手的文本编辑器。

C:/Users/Xin/qmk_firmware/keyboards/kinesis_advantage_teensy_pp2 的文件结构如下:

BASH
1├── keymaps
2│   └── default
3│       └── keymap.c
4├── keyboard.json
5└── readme.md
点击展开查看更多

使用 VSCode 打开 C:/Users/Xin/qmk_firmware/keyboards/kinesis_advantage_teensy_pp2 文件夹的效果如下:

VSCode 编辑 QMK 键盘项目文件夹

主要需要编辑修改的文件是 keyboard.jsonkeymap.c 这两个文件。

我们先来看一下创建键盘向导的生成的 keyboard.json

JSON
 1// QMK创建新键盘项目的向导生成的 keyboard.json
 2{
 3    "manufacturer": "tjxwork",// 制造商署名
 4    "keyboard_name": "kinesis_advantage_teensy_pp2",//键盘名,系统键盘名称
 5    "maintainer": "tjxwork",//制造者名称,影响系统如何称呼该设备
 6    "bootloader": "atmel-dfu",//Bootloader的型号
 7    "diode_direction": "COL2ROW",//矩阵键盘扫描二极管方向,默认是列到行
 8    "features": { //键盘支持的特性
 9        "bootmagic": true, //支持快捷键进入Bootloader模式
10        "extrakey": true,  //支持额外的按键,音量加减和媒体控制键等
11        "mousekey": true, //支持键盘输出鼠标按键信号
12        "nkro": true //支持N-Key Rollover(全键无冲)功能
13    },
14    "matrix_pins": { //定义矩阵键盘的行列分别使用的IO口编号
15        "cols": ["C2", "C2", "C2", "C2"], //使用的列IO
16        "rows": ["D1", "D1", "D1", "D1"]  //使用的行IO
17    },
18    "processor": "at90usb1286", //主控微处理器型号
19    "url": "", //设计者的主页地址
20    "usb": {
21        "device_version": "1.0.0", //设备版本号
22        "pid": "0x0000", //可以理解为设备的型号
23        "vid": "0xFEED"  //可以理解为厂家的编号
24    },
25    "layouts": {
26        "LAYOUT": { //键盘使用的矩阵名称,要和 keymap.c 那边对应,建议保持默认
27            "layout": [ //"layout": []相当于一个数组,你怎么排版不影响,但是要注意,它和 keymap.c 那边的 "[0] = LAYOUT" 的数量和顺序要是对应的。
28                {"matrix": [0, 0], "x": 0, "y": 0}, //每组{}定义每个按键在矩阵的位置,空间坐标和大小
29                {"matrix": [0, 1], "x": 1, "y": 0}, //"matrix": [0, 1], 就是0行,1列,这个矩阵交叉点上有一个按键
30                {"matrix": [0, 2], "x": 2, "y": 0}, //"x": 2, "y": 0,就是这个按钮在逻辑上的大概位置
31                {"matrix": [0, 3], "x": 3, "y": 0}, //还可以定义 "h":2 高度、"w":2 宽度
32                {"matrix": [1, 0], "x": 0, "y": 1}, //至于后面的 x y 之类参数,对于 kinesis advantage 这种非严格直上直下的布局,只有参考作用
33                {"matrix": [1, 1], "x": 1, "y": 1}, //建议按正常思路从上到下,从左到右来填写。
34                {"matrix": [1, 2], "x": 2, "y": 1}, //其实上面的 连线结构 那里就已经提前写好了每个按钮的[行,列]值,直接抄就可以了。
35                {"matrix": [1, 3], "x": 3, "y": 1},
36                {"matrix": [2, 0], "x": 0, "y": 2},
37                {"matrix": [2, 1], "x": 1, "y": 2},
38                {"matrix": [2, 2], "x": 2, "y": 2},
39                {"matrix": [2, 3], "x": 3, "y": 2},
40                {"matrix": [3, 0], "x": 0, "y": 3},
41                {"matrix": [3, 1], "x": 1, "y": 3},
42                {"matrix": [3, 2], "x": 2, "y": 3},
43                {"matrix": [3, 3], "x": 3, "y": 3}
44            ]
45        }
46    }
47}
点击展开查看更多

配合实际的二极管方向、IO接口、键盘矩阵结构对 keyboard.json 进行修改后:

JSON
  1{
  2    "manufacturer": "tjxwork",
  3    "keyboard_name": "kinesis_advantage_teensy_pp2",
  4    "maintainer": "tjxwork",
  5    "bootloader": "atmel-dfu",
  6    "diode_direction": "ROW2COL",
  7    "features": {
  8        "bootmagic": true,
  9        "extrakey": true,
 10        "mousekey": true,
 11        "nkro": true
 12    },
 13    "matrix_pins": {
 14        "cols": ["F1", "F2", "F3", "F4", "F5", "F6", "C1", "C2", "C3", "C4", "C5", "C6"],
 15        "rows": ["D1", "D2", "D3", "D4", "D5", "D6", "D7"]
 16    },
 17    "processor": "at90usb1286",
 18    "url": "",
 19    "usb": {
 20        "device_version": "1.0.0",
 21        "pid": "0x0000",
 22        "vid": "0xFEED"
 23    },
 24    "layouts": {
 25        "LAYOUT": {
 26            "layout": [
 27                {"matrix": [0, 0], "x":  0, "y": 0},
 28                {"matrix": [0, 1], "x":  1, "y": 0},
 29                {"matrix": [0, 2], "x":  2, "y": 0},
 30                {"matrix": [0, 3], "x":  3, "y": 0},
 31                {"matrix": [0, 4], "x":  4, "y": 0},
 32                {"matrix": [0, 5], "x":  5, "y": 0},
 33                {"matrix": [0, 6], "x": 12, "y": 0},
 34                {"matrix": [0, 7], "x": 13, "y": 0},
 35                {"matrix": [0, 8], "x": 14, "y": 0},
 36                {"matrix": [0, 9], "x": 15, "y": 0},
 37                {"matrix": [0,10], "x": 16, "y": 0},
 38                {"matrix": [0,11], "x": 17, "y": 0},
 39
 40                {"matrix": [1, 0], "x":  0, "y": 1},
 41                {"matrix": [1, 1], "x":  1, "y": 1},
 42                {"matrix": [1, 2], "x":  2, "y": 1},
 43                {"matrix": [1, 3], "x":  3, "y": 1},
 44                {"matrix": [1, 4], "x":  4, "y": 1},
 45                {"matrix": [1, 5], "x":  5, "y": 1},
 46                {"matrix": [1, 6], "x": 12, "y": 1},
 47                {"matrix": [1, 7], "x": 13, "y": 1},
 48                {"matrix": [1, 8], "x": 14, "y": 1},
 49                {"matrix": [1, 9], "x": 15, "y": 1},
 50                {"matrix": [1,10], "x": 16, "y": 1},
 51                {"matrix": [1,11], "x": 17, "y": 1},
 52
 53                {"matrix": [2, 0], "x":  0, "y": 2},
 54                {"matrix": [2, 1], "x":  1, "y": 2},
 55                {"matrix": [2, 2], "x":  2, "y": 2},
 56                {"matrix": [2, 3], "x":  3, "y": 2},
 57                {"matrix": [2, 4], "x":  4, "y": 2},
 58                {"matrix": [2, 5], "x":  5, "y": 2},
 59                {"matrix": [2, 6], "x": 12, "y": 2},
 60                {"matrix": [2, 7], "x": 13, "y": 2},
 61                {"matrix": [2, 8], "x": 14, "y": 2},
 62                {"matrix": [2, 9], "x": 15, "y": 2},
 63                {"matrix": [2,10], "x": 16, "y": 2},
 64                {"matrix": [2,11], "x": 17, "y": 2},
 65
 66                {"matrix": [3, 0], "x":  0, "y": 3},
 67                {"matrix": [3, 1], "x":  1, "y": 3},
 68                {"matrix": [3, 2], "x":  2, "y": 3},
 69                {"matrix": [3, 3], "x":  3, "y": 3},
 70                {"matrix": [3, 4], "x":  4, "y": 3},
 71                {"matrix": [3, 5], "x":  5, "y": 3},
 72                {"matrix": [3, 6], "x": 12, "y": 3},
 73                {"matrix": [3, 7], "x": 13, "y": 3},
 74                {"matrix": [3, 8], "x": 14, "y": 3},
 75                {"matrix": [3, 9], "x": 15, "y": 3},
 76                {"matrix": [3,10], "x": 16, "y": 3},
 77                {"matrix": [3,11], "x": 17, "y": 3},
 78
 79                {"matrix": [4, 1], "x":  1, "y": 4},
 80                {"matrix": [4, 2], "x":  2, "y": 4},
 81                {"matrix": [4, 3], "x":  3, "y": 4},
 82                {"matrix": [4, 5], "x":  5, "y": 4},
 83                {"matrix": [4, 6], "x": 12, "y": 4},
 84                {"matrix": [4, 8], "x": 14, "y": 4},
 85                {"matrix": [4, 9], "x": 15, "y": 4},
 86                {"matrix": [4,10], "x": 16, "y": 4},
 87
 88                {"matrix": [5, 5], "x":  7, "y": 5},
 89                {"matrix": [6, 5], "x":  8, "y": 5},
 90                {"matrix": [6, 6], "x":  9, "y": 5},
 91                {"matrix": [5, 8], "x": 10, "y": 5},
 92
 93                {"matrix": [5, 2], "x":  6, "y": 6, "h":2},
 94                {"matrix": [5, 3], "x":  7, "y": 6},
 95                {"matrix": [6, 2], "x":  8, "y": 6},
 96                {"matrix": [6, 8], "x":  9, "y": 6},
 97                {"matrix": [5, 9], "x": 10, "y": 6},
 98                {"matrix": [5,10], "x": 11, "y": 6, "h":2},
 99
100                {"matrix": [6, 1], "x":  8, "y": 7},
101                {"matrix": [6,10], "x":  9, "y": 7}
102            ]
103        }
104    }
105}
点击展开查看更多

接下来要修改 keymap.c,先看一下生成的模板

C
 1// QMK创建新键盘项目的向导生成的 keymap.c
 2
 3// Copyright 2023 QMK
 4// SPDX-License-Identifier: GPL-2.0-or-later
 5
 6#include QMK_KEYBOARD_H
 7
 8const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 9    /*
10     * ┌───┬───┬───┬───┐    //可以看到默认给的一个数字小键盘的布局
11     * │ 7 │ 8 │ 9 │ / │	
12     * ├───┼───┼───┼───┤	
13     * │ 4 │ 5 │ 6 │ * │	
14     * ├───┼───┼───┼───┤	
15     * │ 1 │ 2 │ 3 │ - │
16     * ├───┼───┼───┼───┤
17     * │ 0 │ . │Ent│ + │
18     * └───┴───┴───┴───┘
19     */
20    [0] = LAYOUT( //LAYOUT() 这个名字也是和 keyboard.json 里面的 "LAYOUT": {} 是对应的
21        KC_P7,   KC_P8,   KC_P9,   KC_PSLS, //还要注意这里是和 keyboard.json 里面的 "layout": [] 的键位数量是对应的,都是16个。
22        KC_P4,   KC_P5,   KC_P6,   KC_PAST, //这里它排成了4x4的排版,但是怎么排版都不影响作用的,只看顺序,和 "layout": [] 那边是对应的
23        KC_P1,   KC_P2,   KC_P3,   KC_PMNS, 
24        KC_P0,   KC_PDOT, KC_PENT, KC_PPLS 	
25    )
26        //默认的初始布局只定义了一个基础层,0层,就是 [0] = LAYOUT
27        //要更多层布局就复制一份,把前面的数值增加,比如 [1] = LAYOUT,这个就是1层
28        //有多种方法在 0层 里面定义按键用于切换到 1层,比如 MO(1),按下后临时切换到1层
29        //keyboard.json 里面的 "layout": [] 有多少键位数量,这边的每一层就得有多少个按键。
30        //实在不知道用什么,你可以禁用这个键 KC_NO ,也可以使用切换层之前的键 KC_TRNS
31        //具体的按键定义请看QMK文档:https://docs.qmk.fm/#/keycodes
32};
点击展开查看更多

我设想中的键位配列,按下L1,即可切换到红色的1层

设想中的键位配列

根据 keyboard.json 和设想中的键位配列修改keymap.c

C
  1// Copyright 2023 QMK
  2// SPDX-License-Identifier: GPL-2.0-or-later
  3
  4#include QMK_KEYBOARD_H
  5
  6const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  7   /*
  8    * ,--------------------------------------------                         --------------------------------------------.
  9    * |  ESC   |   1  |   2  |   3  |   4  |   5  |                         |   6  |   7  |   8  |   9  |   0  |    -   |
 10    * |--------+------+------+------+------+-------                         +------+------+------+------+------+--------|
 11    * |  TAB   |   Q  |   W  |   E  |   R  |   T  |                         |   Y  |   U  |   I  |   O  |   P  |    [   |
 12    * |--------+------+------+------+------+------|                         |------+------+------+------+------+--------|
 13    * |  Ctrl  |   A  |   S  |   D  |   F  |   G  |                         |   H  |   J  |   K  |   L  |  ;   |    '   |
 14    * |--------+------+------+------+------+------|                         |------+------+------+------+------+--------|
 15    * | LShift |   Z  |   X  |   C  |   V  |   B  |                         |   N  |   M  |   ,  |   .  |   /  | RShift |
 16    * `--------+------+------+------+------+-------                         -------+------+------+------+------+--------'
 17    *          |  L1  | LEFT | RGHT | ALT  |                                       |   =  |   `  |   \  |  L1  |   
 18    *          ----------------------------'                                       `----------------------------
 19    *                                        ,-------------.       ,-------------.
 20    *                                        |  L1  |  DEL |       |  APP |  L1  |
 21    *                                 ,------|------|------|       |------+------+------.
 22    *                                 |      |      | Home |       |  End |      |      |
 23    *                                 | Spac | Back |------|       |------|  Ent | Spac |
 24    *                                 |      |      | LGUI |       | CAPS |      |      |
 25    *                                 `--------------------'       `--------------------'
 26    */
 27    [0] = LAYOUT(
 28    KC_ESC,   KC_1,   KC_2,    KC_3,    KC_4,    KC_5,                KC_6,    KC_7,    KC_8,     KC_9,    KC_0,    KC_MINS, 
 29    KC_TAB,   KC_Q,   KC_W,    KC_E,    KC_R,    KC_T,                KC_Y,    KC_U,    KC_I,     KC_O,    KC_P,    KC_LBRC, 
 30    KC_LCTL,  KC_A,   KC_S,    KC_D,    KC_F,    KC_G,                KC_H,    KC_J,    KC_K,     KC_L,    KC_SCLN, KC_QUOT, 
 31    KC_LSFT,  KC_Z,   KC_X,    KC_C,    KC_V,    KC_B,                KC_N,    KC_M,    KC_COMM,  KC_DOT,  KC_SLSH, KC_RSFT, 
 32              MO(1),  KC_LEFT, KC_RGHT, KC_LALT,                               KC_EQL,  KC_GRV,   KC_BSLS, MO(1), 
 33
 34                                           MO(1),    KC_DEL,       KC_APP,   MO(1),
 35                                 KC_SPC,   KC_BSPC,  KC_HOME,      KC_END,   KC_ENT,   KC_SPC, 
 36                                                     KC_LGUI,      KC_CAPS
 37    ),
 38
 39
 40   /*
 41    * ,--------------------------------------------                         --------------------------------------------.
 42    * |        |  F1  |  F2  |  F3  |  F4  |  F5  |                         |  F6  |  F7  |  F8  |  F9  | F10  |   F11  |
 43    * |--------+------+------+------+------+-------                         +------+------+------+------+------+--------|
 44    * |        | PGUP | HOME |  UP  | END  | PSCR |                         |  P*  |  P7  |  P8  |  P9  |  P/  |    ]   |
 45    * |--------+------+------+------+------+------|                         |------+------+------+------+------+--------|
 46    * |        | PGDN | LEFT | DOWN | RGHT | SLCK |                         |  P+  |  P4  |  P5  |  P6  |  P-  |   F12  |
 47    * |--------+------+------+------+------+------|                         |------+------+------+------+------+--------|
 48    * |        |   `  |  APP |  INS | DEL  | PPLS |                         |  P0  |  P1  |  P2  |  P3  |   \  |        |
 49    * `--------+------+------+------+------+-------                         -------+------+------+------+------+--------'
 50    *          |      |      |      |      |                                       |  P0  |  P.  | PEnt |      |   
 51    *          ----------------------------'                                       `----------------------------
 52    *                                        ,-------------.       ,-------------.
 53    *                                        |  L2  |      |       |      |      |
 54    *                                 ,------|------|------|       |------+------+------.
 55    *                                 |      |      |      |       |      |      |      |
 56    *                                 |      |  Ent |------|       |------| Back |      |
 57    *                                 |      |      |      |       | NLCK |      |      |
 58    *                                 `--------------------'       `--------------------'
 59    */
 60    [1] = LAYOUT(
 61    KC_TRNS, KC_F1,   KC_F2,   KC_F3,   KC_F4,  KC_F5,                KC_F6,    KC_F7,  KC_F8,    KC_F9,   KC_F10,   KC_F11, 
 62    KC_TRNS, KC_PGUP, KC_HOME, KC_UP,   KC_END, KC_PSCR,              KC_PAST,  KC_P7,  KC_P8,    KC_P9,   KC_PSLS,  KC_RBRC, 
 63    KC_TRNS, KC_PGDN, KC_LEFT, KC_DOWN, KC_RGHT,KC_SCRL,              KC_PPLS,  KC_P4,  KC_P5,    KC_P6,   KC_PMNS,  KC_F12, 
 64    KC_TRNS, KC_GRV,  KC_APP,  KC_INS,  KC_DEL, KC_PAUS,              KC_P0,    KC_P1,  KC_P2,    KC_P3,   KC_BSLS,  KC_TRNS, 
 65             KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,                                KC_P0,  KC_PDOT,  KC_PENT, KC_TRNS, 
 66
 67                                           MO(2),    KC_TRNS,      KC_TRNS,  KC_TRNS, 
 68                                 KC_TRNS,  KC_ENT,   KC_TRNS,      KC_TRNS,  KC_BSPC,  KC_TRNS, 
 69                                                     KC_TRNS,      KC_NUM
 70    ),
 71
 72   /*
 73    * ,--------------------------------------------                         --------------------------------------------.
 74    * |        |      |      |      |      |      |                         |      |      |      |      |      |        |
 75    * |--------+------+------+------+------+-------                         +------+------+------+------+------+--------|
 76    * |        |      |      |      |      |      |                         |      |      |      |      |      |        |
 77    * |--------+------+------+------+------+------|                         |------+------+------+------+------+--------|
 78    * |        |      |      |      |      |      |                         |      |      |      |      |      |        |
 79    * |--------+------+------+------+------+------|                         |------+------+------+------+------+--------|
 80    * |        |      |      |      |      |      |                         |      |      |      |      |      |        |
 81    * `--------+------+------+------+------+-------                         -------+------+------+------+------+--------'
 82    *          |      |      |      |      |                                       |      |      |      |      |   
 83    *          ----------------------------'                                       `----------------------------
 84    *                                        ,-------------.       ,-------------.
 85    *                                        |      |      |       |      | BOOT |
 86    *                                 ,------|------|------|       |------+------+------.
 87    *                                 |      |      |      |       |      |      |      |
 88    *                                 |      |      |------|       |------|      |      |
 89    *                                 |      |      |      |       |      |      |      |
 90    *                                 `--------------------'       `--------------------'
 91    */
 92    [2] = LAYOUT(
 93    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,            KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, 
 94    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,            KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, 
 95    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,            KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, 
 96    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,            KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, 
 97             KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,                              KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, 
 98
 99                                            KC_TRNS,  KC_TRNS,    KC_TRNS,  QK_BOOT, 
100                                  KC_TRNS,  KC_TRNS,  KC_TRNS,    KC_TRNS,  KC_TRNS,  KC_TRNS, 
101                                                      KC_TRNS,    KC_TRNS
102    )
103};
点击展开查看更多

编译固件

回到 QMK MSYS 中,输入 qmk compile -kb kinesis_advantage_teensy_pp2 -km default

这个命令在创建新键盘的时候有提示的。编译固件是比较花时间,耐心等待。

BASH
 1[Xin@DESKTOP-XXXXXXX ~]$ qmk compile -kb kinesis_advantage_teensy_pp2 -km default
 2Ψ Compiling keymap with make -r -R -f builddefs/build_keyboard.mk -s KEYBOARD=kinesis_advantage_teensy_pp2 KEYMAP=default KEYBOARD_FILESAF E=kinesis_advantage_teensy_pp2 TARGET=kinesis_advantage_teensy_pp2_default VERBOSE=false COLOR=true SILENT=false QMK_BIN="qmk"
 3
 4avr-gcc.exe (GCC) 15.1.0
 5Copyright (C) 2025 Free Software Foundation, Inc.
 6This is free software; see the source for copying conditions.  There is NO
 7warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 8
 9Compiling: quantum/keymap_introspection.c                                                           [OK]
10...
11Compiling: tmk_core/protocol/lufa/usb_util.c                                                        [OK]
12Linking: .build/kinesis_advantage_teensy_pp2_default.elf                                            [OK]
13Creating load file for flashing: .build/kinesis_advantage_teensy_pp2_default.hex                    [OK]
14Copying kinesis_advantage_teensy_pp2_default.hex to qmk_firmware folder                             [OK]
15Checking file size of kinesis_advantage_teensy_pp2_default.hex                                      [OK]
16 * The firmware size is fine - 15888/122880 (12%, 106992 bytes free)
点击展开查看更多

编译完成后,在 C:/Users/Xin/qmk_firmware/ 下的 .build 文件夹,可以找到格式为 键盘名_default.hex 的文件,这个就是我们要编译完成的固件。

image-20250904170409183

可以看到默认出来的QMK固件体积有44KB,所以才不建议使用闪存只有32KB的32U4,要精简功能才能放得下去。

刷入固件

下载 QMK Toolbox ,打开运行后,

Open 选择上面生成的固件,点右边的下拉选择对应的 AT90USB1286 ,勾选 Auto-Flash

按一下开发板上的 Reset 按钮,或者用之前键盘上定义过的快捷键进入 bootloader 模式,随后就会自动刷入固件。

QMK Toolbox 刷 QMK 固件

你可以点击 QMK Toolbox 上面 Tools 菜单中的 Key Tester 来测试一下键盘是否正常工作。

QMK Toolbox Key Tester

至此,QMK固件就算制作完成了。

Vial

参考资料:Vial移植指南 - get.vial.today

创建键盘定义 JSON

首先我们要先创建 Vial 要用到的键位分布位置信息,在正常情况下,这些信息最终会以 vial.json 这个文件名出现在键盘项目里面。

访问 keyboard-layout-editor 键盘布局编辑器 ,点击上面的 Preset

keyboard-layout-editor 键盘布局编辑器

里面刚好有 Kinesis Advantage 系列的配列,可以基于这个配列修改,不需要重头开始摆了,点击切换后如图

Kinesis Advantage 系列的配列

删除多余的键,然后在每个按钮的 Properties 中的 Top Legend 属性中,填上键盘矩阵中对应的 行数值,列数值

Kinesis Advantage 配列 Vial信息

这张图是不是有点眼熟,其实就是前面提到的 连线结构 里面的示意图

全部调整完后,点击右上角的 Download ,再点击 Download JSON 下载编辑好的配列文件,把里面内容复制到官方的vial.json模板里面。

JSON
 1// 官方的 vial.json 模板
 2{
 3    "lighting": "none", //键盘的背光方式
 4    "matrix": {
 5        "rows": 0, //输入键盘的行数
 6        "cols": 0  //输入键盘的列数
 7    },
 8    "layouts": {
 9        "labels": //如果您的键盘没有任何变种布局选项,应该删除此行。
10        "keymap": //将上一步中下载的 JSON 的完整内容粘贴到冒号符号之后
11    }
12}
点击展开查看更多

修改后,并添加了keyboard-layout-editor数据的 vial.json 文件内容,注意保存好,后面要用。

JSON
  1{
  2    "lighting": "none",
  3    "matrix": {
  4        "rows": 7,
  5        "cols": 12
  6    },
  7    "layouts": {
  8        "keymap": [
  9            [
 10                {
 11                    "y": 1,
 12                    "x": 2.25,
 13                    "f": 5
 14                },
 15                "0,2",
 16                "0,3",
 17                "0,4",
 18                "0,5",
 19                {
 20                    "x": 5.5
 21                },
 22                "0,6",
 23                "0,7",
 24                "0,8",
 25                "0,9"
 26            ],
 27            [
 28                {
 29                    "y": -0.75,
 30                    "w": 1.25
 31                },
 32                "0,0",
 33                "0,1",
 34                {
 35                    "x": 13.5
 36                },
 37                "0,10",
 38                {
 39                    "w": 1.25
 40                },
 41                "0,11"
 42            ],
 43            [
 44                {
 45                    "y": -0.25,
 46                    "x": 2.25
 47                },
 48                "1,2",
 49                "1,3",
 50                "1,4",
 51                "1,5",
 52                {
 53                    "x": 5.5
 54                },
 55                "1,6",
 56                "1,7",
 57                "1,8",
 58                "1,9"
 59            ],
 60            [
 61                {
 62                    "y": -0.75,
 63                    "w": 1.25
 64                },
 65                "1,0",
 66                "1,1",
 67                {
 68                    "x": 13.5
 69                },
 70                "1,10",
 71                {
 72                    "w": 1.25
 73                },
 74                "1,11"
 75            ],
 76            [
 77                {
 78                    "y": -0.25,
 79                    "x": 2.25
 80                },
 81                "2,2",
 82                "2,3",
 83                "2,4",
 84                "2,5",
 85                {
 86                    "x": 5.5
 87                },
 88                "2,6",
 89                "2,7",
 90                "2,8",
 91                "2,9"
 92            ],
 93            [
 94                {
 95                    "y": -0.75,
 96                    "w": 1.25
 97                },
 98                "2,0",
 99                "2,1",
100                {
101                    "x": 13.5
102                },
103                "2,10",
104                {
105                    "w": 1.25
106                },
107                "2,11"
108            ],
109            [
110                {
111                    "y": -0.25,
112                    "x": 2.25
113                },
114                "3,2",
115                "3,3",
116                "3,4",
117                "3,5",
118                {
119                    "x": 5.5
120                },
121                "3,6",
122                "3,7",
123                "3,8",
124                "3,9"
125            ],
126            [
127                {
128                    "y": -0.75,
129                    "w": 1.25
130                },
131                "3,0",
132                "3,1",
133                {
134                    "x": 13.5
135                },
136                "3,10",
137                {
138                    "w": 1.25
139                },
140                "3,11"
141            ],
142            [
143                {
144                    "y": -0.25,
145                    "x": 2.25
146                },
147                "4,2",
148                "4,3",
149                "4,5",
150                {
151                    "x": 7.5
152                },
153                "4,6",
154                "4,8",
155                "4,9"
156            ],
157            [
158                {
159                    "y": -0.75,
160                    "x": 1.25
161                },
162                "4,1",
163                {
164                    "x": 13.5
165                },
166                "4,10"
167            ],
168            [
169                {
170                    "r": 15,
171                    "rx": 5.25,
172                    "ry": 4,
173                    "y": 0.75,
174                    "x": 2
175                },
176                "5,5",
177                "6,5"
178            ],
179            [
180                {
181                    "x": 1,
182                    "h": 2
183                },
184                "5,2",
185                {
186                    "h": 2
187                },
188                "5,3",
189                "6,2"
190            ],
191            [
192                {
193                    "x": 3
194                },
195                "6,1"
196            ],
197            [
198                {
199                    "r": -15,
200                    "rx": 12.75,
201                    "y": 0.75,
202                    "x": -4
203                },
204                "6,6",
205                "5,8"
206            ],
207            [
208                {
209                    "x": -4
210                },
211                "6,8",
212                {
213                    "h": 2
214                },
215                "5,9",
216                {
217                    "h": 2
218                },
219                "5,10"
220            ],
221            [
222                {
223                    "x": -4
224                },
225                "6,10"
226            ]
227        ]
228    }
229}
点击展开查看更多

下载 Vial 软件 ,运行后,点击 File -> Load dummy JSON 加载上面处理好的 vial.json 文件,加载成功后,应该会显示之前编辑好的布局。

Vial 软件 测试键盘JSON

搭建环境

这里假设你已经装好了 QMK MSYS

先克隆 Vial 的 QMK 分支项目 git clone https://github.com/vial-kb/vial-qmk

BASH
1[Xin@DESKTOP-XXXXXXX ~]$ git clone https://github.com/vial-kb/vial-qmk
2正克隆到 'vial-qmk'...
3remote: Enumerating objects: 584396, done.
4remote: Counting objects: 100% (31879/31879), done.
5remote: Compressing objects: 100% (1439/1439), done.
6remote: Total 584396 (delta 31240), reused 30445 (delta 30440), pack-reused 552517 (from 2)
7接收对象中: 100% (584396/584396), 277.89 MiB | 13.08 MiB/s, 完成.
8处理 delta 中: 100% (306283/306283), 完成.
9正在更新文件: 100% (25186/25186), 完成.
点击展开查看更多

克隆完成后,cd vial-qmk 把目录切到 vial-qmk 下面

BASH
1[Xin@DESKTOP-XXXXXXX ~]$ cd vial-qmk
2[Xin@DESKTOP-XXXXXXX vial-qmk]$
点击展开查看更多

检查环境 qmk doctor

BASH
 1[Xin@DESKTOP-XXXXXXX vial-qmk]$ qmk doctor
 2
 3Ψ QMK Doctor is checking your environment.
 4Ψ CLI version: 1.1.8
 5Ψ QMK home: C:/Users/Xin/vial-qmk
 6Ψ Detected Windows 10 (10.0.19044).
 7Ψ QMK MSYS version: 1.11.0
 8Ψ Userspace enabled: False
 9Ψ Git branch: vial
10⚠ The official repository does not seem to be configured as git remote "upstream".
11Ψ All dependencies are installed.
12Ψ Found arm-none-eabi-gcc version 13.3.0
13Ψ Successfully compiled using arm-none-eabi-gcc
14Ψ Successfully tested arm-none-eabi-binutils using arm-none-eabi-size
15Ψ Found avr-gcc version 15.1.0
16Ψ Successfully compiled using avr-gcc
17Ψ Successfully tested avr-binutils using avr-size
18Ψ Found avrdude version 8.0-2025011
19Ψ Found dfu-programmer version 1.1.0
20Ψ Found dfu-util version 0.11
21Would you like to clone the submodules? [Y/n]
点击展开查看更多

出现提示克隆 submodules 输入 y 回车继续,这个过程会比较久。

BASH
 1Would you like to clone the submodules? [Y/n] y
 2Ψ Submodule status:
 3Ψ - lib/chibios: 2025-05-15 08:25:11 +0000 --  (8bd61b8043)
 4Ψ - lib/chibios-contrib: 2025-01-08 21:03:31 +0100 --  (3ac181e4)
 5Ψ - lib/googletest: 2021-06-11 06:37:43 -0700 --  (e2239ee6)
 6Ψ - lib/lufa: 2022-08-26 12:09:55 +1000 --  (549b97320)
 7Ψ - lib/vusb: 2022-06-13 09:18:17 +1000 --  (819dbc1)
 8Ψ - lib/printf: 2022-06-29 23:59:58 +0300 --  (c2e3b4e)
 9Ψ - lib/pico-sdk: 2025-04-20 21:24:29 +1000 --  (d0c5cac)
10Ψ - lib/lvgl: 2022-04-11 04:44:53 -0600 --  (e19410f8)
11Ψ QMK is ready to go, but minor problems were found
点击展开查看更多

修改新键盘映射

因为在上面已经创建过QMK的键盘项目了,我们可以把上面的QMK键盘项目的文件复制过来使用。

如果没有,请先按照上面的QMK流程创建一个新键盘项目。

C:\Users\Xin\qmk_firmware\keyboards\kinesis_advantage_teensy_pp2 文件夹手动复制到 C:\Users\Xin\vial-qmk\keyboards\ 下面。

或者用命令行复制。

BASH
1[Xin@DESKTOP-XXXXXXX vial-qmk]$ cp -r /c/Users/Xin/qmk_firmware/keyboards/kinesis_advantage_teensy_pp2 /c/Users/Xin/vial-qmk/keyboards
点击展开查看更多

直接复制一份 \kinesis_advantage_teensy_pp2\keymaps\ 下面的 default 文件夹,并且重命名为 vial

BASH
1├── keymaps
2│   └── default
3│   │   └── keymap.c
4│   └── vial
5│       └── keymap.c
6├── keyboard.json
7└── readme.md
点击展开查看更多

把上面 创建键盘定义JSON 得到的 vial.json 文件复制到 vial 文件下

BASH
1├── keymaps
2│   └── default
3│   │   └── keymap.c
4│   └── vial
5│       │── keymap.c
6│       └── vial.json
7├── keyboard.json
8└── readme.md
点击展开查看更多

vial 文件夹下,创建一个 rules.mk 文件,里面填写

C
1VIA_ENABLE = yes
2VIAL_ENABLE = yes
点击展开查看更多

VSCode 编辑 Vial 键盘项目文件夹 rules

回到 QMK MSYS 下,运行命令 python3 util/vial_generate_keyboard_uid.py 以生成键盘唯一ID

BASH
1[Xin@DESKTOP-XXXXXXX vial-qmk]$ python3 util/vial_generate_keyboard_uid.py
2#define VIAL_KEYBOARD_UID {0x53, 0x21, 0xDA, 0xFB, 0x9E, 0x57, 0x5A, 0x9E}
点击展开查看更多

vial 文件夹下,创建一个 config.h 文件,里面填写如下内容,其中第3行就是上面获取到的键盘唯一ID

C
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#pragma once
4
5#define VIAL_KEYBOARD_UID {0x53, 0x21, 0xDA, 0xFB, 0x9E, 0x57, 0x5A, 0x9E}
点击展开查看更多

Vial 建议为了安全起见,需要一个至少2键的组合键用于解锁刷写权限。如果你不想按解锁组合键,可以在 rules.mk 文件里面添加一条 VIAL_INSECURE = yes

这里我还是按官方推荐用上解锁组合键,就把外侧用于切换层的2个"L1"键,定义成解锁组合键吧,矩阵位置分别是 4,1 4,10

所以需要在 config.h 文件中,追加上这最后两行信息:

C
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#pragma once
4
5#define VIAL_KEYBOARD_UID {0x53, 0x21, 0xDA, 0xFB, 0x9E, 0x57, 0x5A, 0x9E}
6#define VIAL_UNLOCK_COMBO_ROWS {4, 4 }
7#define VIAL_UNLOCK_COMBO_COLS {1, 10}
点击展开查看更多

VSCode 编辑 Vial 键盘项目文件夹 config

编译固件

回到 QMK MSYS 中,输入 qmk compile -kb kinesis_advantage_teensy_pp2 -km vial

这个命令把最后的 default 改了对应的 vial,也就是默认的 default 映射,改成了 vial 映射

BASH
 1[Xin@DESKTOP-XXXXXXX vial-qmk]$ qmk compile -kb kinesis_advantage_teensy_pp2 -km vial
 2Ψ Compiling keymap with make -r -R -f builddefs/build_keyboard.mk -s KEYBOARD=kinesis_advantage_teensy_pp2 KEYMAP=vial KEYBOARD_FILESAFE=k inesis_advantage_teensy_pp2 TARGET=kinesis_advantage_teensy_pp2_vial VERBOSE=false COLOR=true SILENT=false QMK_BIN="qmk"
 3
 4
 5Generating: .build/obj_kinesis_advantage_teensy_pp2_vial/src/info_deps.d                            [OK]
 6Generating: .build/obj_kinesis_advantage_teensy_pp2_vial/src/community_modules.c                    [OK]
 7avr-gcc.exe (GCC) 15.1.0
 8Copyright (C) 2025 Free Software Foundation, Inc.
 9This is free software; see the source for copying conditions.  There is NO
10warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
12Generating: .build/obj_kinesis_advantage_teensy_pp2_vial/src/community_modules.h                    [OK]
13...
14Compiling: tmk_core/protocol/lufa/usb_util.c                                                        [OK]
15Linking: .build/kinesis_advantage_teensy_pp2_vial.elf                                               [OK]
16Creating load file for flashing: .build/kinesis_advantage_teensy_pp2_vial.hex                       [OK]
17Copying kinesis_advantage_teensy_pp2_vial.hex to qmk_firmware folder                                [OK]
18Checking file size of kinesis_advantage_teensy_pp2_vial.hex                                         [OK]
19 * The firmware size is fine - 35354/122880 (28%, 87526 bytes free)
点击展开查看更多

编译完成后,在 C:\Users\Xin\vial-qmkf\ 下的 .build 文件夹,可以找到格式为 键盘名_vial.hex 的文件,这个就是我们编译完成的vial固件。

Vial 固件生成路径

可以看到默认出来的Vial固件体积有98KB,所以才建议使用 Vial 闪存要128KB起步,64KB都不够用。

真想塞进小闪存里面,可以看看 Vial 如何减小固件体积

刷入固件

找到 QMK Toolbox ,打开运行后

Open 选择上面生成的 Vial 固件,点右边的下拉选择对应的 AT90USB1286 ,勾选 Auto-Flash

按一下开发板上的 Reset 按钮,或者用之前键盘上定义过的快捷键进入 bootloader 模式,随后就会自动刷入固件。

QMK Toolbox 刷 Vial 固件

键盘映射修改

刷完固件之后,打开 Vial 软件,可以看到 Vial 直接就识别出来键盘,默认的键位配列就是QMK固件里面定义好的。

在这个界面可以直接修改按键并直接生效,不需要重新刷入固件,对于正在摸索改进自己键盘映射的用户十分方便。

Vial 的使用和功能我这里就不再赘述,请自行搜索了解。

Vial 固件刷入后界面

我们可以试一下矩阵测试和定义的解锁键是否正常。

点击 Matrix tester 标签页,点击右下角的 Unlock ,按弹窗提示,长按对应位置的按键即可完成解锁。

Vial 矩阵测试标签页

完成解锁后,就可以测试整个键盘的按键,Vial 矩阵测试的好处是,切换层这种没有输出键值的按键也可以测试到。

Vial 矩阵测试完成

至此,Vial固件就算制作完成了。

杂谈

人体工学键盘大概需要多少个键?

我觉得我们可以推导一下,手指以标准指法放在键盘上,大部分人除拇指外,每根手指能舒适按到大概有3个键吧。

举个例子,右手食指默认放在J键上,除了J键还能舒服按到的键还有,手指向前伸展的U键,手指向后收缩的M键。

虽然常规键盘里面,标准指法在不移动手的情况下,给拇指按的只有1个空格。

但可以以此类推,拇指在舒适的放松状态的下的位置定为1个键,伸展的情况下定为1个键,收缩的情况下定为1个键,这样我们也得到了拇指对应的3个键。

10根手指,每根手指3个键,(4x3+3)*2 = 30,那是不是30个键就是最理想的数量?

如果当年的机械打字机直接就按人体工学键位来做,如果后面IBM也按人体工学键位和切换层的思路来做键盘标准。

那也许30键真的就是最理想的数量了,手指完全不用大幅度移动。

但是这基本不太可能的,就算没有机械打字机QWERT布局的影响,出于学习成本和制作成本的考虑,还是会增加更多的按键,也不会做切换层的功能。

历史无法改变,在不考虑兼容各种已有的、常见的键盘组合键和用法,在配合切换层的情况下,克服了学习成本和兼容性问题,30键的键盘确可以用。

现在的人体工学键盘,为兼容已有传统的布局以及放下更多的功能,也会在上面30键基础上,食指和小指区域都向外多增加了一例,由4x3变成了6x3。

corne-cherry v2

Corne 键盘是 6x3+3 键、列交错的分体式键盘,基于 Helix 。上面这个是v2版本,v4版本在每块的内侧增加了2个按键,基本要移动手才好按。

为了更高的兼容性,上面也可以加1行数字行,那就由6x3变成了6x4,然后空着也是空着,拇指区的3个键的边上也可以也再加几个键。

SofleKeyboard v2

SofleKeyboard 键盘是 6×4+5 键,列交错的分体式键盘。基于 Lily58 Corne Helix 键盘。上面这个是 Sofle v2

这就是现在90%的人体工学键盘的核心布局,大部分布局都是在此基础上的微调:列交错的幅度,要不要数字行,拇指区给几个键、怎么放,要不要做成立体的。

在这个思路上,我认为人体工学键盘在考虑到舒适度和兼容性的情况下,(6x4+4)* 2 = 56键 是一个相对合适的基准线。

tjx58

tjx58 键盘是 6×4+4+1 键,我没有正式发布出来,一开始叫T58,原谅我多年前的拍摄条件。

我第二把DIY键盘 tjx58 也是如此思路,每个手指负责4个键,小指和食指多负责1列,还多加了1个键来给手掌按压。共(6x4+4+1)* 2 = 58键。

不增加额外手指负担、不增加脚踏之类的外设的情况下,这是我觉得比较好的增加输入键的方式了,我觉得这个键当成层切换键(FN)用非常合适。

后记

写这篇的文章的原意是为了防止自己日后忘记,避免重新摸索。

结果这篇文章前后拖了一周多才写完,当我好不容易写完之后,我不禁反问自己:

我真的还有精力和必要去重头开始折腾一个新的键盘布局吗?

当年在折腾这把 Kinesis Contoured 之前,我已经DIY过两把人体工学键盘,都不超过60键。

第一把是分体,第二把是把分体的布局合并在了一起后微调了一下,就是上面的 tjx58。

当时因为是为了验证布局的合理性与测试是否习惯,两把DIY键盘都没有做PCB,直接找淘宝商家切割铝定位板后飞线做的。

后面也一直想着确定好布局之后,再去做PCB板做一个完全体,期间甚至想搞台3D打印机来做布局验证。

结果快十年了,我用得最多的就是 tjx58 和 改造版Kinesis Contoured,我一直没有确定好理想中的完全体,我也一直没有学完过怎么画PCB。

我的 tjx58 实际上和现在常见的 Corne、Sofle 已经非常相似了,比起自己重头做,貌似直接选择他们的套件可能是更好的选择……

妄想一下:我在做 tjx58的时候,Corne、Sofle 应该还没出现,也许当年我应该完善点发出来?搞不好在DIY键盘历史上能留下点我的痕迹……

Sofle 的作者在 2023年搞了一个 Stáňa (AKA Sofle Unsplit)单块的键盘,像是合并起来的Sofle,和我 tjx58几乎只有一个键的差异。

参考资料

教程

QMK固件 官方文档 - docs.qmk.fm

QMK新手开发教程 - bilibili.com/video/BV1h34y137YN

Vial 移植指南 - get.vial.today

工具

QMK MSYS 构建环境 - msys.qmk.fm

QMK Toolbox 工具箱- github.com/qmk/qmk_toolbox

键盘布局编辑器 - keyboard-layout-editor.com

Vial 软件 - get.vial.today

ai03 定位板生成器 - kbplate.ai03.com

定位板生成器 - builder.swillkb.com

键盘固件生成器 - kbfirmware.com

打印常见的人体工学键盘到纸上体验布局 - jhelvy.shinyapps.io

QMK 热图生成器 - precondition.github.io

更好看的键盘布局设计规划 - jaroslaw-weber.github.io

USB 设备树查看器 USB Device Tree Viewer

文章

我的第一个键盘 PCB 设计 - freemind.pluskid.org

较完整的记录了一个DIY键盘完整的制作过程

用拇指按 E ? - precondition.github.io

可能对有大量英文输入的人比较有意义

Jonas Hietala T-34 配列改进思路 - jonashietala.se )

键位少的用户可以看一下他的分配思路

基键修饰指南 - precondition.github.io

A guide to home row mods 在字母区二合一修饰键的复用思路

减小 QMK 中的固件大小 – thomasbaart.nl

万一你的开发板真的不够大

配列

DIY 机械键盘以及在哪里可以找到它们 - github.com/help-14/mechanical-keyboard

Yellow After life 的人体工学键盘列表数据库 - yal-tools.github.io

拆分键盘数据库 - golem.hu

符合人体工程学的分体式键盘⌨的集合 - github.com/diimdeep/awesome-split-keyboards

微处理器

Raspberry Pi 树莓派 RP2040 - pidoc.cn)

RP2040

STM32F103的规格 - st.com

STM32F103


原文作者:tjxwork
原文链接:https://www.tjxblog.com/blog/2025-0001
起稿时间:2025-08-28
完稿时间:2025-09-09
发布时间:2025-09-11

原来用的 Hexo + Stellar 主题,太久不用,各种莫名其妙的小Bug,花了两天时间改成 Hugo + Narrow 主题,并修改了部分样式……

版权声明

作者: tjxwork

链接: https://tjxblog.com/blog/2025-0001/

许可证: CC BY-NC-SA 4.0

使用者可以对本创作进行转载、节选、混编、二次创作,但不得运用于商业目的,且使用时须进行署名,采用本创作的内容必须同样采用本协议进行授权。

评论

开始搜索

输入关键词搜索文章内容

↑↓
ESC
⌘K 快捷键