☰
三模无线键盘主控移植:QMK固件与双主控矩阵复用实践
2026/10/29 15:46:14 网站建设 项目流程

键盘圈子里隔三差五就有人问:手里那把型号后缀带 G6 的三模无线键盘,轴还好用,外壳手感也在,就是主控阉割得厉害——没有开源固件、灯效固定、宏编辑要靠配套软件、蓝牙通道少得可怜,扔了可惜,用着难受。于是就有了这块“移植板”的活:保留原厂外壳、原厂定位结构、原厂轴体,把里面那块主板整个换掉,换成自己画的 PCB 加自己写的 QMK 固件,顺便把有线、蓝牙、2.4G 三条通道和 RGB 灯效一起做进去。这类项目在社区里叫“主控移植”或者“换心手术”,难度不算顶天,但坑极其密集:外壳测绘、轴位兼容、矩阵复用、电源路径、固件移植,每一环都能让人卡上一周。这篇文章就把我这一版三模 RGB 移植板的完整思路、参数核算、实操步骤和踩过的坑,从头到尾摊开讲一遍,写给已经会焊板子、想往固件和系统设计再走一步的朋友,也写给刚入门、想搞清楚“一块键盘主板到底难在哪”的新手。

1. 先想清楚:这块板子到底在解决什么问题

动手画板之前,最该做的不是打开 EDA 软件,而是拿张纸把“我到底要什么”写清楚。移植板项目失败的案例里,十有八九不是焊接翻车,而是一开始的目标就没收敛——既想保留原厂轴,又想换 MX 键帽,还想塞进 3000mAh 大电池,最后板子画出来发现外壳装不进去。所以这一章先把需求拆干净。

1.1 移植板的价值边界在哪里

所谓移植板,本质是用自制 PCB 替换原厂主板,同时保留原厂机械结构。这个定义里有两个关键词:替换、保留。替换的是电气核心,保留的是外壳、定位板、轴体、键帽这套物理系统。它的价值不在于“做一把新键盘”,而在于让一个已经被固件锁死的成品,重新获得可编程能力。

具体到这把 G 系原型键盘,原厂状态下的限制非常明确:配列是 108 键加左侧 6 个独立宏键,共 114 个物理按键;无线用的是厂商私有协议,接收器丢了基本就废了;灯效只有固定几档,且没有逐键控制;宏定义必须依赖桌面软件,换台电脑就得重装;蓝牙通道数量也不够轮流切换设备。这些限制里,前两条是硬件层面的,后三条纯粹是固件层面的。移植板真正解决的,是后面三条——把固件的话语权拿回来。

那么前面两条呢?私有协议这条,移植板必须自己重新实现一套 2.4G 收发,否则“三模”就名不副实。这是本项目里技术含量最高、也最容易半途而废的部分。我在第一版里就干了件蠢事:先把有线和蓝牙做完,觉得 2.4G“回头再说”,结果外壳已经封胶、电池已经点焊,回头再改板等于重来。所以后面章节里我会反复强调一件事——三模的三个模,必须在画第一版 PCB 的时候就全部预留好电路和引脚,哪怕固件先只做两模。

至于键位数量,114 键这个数字看着不大,但它决定了矩阵规模、扫描时序、GPIO 预算、灯珠数量,几乎每一个下游参数都从它推出来。所以第一件事是把键位表列全:主键区 104 键、左侧宏键 6 个、顶部功能键区若干、再加一个独立的音量滚轮(原厂是编码器还是电位器,要拆开确认,两者电路完全不同)。

注意:拆机第一件事不是拔排线,是先拍照。原厂主板上每一条排线的走向、每一个卡扣的方向、每一颗螺丝的长度差异,都要留档。我见过太多人拆完装不回去,最后靠网上别人的拆机图猜。

1.2 三模、RGB、开源固件这三件事为什么会互相打架

单看每一个需求都不算难:三模有成熟的芯片方案,RGB 有成熟的灯珠和驱动库,QMK 有一整套键盘固件框架。难点在于这三者放在同一块板子上,且共用一套电池供电时,会形成三组硬冲突。

