ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

QMK Sweet16 轴体测试器 Keymap 实战:基于 switches 数组与位域宏实现按轴报名

QMK Sweet16 轴体测试器 Keymap 实战:基于 switches 数组与位域宏实现按轴报名 QMK Sweet16 轴体测试器 Keymap 实战基于 switches 数组与位域宏实现按轴报名【免费下载链接】qmk_firmwareOpen-source keyboard firmware for Atmel AVR and Arm USB families项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmware本篇文章以 QMK Firmware 仓库中keyboards/1upkeyboards/sweet16/keymaps/switchtester这个官方示例 keymap 为主体完整拆解它是如何把一块 4×4 的 Sweet16 小键盘垫变成“轴体测试器”的按下任意按键固件就把该位置安装的机械轴名称如Cherry MX Blue、Gateron Red以文本形式输出到电脑。读完本文你将掌握 QMK 中process_record_user按键拦截、二维数组按矩阵位置索引、位域结构体定义轴体属性、名称拼接与send_string输出等完整实现链路并可以直接照搬到自己的键帽/轴体测试项目中。一、这个 Keymap 是什么把 Sweet16 变成轴体测试器Sweet16是由 1up Keyboards 出品的 4×4 正交网格小键盘垫macropad其厂商与维护者信息、USB VID 以及LAYOUT_ortho_4x4、LAYOUT_numpad_4x4两种布局定义都可以在 keyboards/1upkeyboards/sweet16/info.json 中查到键盘整体说明见 keyboards/1upkeyboards/sweet16/readme.md。switchtester是官方提供的其中一个 keymap它的用途正如其名每个按键位对应一枚真实焊接在 PCB 上的机械轴体按下后固件会把该轴的型号名称直接打字输出相当于一个即插即用的“轴体标签打印机”适合用来给批量收到的轴体做分类标记或手测手感。与同键盘的默认 keymapkeymaps/default/keymap.c数字小键盘功能不同switchtester 的按键矩阵本身不响应任何常规按键功能而是全部交给自定义逻辑处理。二、整体架构三个文件的分工该 keymap 目录keyboards/1upkeyboards/sweet16/keymaps/switchtester/下共有 4 个核心文件职责非常清晰文件职责keymap.c定义 4×4 空键位、声明switches轴体摆放表、实现process_record_user按键处理switches.h定义struct mechswitch位域结构体、品牌/颜色/变体枚举常量以及全部轴体宏switches.c提供品牌/颜色/变体名称映射表与switch_name()名称拼接函数rules.mk该 keymap 的构建配置并通过SRC switches.c把自定义源文件编入固件这种“数据宏定义 逻辑名称映射 键位keymap”分层方式是把这个测试器扩展到任意新轴体时最容易维护的结构。三、键位与轴体摆放表用 4×4 数组一一对应矩阵位置3.1 空键位定义keymap.c 中的键位映射全部使用KC_NO表示这些键位不执行任何标准按键行为const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] { LAYOUT_ortho_4x4( KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO ) };MATRIX_ROWS/MATRIX_COLS由键盘定义给出此处为 4×4与LAYOUT_ortho_4x4的 16 个矩阵坐标一一对应见 info.json 中matrix: [row, col]的定义顺序。3.2 轴体摆放表switches轴体与矩阵位置的对应关系保存在一个与键位矩阵同样形状的二维数组里行/列索引即按键的行/列struct mechswitch switches[MATRIX_ROWS][MATRIX_COLS] { {CHERRY_MX_BLUE, CHERRY_MX_RED, CHERRY_MX_BLACK, CHERRY_MX_BROWN}, {GATERON_BLUE, GATERON_RED, GATERON_BLACK, GATERON_BROWN}, {KAILH_BLUE, KAILH_RED, KAILH_BLACK, KAILH_BROWN}, {HAKO_CLEAR, HAKO_TRUE, HAKO_VIOLET, HAKO_ROYAL_TRUE} };也就是说第一行焊接的是 4 颗 Cherry MX蓝/红/黑/茶第二行是 4 颗 Gateron第三行是 4 颗 Kailh第四行是 4 颗 Hako。要测试别的轴只需要把对应位置的宏替换掉即可无需改动任何处理逻辑。四、按键处理核心process_record_user 与矩阵坐标读取处理逻辑同样在 keymap.c 中它是整个测试器的“心脏”bool process_record_user(uint16_t keycode, keyrecord_t *record) { uint8_t col record-event.key.col; uint8_t row record-event.key.row; if (record-event.pressed) { char name[MAX_SWITCH_NAME_LENGTH]; switch_name(switches[row][col], name); send_string(name); SEND_STRING(\n); } return false; }关键点逐条说明取矩阵坐标record-event.key.row与record-event.key.col是本次事件对应的矩阵行列号switches[row][col]就能直接取到该位置安装的轴体。仅在按下时响应通过record-event.pressed判断只在下压沿输出一次避免按住时重复触发。名称拼接switch_name()把struct mechswitch解析为可读文本写入name缓冲区。文本输出send_string(name)将名称以 HID 键盘文本形式逐字打出随后SEND_STRING(\n)补一个回车换行形成“每按一次、输出一行轴名”的效果。返回false吞掉本次按键事件阻止其继续走常规键码处理键位本身也是KC_NO双保险确保不会产生意外输入。send_string/SEND_STRING是 QMK 提供的最常用的字符串发送宏适用于这种需要“打字”场景本 keymap 在rules.mk中开启了EXTRAKEY_ENABLE等特性send_string属于核心功能、默认可用。五、数据模型用位域结构体描述一颗轴5.1struct mechswitch位域设计switches.h 用一个紧凑的位域结构体描述轴体三要素——品牌、变体、颜色struct mechswitch { unsigned int brand: 4; // 品牌最多 16 种 unsigned int variant: 4; // 变体最多 16 种 unsigned int color: 5; // 颜色最多 32 种 };总共只用 13 bit 就能唯一标识一颗轴说明这个 keymap 把“描述数据”压缩到了极致每个字段用宏常量枚举品牌brandBRAND_KAILH(1)、BRAND_KAILH_LOW(2)、BRAND_GATERON(3)、BRAND_CHERRY_MX(4)、BRAND_CHERRY_ML(5)、BRAND_OUTEMU(6)、BRAND_GREETECH(7)、BRAND_VARMILO(8)、BRAND_MOD(9)、BRAND_HAKO(10)。颜色color从COLOR_NO(0) 到COLOR_SH(30)共 31 个覆盖White/Black/Blue/Red/Brown/Green/Clear/Silver/Nature White/Grey/Jade/Navy/Burnt Orange/Pale Blue/Dark Yellow/Gold/Chocolate White/Burgundy/Purple/Light Green/True/Berry/Plum/Sage/Violet/L/M/H/SH等实际轴色命名。变体variantVARIANT_NO(0)、VARIANT_BOX、VARIANT_BOX_THICK、VARIANT_BOX_HEAVY、VARIANT_SILENT、VARIANT_TACTILE、VARIANT_LINEAR、VARIANT_SPEED、VARIANT_SPEED_HEAVY、VARIANT_SPEED_CLICK_THICK、VARIANT_PRO、VARIANT_PRO_HEAVY、VARIANT_ROYAL、VARIANT_CLICK_THICK等用来表达“BOX”“Silent”“Speed”“Pro”“Royal”这类系列名。5.2 轴体宏复合常量的定义方式在枚举之上switches.h 用“宏 → 结构体初始化器”的方式定义了大量现成轴体例如#define CHERRY_MX_BLUE {BRAND_CHERRY_MX, VARIANT_NO, COLOR_BLUE} #define CHERRY_MX_SILENT_BLACK {BRAND_CHERRY_MX, VARIANT_SILENT, COLOR_BLACK} #define GATERON_SILENT_CLEAR {BRAND_GATERON, VARIANT_SILENT, COLOR_CLEAR} #define KAILH_BOX_WHITE {BRAND_KAILH, VARIANT_BOX, COLOR_WHITE} #define KAILH_BOX_THICK_JADE {BRAND_KAILH, VARIANT_BOX_THICK, COLOR_JADE} #define KAILH_SPEED_GOLD {BRAND_KAILH, VARIANT_SPEED, COLOR_GOLD} #define KAILH_PRO_BURGUNDY {BRAND_KAILH, VARIANT_PRO, COLOR_BURGUNDY} #define HAKO_ROYAL_TRUE {BRAND_HAKO, VARIANT_ROYAL, COLOR_TRUE} #define MOD_L_TACTILE {BRAND_MOD, VARIANT_TACTILE, COLOR_L}这份清单覆盖了该 keymap 内置可用的全部轴型包括 Cherry MX 全色系与 Silent/Tactile/Linear 变体、Cherry ML、Gateron 常规与 Silent 系列、Greetech、Outemu、Kailh 常规/BOX/BOX Thick/BOX Heavy/Speed/Speed Heavy/Speed Thick Click/Pro/Pro Heavy/Low Profile Choc 系列、Hako 与 Hako Royal、以及 MOD 系列——新增轴体时只需按同样格式追加一条宏即可例如#define YOUR_SWITCH {BRAND_KAILH, VARIANT_BOX, COLOR_RED}随后把该宏填入switches数组即可。六、名称渲染switches.c 的映射表与拼接逻辑6.1 三张静态名称映射表switches.c 顶部定义了与枚举一一对应的三张字符串表BRAND_NAMES[]Kailh、Kailh Low Profile Choc、Gateron、Cherry MX、Cherry ML、Outemu、Greetech、Varmilo、MOD、Hako。COLOR_NAMES[]空字符串对应COLOR_NO加 30 个颜色名。VARIANT_NAMES[]空字符串对应VARIANT_NO加BOX、BOX Thick、BOX Heavy、Silent、Tactile、Linear、Speed、Speed Heavy、Speed Thick Click、Pro、Pro Heavy、Royal、Thick Click、Heavy。三个取值函数直接用枚举值做下标取字符串const char *brand_name(struct mechswitch ms) { return BRAND_NAMES[ms.brand - 1]; } const char *variant_name(struct mechswitch ms) { return VARIANT_NAMES[ms.variant]; } const char *color_name(struct mechswitch ms) { return COLOR_NAMES[ms.color]; }注意品牌表下标做了- 1偏移品牌枚举从 1 开始而变体与颜色下标直接使用枚举值从 0 开始。6.2switch_name()拼出完整轴名void switch_name(struct mechswitch ms, char *buf) { const char *v_name variant_name(ms); const char *c_name color_name(ms); snprintf(buf, MAX_SWITCH_NAME_LENGTH, %s, brand_name(ms)); strncat(buf, , MAX_SWITCH_NAME_LENGTH - strlen(buf)); if (strlen(v_name) 0) { strncat(buf, v_name, MAX_SWITCH_NAME_LENGTH - strlen(buf)); strncat(buf, , MAX_SWITCH_NAME_LENGTH - strlen(buf)); } if (strlen(c_name) 0) { strncat(buf, c_name, MAX_SWITCH_NAME_LENGTH - strlen(buf)); } }拼接规则为品牌 [变体] [颜色]变体/颜色为空字符串时自动跳过并省略多余空格因此CHERRY_MX_BLUE→Cherry MX BlueKAILH_BOX_THICK_NAVY→Kailh BOX Thick NavyGATERON_SILENT_RED→Gateron Silent RedHAKO_ROYAL_TRUE→Hako Royal True缓冲区长度由switches.h中的MAX_SWITCH_NAME_LENGTH256限定所有strncat都带剩余长度上限避免溢出。同文件还附带了一个辅助函数bitfieldtoi()把三个位域拼成一个整数brand 9 | variant 5 | color可以推断这是为调试/序列化场景预留的工具函数。七、构建配置rules.mk 怎么把自定义代码编进去keymaps/switchtester/rules.mk 中的关键一行是SRC switches.c它把 keymap 目录下的switches.c加入本次构建的源文件列表从而让keymap.c中调用的switch_name()等函数能被链接进固件。其余选项依次为BOOTMAGIC_ENABLE no MOUSEKEY_ENABLE no EXTRAKEY_ENABLE yes # 媒体键与系统控制 CONSOLE_ENABLE yes # 调试用控制台输出 COMMAND_ENABLE yes # 调试与配置命令 NKRO_ENABLE no RGBLIGHT_ENABLE no其中EXTRAKEY_ENABLE提供媒体/系统键支持CONSOLE_ENABLE与COMMAND_ENABLE为调试打开通道RGBLIGHT_ENABLE在该 keymap 中被关闭测试器不需要灯效。八、编译、烧录与使用在 QMK 环境中按标准工作流编译烧录该 keymapqmk compile -kb 1upkeyboards/sweet16 -km switchtester qmk flash -kb 1upkeyboards/sweet16 -km switchtester-kb指定键盘-km指定 keymap 名称也可用传统方式make 1upkeyboards/sweet16:switchtester。使用流程将待测轴体按switches数组的摆放焊入/装入 Sweet16 的对应键位打开任意文本编辑器或终端按下某个键电脑即收到该键位轴体的完整名称文本并自动回车换行逐个按压即可快速得到一份“哪个键位装了什么轴”的输出清单用于核对或记录。九、如何扩展成你自己的轴体测试器把这个示例改造成自用测试器只需三步加宏在 switches.h 中按#define 轴名 {BRAND_*, VARIANT_*, COLOR_*}格式新增你手里的轴若品牌/颜色不在现有枚举里先在枚举区追加常量再在 switches.c 的BRAND_NAMES/COLOR_NAMES表里补对应字符串——下标必须与枚举顺序严格一致填数组把新宏按矩阵行列填进keymap.c的switches[MATRIX_ROWS][MATRIX_COLS]与物理焊接位置一一对应编译烧录重新qmk compile/qmk flash即可。同理该模式也适用于其他任意正交网格 macropad把LAYOUT_ortho_4x4换成自己的布局、矩阵尺寸换成自己的行列数是 QMK 中“自定义数据 矩阵坐标索引 文本输出”这一类实用 keymap 的典型范本。【免费下载链接】qmk_firmwareOpen-source keyboard firmware for Atmel AVR and Arm USB families项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmware创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表