QMK机械键盘固件开发指南:从源码到实践
QMK机械键盘固件开发指南:从源码到实践
前言
QMK(Quantum Mechanical Keyboard)是一款开源的键盘固件,支持众多自定义键盘的功能配置。通过QMK,您可以完全掌控键盘的每一个按键,实现复杂的宏指令、多层按键映射、RGB灯效等高级功能。本教程将带您从零开始构建一个基础的QMK键盘固件,使您的键盘真正实现个性化定制。
一、QMK项目文件结构
在开始编写固件代码前,我们需要先了解QMK的文件结构。对于每一个键盘项目,我们需要在keyboards
文件夹下创建特定的文件和文件夹。
1.1 基本结构
keyboards/
└── your_keyboard_name/ # 键盘名称(全小写,无空格,无特殊符号)├── rules.mk # MCU类型、Bootloader选择及功能开关配置├── config.h # 硬件参数配置├── info.json # USB VID/PID、制造商信息等├── your_keyboard_name.h # 键盘矩阵定义├── your_keyboard_name.c # 键盘核心功能实现└── keymaps/ # 键盘映射文件夹└── default/ # 默认键盘映射└── keymap.c # 按键功能定义
1.2 文件命名规则
关于命名规则,有几点需要特别注意:
- 键盘名称文件夹必须全部小写,不能包含空格和特殊符号(下划线除外)
.h
和.c
文件的名称应与最深层文件夹名称一致- 例如:如果键盘文件夹结构为
keyboards/modelo75/costume/
,则对应的文件应命名为costume.h
和costume.c
,而非modelo75.h
1.3 ARM架构专用文件
对于使用ARM架构芯片(如STM32系列)的键盘,还需要两个额外的文件:
mcuconf.h
- MCU配置文件halconf.h
- HAL层配置文件
注意:这两个文件对于AVR架构(如ATmega32U4)的键盘不是必需的。
二、创建键盘固件项目
现在,让我们一步步创建一个完整的键盘固件项目。本教程以一个名为"Modelo75"的75%布局键盘为例。
2.1 创建项目文件夹
首先,在QMK固件的keyboards
目录下创建一个新文件夹:
# 进入QMK固件目录
cd qmk_firmware# 创建键盘文件夹
mkdir keyboards/modelo75
2.2 编写 rules.mk 文件
rules.mk
是项目的核心配置文件,用于指定MCU类型、Bootloader以及各种功能开关。
# MCU名称
MCU = STM32F103
# 注释:芯片型号# Bootloader选择
BOOTLOADER = stm32duino
# 注释:F103需要使用stm32duino bootloader,因为它原生不支持USB DFU# 功能开关
NKRO_ENABLE = yes # 启用全键无冲
EXTRAKEY_ENABLE = yes # 启用音频控制和系统控制
# LTO_ENABLE = yes # 链接时优化,可减小固件体积(对于Flash空间小的MCU有用)
扩展知识:LTO(Link Time Optimization)是一种编译优化技术,可以在链接阶段对整个程序进行优化,减小固件体积并提高执行效率。对于Flash空间有限的AVR系列MCU(如ATmega32U4),启用LTO非常有用。
2.3 定义键盘矩阵 (modelo75.h)
键盘矩阵文件定义了键盘的物理布局,是固件开发中最重要的文件之一。这个文件将指导QMK如何理解您的键盘按键排列。
#pragma once#include "quantum.h"/* 这个宏防止头文件被重复包含 *//* 定义键盘布局 */
#define LAYOUT( \K000, K001, K002, K003, K004, K005, K006, K007, K008, K009, K010, K011, K012, K013, K014, \K100, K101, K102, K103, K104, K105, K106, K107, K108, K109, K110, K111, K112, K113, K114, \K200, K201, K202, K203, K204, K205, K206, K207, K208, K209, K210, K211, K212, K214, \K300, K301, K302, K303, K304, K305, K306, K307, K308, K309, K310, K311, K313, K314, \K400, K401, K402, K403, K404, K405, K406, K407, K408, K409, K410, K412, K413, K414, \K500, K501, K502, K506, K510, K511, K512, K513, K514 \
) { \{ K000, K001, K002, K003, K004, K005, K006, K007, K008, K009, K010, K011, K012, K013, K014 }, \{ K100, K101, K102, K103, K104, K105, K106, K107, K108, K109, K110, K111, K112, K113, K114 }, \{ K200, K201, K202, K203, K204, K205, K206, K207, K208, K209, K210, K211, K212, KC_NO, K214 }, \{ K300, K301, K302, K303, K304, K305, K306, K307, K308, K309, K310, K311, KC_NO, K313, K314 }, \{ K400, K401, K402, K403, K404, K405, K406, K407, K408, K409, K410, KC_NO, K412, K413, K414 }, \{ K500, K501, K502, KC_NO, KC_NO, KC_NO, K506, KC_NO, KC_NO, KC_NO, K510, K511, K512, K513, K514 } \
}
技巧:使用Excel等电子表格工具可以快速生成键盘矩阵布局。您可以在Excel中创建一个与键盘行列对应的表格,填入键位标识符,然后复制到代码中进行格式调整。
2.4 创建键盘C文件 (modelo75.c)
对于基础功能,这个文件可以非常简单:
#include "modelo75.h"/* 键盘特定功能的实现可以放在这里 */
/* 例如RGB矩阵效果、旋钮功能等 */
2.5 配置硬件参数 (config.h)
config.h
文件包含了键盘硬件相关的配置,如矩阵尺寸、引脚定义等:
#pragma once#include "config_common.h"/* 键盘矩阵尺寸 */
#define MATRIX_ROWS 6
#define MATRIX_COLS 15/* 键盘矩阵引脚定义 */
#define MATRIX_ROW_PINS { B5, B4, B3, A15, A2, A1 }
#define MATRIX_COL_PINS { A0, A3, A4, A5, A6, A7, B0, B1, B10, B11, B12, B13, B14, B15, B9 }/* 二极管方向 */
#define DIODE_DIRECTION COL2ROW
2.6 创建USB和设备信息 (info.json)
在QMK 0.19版本后,需要在info.json
文件中定义USB相关信息:
{"keyboard_name": "Modelo75","manufacturer": "YourName","url": "","maintainer": "YourName","usb": {"vid": "0xF055","pid": "0x7501","device_version": "0.0.1"}
}
注意:VID(厂商ID)和PID(产品ID)应该是唯一的。对于个人项目,可以使用随机的16进制数值,但要避免与商业产品冲突。
2.7 ARM架构特定文件
如果使用STM32等ARM架构芯片,还需要添加以下两个文件:
mcuconf.h:
#pragma once#include_next <mcuconf.h>
halconf.h:
#pragma once#include_next <halconf.h>
2.8 创建默认按键映射
现在创建键盘映射目录和默认映射文件:
mkdir -p keyboards/modelo75/keymaps/default
touch keyboards/modelo75/keymaps/default/keymap.c
编辑keymap.c
文件,定义键盘的默认按键功能:
#include QMK_KEYBOARD_H/* 层定义 */
enum layer_names {_BASE, // 基础层_FN // 功能层
};const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {/* 基础层 (0) */[_BASE] = LAYOUT(KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_DEL,KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_HOME,KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGDN,KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_END,KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, MO(_FN), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),/* 功能层 (1) */[_FN] = LAYOUT(KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,RGB_TOG, RGB_MOD, RGB_HUI, RGB_SAI, RGB_VAI, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS, RGB_RMOD,RGB_HUD, RGB_SAD, RGB_VAD, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, QK_BOOT, KC_TRNS, KC_MUTE, KC_VOLD, KC_VOLU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS)
};
三、层与键码详解
QMK的强大功能之一是支持多层按键映射,借助层切换功能,您可以在有限的物理按键上实现几乎无限的功能。
3.1 常用层切换键码
以下是QMK中用于层控制的常用键码:
键码 | 说明 |
---|---|
DF(n) | 将层n设为默认层 |
MO(n) | 按住时临时切换到层n,松开后返回 |
OSL(n) | 单击后下一个按键从层n生效,然后返回 |
LM(n,mod) | 类似MO(n),但同时应用指定的mod修饰符 |
LT(n,kc) | 按住时临时切换到层n,单击时发送KC键码 |
TG(n) | 切换层n的开启/关闭状态 |
TO(n) | 直接切换到层n |
TT(n) | 点按功能类似MO,多次点击保持层n开启 |
3.2 特殊键码举例
QMK提供了许多特殊键码,以下是一些常用的例子:
QK_BOOT
:进入Bootloader模式,可用于刷新固件RGB_TOG
:开关RGB灯效RGB_MOD
:切换RGB灯效模式KC_MUTE
:系统静音KC_VOLD
/KC_VOLU
:音量减/增
四、编译和烧录固件
完成所有文件的创建和编辑后,就可以编译并烧录固件了。
4.1 编译固件
使用以下命令编译固件:
qmk compile -kb modelo75 -km default
如果您有多级目录,需要指定完整路径:
qmk compile -kb your_folder/modelo75 -km default
4.2 烧录固件
编译成功后,固件文件会生成在.build
文件夹中。根据MCU类型,文件格式可能是.hex
、.bin
或.uf2
。
使用QMK Toolbox或命令行工具烧录固件:
qmk flash -kb modelo75 -km default
重要提示:烧录固件前,需要将键盘设置为Bootloader模式。这通常可以通过按下键盘上的RESET按钮,或在PCB上短接RESET和GND引脚实现。
五、扩展功能与进阶技巧
5.1 快速构建键盘矩阵的Excel技巧
创建键盘矩阵是固件开发中最繁琐的工作之一。使用Excel可以大大简化这一过程:
- 创建一个与键盘行列数相匹配的表格
- 按照行列顺序填入键位标识符(如K000, K001等)
- 在单元格间添加逗号分隔符
- 复制整个表格数据到代码编辑器
- 使用查找替换功能调整格式
5.2 代码优化与调试技巧
- 保持代码整洁:适当的缩进和注释可以使代码更易于阅读和维护
- 模块化设计:将复杂功能拆分为单独的函数,提高代码可维护性
- 使用条件编译:对于可选功能,使用条件编译可以减小固件体积
- 日志输出:在调试复杂问题时,可以使用
print
或dprintf
函数输出调试信息
5.3 常见问题解决方案
- 编译错误:检查括号、逗号是否正确,确保所有必需文件都已创建
- 按键不响应:检查键盘矩阵定义是否正确,二极管方向是否设置正确
- 层切换问题:确认层切换键的位置和功能是否正确配置
- 固件太大:尝试启用LTO,或禁用不需要的功能
- USB不识别:检查VID/PID配置,确保已正确设置USB参数
六、结语
通过本教程,您已经学习了如何从零开始创建QMK键盘固件。这只是QMK功能的冰山一角,随着您的深入学习,还可以探索更多高级功能,如RGB灯光效果、OLED显示、旋钮编码器控制等。
持续学习QMK文档和社区资源,将帮助您进一步掌握键盘固件开发技术,创造出完全符合个人需求的独特键盘体验。
如果您在开发过程中遇到任何问题,欢迎在评论区留言交流,也可以加入QMK官方Discord社区获取更多帮助。
参考资源:
- QMK官方文档
- QMK GitHub仓库
- 键码列表
- QMK设置指南