第一组冲突是固件生态与无线能力。QMK 主线对蓝牙的支持一直不是它的强项,主线代码的重心在有线 USB HID 和矩阵扫描上。原生支持低功耗蓝牙的开源键盘固件是另一个分支体系,但那个体系的生态、灯效插件、宏系统跟 QMK 又不是一回事。想在同一颗主控上同时拿到 QMK 的完整功能和稳定的低功耗蓝牙,现实做法只有两条:要么用社区维护的无线分支(版本跟进慢,出问题得自己啃代码),要么走双主控路线。我选的是后者,原因在后面 2.3 节展开。

第二组冲突是RGB 功耗与电池续航。这个必须拿数字说话。常见的串行可编程灯珠,单颗全白满亮度电流在 50 到 60 毫安之间,114 颗全开就是 6.8 安培左右。这个数字不是“有点大”,是“电池直接保护板跳闸”的级别。就算把亮度压到 20/255,等效占空比 8% 左右,全键点亮也是 500 毫安上下的持续电流。一块 2000mAh 的电池,这么烧只能撑四个小时。所以 RGB 和无线这两个功能,在物理上就不可能“同时全开还想要长续航”,必须做策略性限流。

第三组冲突是充电、放电、供电三者的路径。键盘插着 USB 的时候,既要从 USB 取电给主控,又要给电池充电,还要保证这时候按下的键走有线通道而不是蓝牙通道。如果电源路径设计得糙,会出现“边充边用导致电池反复微循环”或者“插上线以后蓝牙没断开、两个通道同时发键”这种诡异现象。

冲突项具体表现我的处理思路
固件与无线主线固件无线支持弱双主控 + 矩阵硬件切换
RGB 与续航满亮电流超出电池承受范围全局亮度封顶 + 无操作熄灭
充放电路径边充边用损伤电池、通道抢占路径管理 IC + USB 插入硬件优先

1.3 最终架构的取舍:两颗脑子加一条共享矩阵

把上面三组冲突消化完之后,整体架构就定型了,用一句话概括:两颗主控,共享一套按键矩阵,硬件仲裁通道归属。

一颗是工业级的通用 MCU,跑 QMK 固件,负责 USB 有线模式下的全部逻辑,包括矩阵扫描、键位映射、宏、层切换、RGB 灯效运算。另一颗是低功耗无线 SoC,负责蓝牙和 2.4G 两条无线通道,自己跑一套轻量的扫描和 HID 上报逻辑。两颗芯片不通信,或者说只在极少数场景下通过一根握手线通信,避免协议耦合带来的调试地狱。

按键矩阵的物理走线只有一套,接到两颗主控上。谁在工作,谁就接管矩阵;另一颗的扫描引脚全部置为高阻输入,或者干脆用模拟开关做物理隔离。电源方面,锂电池经路径管理芯片分三路:一路给 USB 主控的 LDO,一路给无线 SoC 的低压差稳压,一路给灯珠的升压或直驱。

这套架构的代价是 BOM 成本上去了一点,PCB 面积吃紧,布线复杂度翻倍。收益是每一部分都可以独立调试、独立替换、独立升级。有线模式下的手感调优和灯效折腾,完全不影响无线那套代码;无线那边延迟不满意,换个模块重刷就行,不用碰 QMK 那一坨。对一个长期维护的个人项目来说,这种解耦比省几块钱重要得多。

2. 主控选型与矩阵复用设计

选型这件事,圈子里有个不太好的惯性:看到别人用什么就跟着用什么。但移植板这种项目,主控的选择标准跟“做一把新键盘”其实不太一样——你要考虑的是能不能塞进原厂外壳那个狭长的板型空间、能不能在有限的层数里布完线、能不能长期买到。

2.1 工业级 MCU 为什么会进入键盘选型池

客制化键盘圈长期以来的默认选项是某几个经典系列,生态好、资料多、QMK 官方支持完善。但这两年情况变了:这些经典型号的价格波动大、交期不稳、市场上翻新货和打磨片不少,批次之间还可能有细微差异。于是很多人开始把目光投向工业控制领域量产的 MCU——这些芯片原本用在电机驱动、工业仪表、电源管理这些场景,特点是供货稳定、温宽宽、单价低、外设齐全。

把它们挪到键盘上,需要对齐几个硬指标,我列了个选型清单:

指标要求为什么这么要求
USB 控制器内置全速 USB 2.0 设备控制器外挂 USB 桥接芯片会增加成本和故障点
Flash不小于 128KBQMK 加灯效加宏,64KB 很容易爆
RAM不小于 32KB灯效缓冲和层数据占地方
主频不低于 72MHzRGB 矩阵运算是主要开销
GPIO可用不少于 45 个23 根矩阵线 + 灯线 + 杂项
封装LQFP48 或 LQFP64手焊友好,面积也能塞进外壳
供电电压支持 3.3V 单电源省掉额外电平转换

实际算一遍 GPIO 预算:8 行 15 列的矩阵要 23 根,RGB 数据线 1 根,三模切换检测 2 根(USB 插入检测、模式拨钮),编码器 2 根(A/B 相),指示灯 3 根(大写锁定、通道指示、充电指示),再加上调试串口 2 根、SWD 烧录 2 根,总共 35 根。留出 20% 余量,45 根可用 GPIO 是比较舒服的。LQFP64 封装通常能提供 50 根左右,刚好够。

这里有个容易忽略的细节:工业 MCU 的引脚复用表往往比消费级芯片保守,很多引脚默认是模拟功能或者特殊外设,需要显式关掉才能当普通 IO 用。我第一版板子就踩了这个坑——某几个引脚默认带内部比较器,上电后一直输出高电平,导致对应的矩阵列永远读到“按下”。排查了两个晚上才在参考手册角落里找到那个寄存器位。

实操心得:拿到一颗没用过的 MCU,第一件事不是画板,是画一块最小系统板,把矩阵扫描、USB 枚举、灯珠驱动这三件事各跑通一遍。花三天时间做最小验证,能省掉三周的返工。

2.2 引脚预算与扫描时序的账

矩阵规模定为 8 行 × 15 列 = 120 个交叉点,114 个按键占用 95%,剩下 6 个空位留给未来可能的扩展(比如加个旋钮按压或者备用键)。为什么不排成 6×20?因为 20 列的走线会把 PCB 横向拉得太开,塞不进原厂板型;而 8 行的纵向排布正好贴合原厂主板的宽度。

扫描时序这块要算一笔账。QMK 默认的矩阵扫描周期通常在毫秒级别,对有线键盘完全够用。但这把键盘要跑无线,无线模式下扫描频率直接关系到延迟和功耗的平衡:扫得太慢,按键响应跟不上;扫得太快,主控没法进低功耗状态。

单行扫描时间 ≈ 引脚建立时间(2μs) + 稳定延时(3μs) + 读取(1μs) ≈ 6μs 完整一轮 8 行 ≈ 48μs 理论最高扫描率 ≈ 1 / 48μs ≈ 20kHz

实际不会跑这么高。我最终取的是每 1 毫秒扫一轮,也就是 1kHz 扫描率,这个频率下人手最快连击也不会漏键,同时主控有 95% 的时间可以待在低功耗状态。有线模式下可以把这个间隔压到 0.5 毫秒,反正不缺电。

消抖参数也得跟着改。QMK 默认 5 毫秒,这个值在 1kHz 扫描下相当于连续 5 轮读到相同状态才确认,手感上会有轻微迟滞。我实测下来,质量好的轴体在 3 毫秒就能稳定,所以无线模式设 4 毫秒、有线模式设 2 毫秒,是延迟和稳定性的折中点。当然如果用的是原厂那种双触点结构的方柱轴,触点抖动会比标准轴大一些,建议不要低于 4 毫秒。

2.3 双主控共享矩阵:模拟开关还是高阻并联

这是整个项目里最容易出问题的地方,值得单独拎出来讲透。两颗主控都要读同一套矩阵,最直觉的做法是直接并联,谁不工作就把引脚设成高阻。但这个方案有两个隐患:一是某些 MCU 的 GPIO 在复位期间处于不确定状态,可能短暂拉低某条列线造成误读;二是长时间高阻并联,PCB 上的寄生电容会让扫描波形变钝,边缘变缓,读到的电平处在中间态。

所以我最终选了硬件隔离:在矩阵的行线上串入双向模拟开关,用一颗仲裁逻辑控制通断。行线只有 8 根,用两片六路双向开关芯片就够了;列线直接并联,因为列线是输入方向,未工作的主控把引脚设为输入即可,不存在驱动冲突。

仲裁逻辑很简单,用一个或门加一个延时电路实现:

  • USB 插入检测脚为低电平(表示插了线),强制切到有线主控,无线 SoC 断电。
  • USB 拔出后,延时约 200 毫秒再切回无线,避免插拔瞬间的抖动导致两颗主控抢总线。
  • 无线 SoC 在检测到自己被断电时,立刻停止扫描并把所有引脚置输入。

这段逻辑我用一颗小逻辑芯片加 RC 延时搭的,没走软件。原因是软件仲裁在掉电瞬间不可靠——主控自己都快没电了,还指望它优雅退出,不现实。

注意:模拟开关的导通电阻会串进扫描回路,选型时要看这个参数。导通电阻超过 100 欧的型号,在长列线上会造成明显的电平衰减,表现为边缘按键偶尔失灵。选 10 欧以下的。

还有一个细节:模拟开关切换的瞬间,矩阵上会有一个极短的浮空状态,可能被误判成一串按键按下。解决办法是在固件初始化时加一个“上电丢弃前 50 毫秒扫描结果”的逻辑,切换时同理。这个补丁很小,但不加的话会出现开机瞬间乱发键的问题。

3. 硬件实做:从外壳测绘到电源路径

架构定完进入画板阶段,这一步的节奏很不一样:软件可以反复改,PCB 打一次样就是一周加几百块。所以画板阶段的原则是宁可多花两天核对尺寸,不要靠飞线补救。

3.1 外壳测绘与定位柱避让

原厂外壳不是为标准 PCB 设计的,它的内部空间里有大量加强筋、定位柱、卡扣、电池仓隔断。这些东西在 PCB 上必须一一避让,否则板子装不进去,或者装进去了被顶得翘起来。

我的测绘流程是这样的:先拆掉原厂主板,用游标卡尺量出外壳内腔的长、宽、深度,以及每一个定位柱的中心坐标和直径。然后用平板扫描仪把外壳底面按 1:1 扫一遍,导入 EDA 软件作为底层参考图,描出轮廓线。扫描的精度受限于扫描仪,通常有 1% 左右的误差,所以关键位置——尤其是螺丝孔和定位柱——必须用卡尺实测校正。

几个容易被忽略的配合点:

  • 螺丝柱的高度:原厂用的螺丝柱往往不是等高的,靠近边缘的会矮一些,因为外壳有弧度。PCB 上的过孔位置对了,但如果板子厚度选错,螺丝拧到底会把板子压弯。
  • 排线出口:电池仓和主控板之间通常有排线穿过,PCB 上要留缺口,缺口的圆角不能太小,否则应力集中容易裂。
  • 卡扣凸起:外壳内侧常有几处小凸起用来压住主板,这些凸起对应位置的 PCB 元件高度必须控制住,否则压不进去。

我第一版就死在卡扣上——灯珠放在了靠近边缘的位置,高度超了 0.8 毫米,外壳压不紧,缝隙肉眼可见。第二版把灯珠整体内移 3 毫米,同时换成矮体封装才解决。

实操心得:测绘阶段建议做一块“假板”——用 1.6 毫米厚的亚克力或者覆铜板按轮廓切出来,装上定位柱试插一遍。成本几块钱,能提前发现 90% 的机械配合问题。

3.2 轴位的兼容取舍:保留原厂轴还是改标准轴

这是整个项目里最需要冷静决策的一步,因为它直接决定了工程量。原厂用的是方柱定位结构的轴体,它的定位柱是方形、焊脚位置和标准机械轴完全不同,键帽接口也是专用的。这意味着两件事:原厂轴装不到标准轴位上,标准轴也装不进原厂外壳的轴孔。

摆在面前的是两条路:

方案工作量手感上限键帽可选性综合建议
保留原厂轴小,只做封装库受限于原厂轴只能用原厂键帽推荐,适合首版
换标准轴大,需扩孔或做转接高,可换各种轴全兼容适合二版或进阶

我第一版选的是保留原厂轴。理由很实在:换标准轴需要对 114 个轴位逐一扩孔,手工打磨的精度根本保证不了,用 CNC 加工的话成本又远超项目预算。而保留原厂轴的代价只是手感不能升级,键帽不能换——对“让老键盘活过来”这个目标来说,完全可以接受。

保留原厂轴要做的事是建封装库。方柱轴的焊脚只有两个,位置在轴体中线两侧,间距与标准轴不同,定位柱是方形的。这个封装必须自己画,而且要用实物反复比对——我第一次画的封装,方形定位柱的边长量少了 0.2 毫米,装轴的时候全靠硬压,压完板子有轻微变形。

如果确实想换标准轴,比较现实的路径是做一块转接中层:用一块薄板加工出标准轴孔,固定在原厂外壳的轴位上方,PCB 则按标准轴位设计。这样外壳不用动刀,代价是整体高度增加、外观略有变化。这个方案我在第二版试过,可行但费工,后面章节会提。

3.3 矩阵走线与防鬼键设计

矩阵走线的核心目标是降低扫描串扰。114 个按键挤在一块不大的板子上,行线和列线必然大量交叉,走线不当会出现“按 A 键读出 B 键”或者“同时按三个键读出第四个”的问题。

物理层面的处理:

  • 行线和列线尽量分层走,行线走顶层、列线走底层,交叉处不打过孔。
  • 每条列线末端加一个上拉电阻,阻值 10k 左右。阻值太小增加功耗,太大则边沿变缓。
  • 每条行线的驱动引脚串一个 100 欧左右的小电阻,抑制振铃。

电气层面的重点是防鬼键二极管。每个按键位置串一颗小信号开关二极管,方向统一从行到列(或列到行,取决于扫描极性)。这个二极管的作用是阻断反向电流路径,让多个按键同时按下时不会出现“幽灵键”。

我实测过不装二极管的效果:同时按住三个键以上,开始出现随机误报,尤其在游戏场景同时按方向键加技能键时特别明显。装上以后,全键无冲可以稳定实现。

注意:二极管方向一定要全板统一。混着焊的话,症状非常诡异——部分键正常,部分键按下无反应,还有部分键会把相邻键“带”出来。返工的时候拆 114 颗二极管,那滋味不好受。

3.4 电源路径:锂电、充电与灯珠限流的三角平衡

原厂用的是两节干电池,3V 供电,简单粗暴。移植板要上 RGB 和无线,干电池撑不住,必须换锂电池。这一换,电源设计复杂度直接翻倍。

电池选型上,我用的是一块 2000mAh 的锂聚合物软包,尺寸刚好能塞进原厂电池仓。选软包而不是圆柱电池,是因为软包可以做得薄、形状可定制,能贴合电池仓的异形空间。

充电管理用一颗带路径管理的电源芯片,而不是简单的线性充电 IC。这两者的差别很关键:

  • 简单充电 IC:插上线就开始充电,同时系统从电池取电。结果是边充边用时电池在反复充放,长期下来容量衰减快。
  • 路径管理 IC:插上线后,系统供电直接切到 USB,电池单独走充电回路。这样电池充得干净,系统供电也稳定。

输入口用 Type-C,注意 CC1 和 CC2 各接一个 5.1k 下拉电阻,否则某些充电器不会输出 5V。这个细节吃过亏——第一版忘了接,用某几个充电头完全没反应,还以为是芯片坏了。

灯珠供电是另一个坑。串行灯珠的供电电压和主控的 3.3V 不同,通常要 5V。所以需要一路升压。升压电路的选型要看峰值电流,按最坏情况算:

114 颗灯珠 × 每颗满亮 55mA ≈ 6.3A(理论峰值) 实际限流后按亮度 20/255 计,等效占空比约 8% 114 × 55mA × 8% ≈ 500mA 升压芯片按 1A 峰值选型,留 100% 余量

限流不能只靠硬件,必须固件配合。QMK 里有个全局最大亮度宏,我把它设成 60(满值 255),相当于 23% 上限;无线模式下再进一步压到 25。这个亮度下日常使用完全够看,晚上甚至偏亮。

4. QMK 固件移植的关键动作

硬件通了只是第一步,固件这边才是真正耗时间的地方。QMK 的移植流程本身有官方文档,但文档写的是“标准情况”,移植板遇到的都是非标准情况。

4.1 工程目录结构与配置骨架

QMK 的工程组织方式是按键盘型号分目录,每个目录下放配置文件、矩阵定义、键位图。移植板要新建一个自己的目录,结构大概是这样的:

keyboards/port_board/ ├── config.h ├── info.json ├── rules.mk ├── port_board.c ├── port_board.h └── keymaps/ └── default/ └── keymap.c

config.h里定义硬件相关的宏,这是移植的核心:

#pragma once #define MATRIX_ROWS 8 #define MATRIX_COLS 15 /* 消抖时间,单位毫秒 */ #define DEBOUNCE 4 /* RGB 矩阵 */ #define RGB_MATRIX_LED_COUNT 114 #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 60 #define RGB_DISABLE_WHEN_USB_SUSPENDED /* 无线模式下的额外限制 */ #ifdef WIRELESS_MODE #undef RGB_MATRIX_MAXIMUM_BRIGHTNESS #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 25 #define RGB_MATRIX_TIMEOUT 30000 #endif

info.json里定义引脚映射和物理布局。引脚这块要特别注意,工业 MCU 的引脚命名和 QMK 默认的 STM32 风格不一样,需要自己写映射表:

{ "matrix_pins": { "rows": ["A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7"], "cols": ["B0", "B1", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "B10", "B12", "B13", "B14", "B15", "C13"] }, "diode_direction": "COL2ROW" }

rules.mk控制编译选项,RGB 和无线相关的开关都在这里:

RGB_MATRIX_ENABLE = yes RGB_MATRIX_DRIVER = WS2812 NKRO_ENABLE = yes MOUSEKEY_ENABLE = yes EXTRAKEY_ENABLE = yes LTO_ENABLE = yes

LTO_ENABLE这行别漏,链接时优化能省下不少 Flash 空间。我第一版没开,编译出来 118KB,差一点爆掉 128KB 的 Flash。

4.2 矩阵映射表与左侧宏键区

矩阵映射是整个移植过程中最枯燥、也最容易出错的一步。你要把 114 个物理按键位置,一一对应到 8×15 的逻辑矩阵坐标上,写进键位图里。

我的做法是先做一张对照表:在 PCB 的丝印图上标出每个交叉点的行列编号,再对着外壳的键位顺序,逐个填表。填完以后不急着写代码,先写个小脚本验证有没有重复或者遗漏:

# 校验矩阵映射表是否有重复占用 matrix = {} duplicates = [] layout = [ (0, 0), (0, 1), (0, 2), # 示例:前三个键的位置 ] for idx, pos in enumerate(layout): if pos in matrix: duplicates.append((pos, matrix[pos], idx)) matrix[pos] = idx print(f"已占用交叉点: {len(matrix)}") print(f"重复项: {duplicates}")

左侧那 6 个宏键要特别处理。它们物理位置独立,但在逻辑上属于同一个矩阵,扫出来以后建议单独映射成一组自定义键码,然后在键位图里绑定成常用操作,比如一键静音、一键打开计算器、一键切层。这 6 个键是这把键盘相对普通配列最大的差异化优势,别浪费。

4.3 RGB 矩阵的坐标映射与省电策略

灯珠是串行连接的,数据从第一颗依次往后传。物理上它们按照某个蛇形或者螺旋形走线排布,但逻辑上你要告诉固件“第 N 颗灯对应键盘上的哪个位置”,这就是灯位映射表。

映射表写错的表现很有辨识度:按 A 键,B 键的灯亮了;或者灯效从左上角开始流动,走到一半突然跳到右下角。调试方法是先只点一颗灯——把映射表里其他项全部注释掉,只留第 0 颗,编译烧录,看是哪颗亮,然后依次往后加。114 颗逐个确认很笨,但比瞎猜快。

省电策略这块我做了三层:

  1. 亮度分级:有线模式 60,蓝牙模式 35,2.4G 模式 25。2.4G 发射本身耗电大,灯效必须压到最低。
  2. 超时熄灭:无操作 30 秒后自动关灯,任意按键唤醒。这个超时时间在 QMK 里通过宏配置。
  3. 按需点亮:常规状态只点亮当前层的功能键位,其余熄灭。这个需要自定义效果,但省电极明显。

这三层叠加之后,带灯无线续航从最初的 4 小时上下拉到了 20 小时级别,日常够用。

4.4 三模切换状态机与无线侧协议

模式切换我做成两种方式并行:物理拨钮和组合键。物理拨钮直观,组合键方便。状态机逻辑用一段伪代码说明:

typedef enum { MODE_USB, MODE_BLE_1, MODE_BLE_2, MODE_BLE_3, MODE_2G4 } kb_mode_t; static kb_mode_t current_mode = MODE_USB; bool process_record_user(uint16_t keycode, keyrecord_t *record) { if (!record->event.pressed) return true; switch (keycode) { case KC_MODE_USB: switch_mode(MODE_USB); return false; case KC_MODE_BLE1: switch_mode(MODE_BLE_1); return false; case KC_MODE_2G4: switch_mode(MODE_2G4); return false; default: return true; } } void switch_mode(kb_mode_t target) { if (target == current_mode) return; /* 先断开当前通道,再切硬件,最后初始化新通道 */ wireless_disconnect(); hw_matrix_switch(target == MODE_USB ? OWNER_USB : OWNER_WIRELESS); delay_ms(50); /* 等模拟开关稳定 */ matrix_clear_state(); /* 丢弃切换瞬间的无效扫描 */ if (target != MODE_USB) { wireless_connect(target); } current_mode = target; }

蓝牙侧我用三通道轮流连接的设计,分别对应三台设备。切换通道时会断开当前连接再连新的,重连时间实测在 1.5 到 3 秒之间,取决于目标设备的蓝牙栈。

2.4G 那条通道是自己实现的一套轻量协议。收发两端用同款无线 SoC,一端做键盘主控,一端做 USB 接收器。协议层包含配对握手、跳频、包序号、确认重传。这块内容展开能写一整篇,这里只说两个关键点:

  • 跳频必须做。固定信道在 2.4G 频段上干扰太严重,尤其是周围有路由器和其他无线设备的时候,不跳频会出现规律性的丢包。
  • ACK 机制要轻。键盘是单向数据流为主,重传机制不能太重,否则延迟飙升。我用的是一包数据加一个极短确认帧,超过 3 次重传就丢弃,靠上层重发。

5. 实测数据与问题排查实录

板子焊完、固件刷进去,真正的折磨才开始。这一章把实测数据和遇到过的典型问题整理出来,按“症状—可能原因—排查手法—解决”的格式写,方便直接对照。

5.1 功耗与续航实测

用可编程电源和电流表测了三组数据,都是 3.7V 供电、室温环境:

工作状态平均电流折算续航(2000mAh)
有线模式,灯效全开由 USB 供电不适用
蓝牙模式,灯效关闭2.8mA约 710 小时
蓝牙模式,灯效 35 亮度78mA约 25 小时
2.4G 模式,灯效 25 亮度92mA约 21 小时
2.4G 模式,灯效关闭12mA约 165 小时

这组数字里有个反直觉的地方:蓝牙模式关灯只有 2.8mA,而 2.4G 关灯要 12mA。原因是 2.4G 私有协议的收发器需要持续保持接收窗口,而蓝牙可以进入深度睡眠靠广播唤醒。所以日常办公场景我会建议默认走蓝牙,游戏或者需要低延迟的时候再切 2.4G。

续航测试还暴露了一个问题:电池电压降到 3.4V 附近时,升压电路效率骤降,灯效会突然变暗。这是升压芯片的工作区间限制,解决办法是加一路低压检测,电压低于阈值时主动把灯效关掉,别等它自己撑不住。

5.2 问题速查表

这张表是我这两个月里攒下来的,基本都是反复出现过的问题:

症状可能原因排查手法解决
部分按键完全无反应二极管方向反了万用表二极管档测正反向压降拆下重焊
按一个键,相邻键也被触发矩阵走线短路或列线上拉缺失断电测相邻列线是否导通补上拉或割断短路
开机瞬间乱发键上电时矩阵浮空观察是否只在通电瞬间出现固件加初始化丢弃逻辑
灯效颜色错乱灯珠型号色序不匹配单点测试确认色序改驱动配置的色序参数
第一颗灯不亮,后面正常数据线极性或电平不匹配示波器看第一颗输入波形加电平转换或串限流电阻
无线模式偶尔连击消抖时间不足缩短扫描间隔对比消抖从 3ms 提到 5ms
插 USB 后无线仍在发键仲裁延时不足插拔观察切换时序仲裁延时从 50ms 加到 200ms
充电时板子发烫充电电流过大测充电电流和环境温度从 1A 降到 500mA
蓝牙配对后频繁掉线天线附近有金属遮挡看天线净空区是否有铺铜天线区挖空并远离电池
长时间不用后无法开机电池过放保护触发测电池电压换带欠压保护的电源芯片

5.3 几条不太会写进文档的经验

第一条是关于调试顺序的。正确顺序是:电源(能不能上电、电压对不对)→ 时钟(烧个闪灯程序看跑不跑)→ USB(能不能枚举)→ 矩阵(能不能读到按键)→ 灯效(能不能点亮)→ 无线(能不能连上)。跳过任何一步直接做后面的,出问题时会完全找不到方向。我第一块板子就是电源还没稳定就开始调 USB,折腾了一天发现是 LDO 选错了,压差不够。

第二条是关于飞线板的用法。正式 PCB 打样之前,一定要用洞洞板或者飞线板把最小系统跑通。我知道这听起来很啰嗦,但移植板涉及的子系统太多,任何一个子系统没验证就上正式板,返工成本都是几百块加一周时间。我后来的习惯是,每个新模块都先在飞线板上验证一遍,通过了才敢往正式板上放。

第三条是关于固件版本管理。QMK 是活跃开发的项目,主线的更新频率不低,有时候一个新版本会改掉你依赖的某个接口。我的做法是给自己项目的固件锁一个固定的上游版本,用分支管理,升级前先在飞线板上跑一遍全功能测试。直接跟着主线走的代价,是某天早上起来发现编译不过了,而当天正好要交东西。

第四条,也是我觉得最重要的一条:别指望一次成功。这个项目的第二版比第一版改动超过 40%,第三版又改了不少。移植板这种活,本质上是把一个成熟产品的设计反向拆解再重组,中途发现原设计里有你没考虑到的东西,太正常了。接受这个前提,心态会好很多,反而更容易把每一版都做扎实。

最后再分享一个小技巧:板子做完别急着封壳,先裸板用两周。这两周里你会陆续发现各种零碎问题——某个键手感怪、某条通道切换慢、灯效在特定角度刺眼——这些问题在封壳之后修复成本翻倍,裸板状态下改起来却很快。我的第三版就是裸板用了三周才封的,期间改了四处固件和三处硬件补丁,如果早早封壳,这七处改动大概率会被我忍下来,然后一直别扭着用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询