news 2026/9/19 22:36:49

QMK 开源静电电容数字键盘 EC 23U:构建、刷写与源码级解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
QMK 开源静电电容数字键盘 EC 23U:构建、刷写与源码级解析

QMK 开源静电电容数字键盘 EC 23U:构建、刷写与源码级解析

【免费下载链接】qmk_firmwareOpen-source keyboard firmware for Atmel AVR and Arm USB families项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmware

本篇技术指南围绕 QMK 固件仓库中 keyboards/cipulot/ec_23u 的 EC 23U 数字键盘展开,系统讲解这款开源静电电容(Electrostatic Capacitive,简称 EC)数字键盘的硬件背景、构建与刷写流程、进入 Bootloader 的两种方式,并结合仓库内配置与驱动源码剖析其电容矩阵扫描、自适应触发(APC)与快速触发(Rapid Trigger)等核心实现原理。读完本文,你将能够独立完成 EC 23U 的固件编译、烧录与按键阈值调校,并理解 QMK 自定义矩阵在 EC 键盘上的落地方式。

一、项目概览:什么是 EC 23U

EC 23U 是 cipulot 维护的一款开源静电电容数字键盘 PCB(Open source numpad Electrostatic Capacitive PCB)。与常规机械键盘的物理触点导通不同,EC 键盘通过测量按键电容变化来判定按下与释放,其按键手感与触发方式具有明显差异,因此固件侧的处理逻辑也完全不同。

在 QMK 仓库中,EC 23U 的完整工程位于 keyboards/cipulot/ec_23u,其目录结构如下:

keyboards/cipulot/ec_23u/ ├── keymaps/ │ └── default/ │ └── keymap.c # 默认键位 ├── config.h # 矩阵、AMUX、APC 阈值等配置 ├── halconf.h # ChibiOS HAL 配置 ├── keyboard.json # 键盘描述与构建选项 ├── mcuconf.h # MCU 配置 ├── post_rules.mk # 引入 cipulot 公共 EC 驱动 ├── readme.md # 项目说明 └── rules.mk # 编译优化选项

基础信息(来源 keyboard.json):

项目
键盘名称EC 23U
制造商 / 维护者Cipulot
主控STM32F401
Bootloaderstm32-dfu
USB VID / PID0x6369 / 0x6B95
二极管方向COL2ROW
矩阵规模4 行 × 6 列(见 config.h)
布局LAYOUT_all、LAYOUT_numpad_6x4

此外,keyboard.json 开启了如下功能:NKRO、鼠标键(mousekey)、多媒体扩展键(extrakey)、控制台(console)、RGB 灯光(rgblight,21 颗 LED,数据引脚 B5),以及数字锁定指示灯(num_lock,引脚 B14);构建层面启用了 LTO 链接时优化,rules.mk 中指定OPT = 2优化级别。

二、构建环境与固件编译

与 QMK 其他键盘一致,EC 23U 使用标准 QMK 构建流程。首先需要完成 QMK 构建环境配置(包括工具链、编译依赖与 QMK CLI),然后即可使用make命令编译固件。

在仓库根目录下执行以下命令即可构建默认键位固件:

make cipulot/ec_23u:default

其中cipulot/ec_23u为目标键盘路径,default为键位名(对应 keymaps/default/keymap.c)。

编译产物为可直接刷写的固件文件,之后通过 DFU 方式烧录到板载 STM32F401:

make cipulot/ec_23u:default:flash

:flash目标会先编译,再调用对应的刷写工具(stm32-dfu)将固件写入主控。关于构建工具安装与 make 指令的完整说明,可参考仓库文档 docs/getting_started_make_guide.md 与 docs/newbs.md;对 QMK 完全陌生的用户,建议先阅读 docs/newbs_getting_started.md 完成环境搭建。

注意:EC 23U 属于 EC 键盘,其矩阵依赖模拟量采样而非 GPIO 扫描,因此普通机械键盘的构建方式仅覆盖了 CLI 层面,固件内部的处理逻辑完全不同(详见下文源码解析)。

默认键位速览

默认键位位于 keymaps/default/keymap.c,采用双层布局:

  • 第 0 层(主层):完整的数字键盘功能,包括KC_NUMKC_PSLS(/)、KC_PAST(*)、KC_PMNS(-)、KC_PPLS(+)、KC_PENTKC_P0~KC_P9KC_PDOT,以及KC_ESCKC_TABKC_BSPC和进入功能层的MO(1)
  • 第 1 层(功能层):通过MO(1)按住触发,包含 RGB 控制(UG_TOGG开关、UG_VALD/UG_VALU亮度调节)、NKRO 切换NK_TOGG,以及关键的系统复位键QK_BOOT——按下它即可让键盘进入 DFU Bootloader,无需拆壳短接。
[1] = LAYOUT_all( UG_TOGG, UG_VALD, UG_VALU, _______, _______, _______, _______, NK_TOGG, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, QK_BOOT, _______)

三、进入 Bootloader 的两种方式

EC 23U 支持两种进入 Bootloader 的方式(见 readme.md):

  1. 物理复位(Physical reset):短接 PCB 顶部的暴露焊盘(Long short the exposed pads on the top of the PCB)。这是最可靠的硬性方式,适用于固件异常、键位未映射QK_BOOT等场景。
  2. 键位触发(Keycode in layout):按下布局中映射到QK_BOOT的按键。默认键位的第 1 层已预置QK_BOOT(位于右下区域),可在不拆机的情况下进入 DFU 模式。

两种方式最终都将使 STM32F401 进入 stm32-dfu 引导模式,此时即可通过make cipulot/ec_23u:default:flash或 DFU 工具刷写固件。

四、源码级解析:EC 键盘的电容矩阵驱动

EC 23U 的固件价值不仅在于数字键盘功能本身,更在于其完整的 EC 电容矩阵驱动实现。这类键盘不使用普通二极管矩阵,而是通过模拟多路复用器(AMUX)逐列选通、对电容充放电并采样 ADC 电压值来判断按键状态。

4.1 驱动装配方式

post_rules.mk 引入了 cipulot 全系列 EC 键盘的公共驱动:

include keyboards/cipulot/common/common_cipulot.mk

而 common_cipulot.mk 完成了关键装配:

CUSTOM_MATRIX = lite ANALOG_DRIVER_REQUIRED = yes VPATH += keyboards/cipulot/common SRC += matrix.c ec_board.c ec_switch_matrix.c
  • CUSTOM_MATRIX = lite:声明使用自定义矩阵实现,替代默认 GPIO 矩阵扫描;
  • ANALOG_DRIVER_REQUIRED = yes:启用 ADC 模拟量驱动,这是电容采样所必需的;
  • SRC追加的matrix.cec_board.cec_switch_matrix.c分别承担自定义矩阵入口、板级引脚初始化和 EC 采样算法。

4.2 自定义矩阵初始化与扫描

matrix.c 是 QMK 自定义矩阵的接入点:

void matrix_init_custom(void) { ec_init(); // 初始化 EC 相关引脚与 AMUX ec_noise_floor(); // 启动时采样噪声底 } bool matrix_scan_custom(matrix_row_t current_matrix[]) { return ec_matrix_scan(current_matrix); }

两个细节值得注意:

  • 启动噪声底采样:开机时会调用ec_noise_floor()采集每个键位的环境噪声水平,作为后续阈值判定的基准,避免不同环境下误触发。
  • Bootmagic 被覆盖:同文件中bootmagic_scan()被重写为空实现,注释明确指出这是为了避免与 EC 矩阵逻辑冲突(EC 键盘的模拟量采集与 Bootmagic 的启动时按键检测机制不兼容)。因此该键盘在 keyboard.json 中也将bootmagic功能关闭。

4.3 矩阵与模拟前端配置

config.h 定义了 EC 23U 的完整硬件映射:

#define MATRIX_ROWS 4 #define MATRIX_COLS 6 #define MATRIX_ROW_PINS \ { B13, B12, A7, B0 } #define AMUX_COUNT 1 #define AMUX_MAX_COLS_COUNT 6 #define AMUX_EN_PINS \ { C15 } #define AMUX_SEL_PINS \ { C14, C13, B6 } #define AMUX_COL_CHANNELS_SIZES \ { 6 } #define AMUX_0_COL_CHANNELS \ { 4, 6, 3, 2, 0, 1 } #define DISCHARGE_PIN A3 #define ANALOG_PORT A2
  • 行引脚(ROW)直接由 MCU 引脚驱动,用于对列电容充电;
  • 列信号通过 1 片模拟多路复用器(AMUX)选通,AMUX_SEL_PINS(C14、C13、B6)为通道选择线,AMUX_EN_PINS(C15)为使能引脚;
  • AMUX_0_COL_CHANNELS = { 4, 6, 3, 2, 0, 1 }表示 6 个物理列在 AMUX 上的通道编号顺序(注意并非递增排列,PCB 走线决定了这种映射);
  • DISCHARGE_PIN(A3)用于放电,ANALOG_PORT(A2)用于 ADC 采样。

典型的 EC 键位采样流程(对应ec_switch_matrix.h中声明的discharge_capacitor()charge_capacitor()select_amux_channel()等函数)为:先放电 → 选中目标列 → 对该列充电 → 经 ADC 读取电压 → 依据阈值判定该键是否按下。

4.4 触发模式与 APC / Rapid Trigger 配置

EC 键盘的灵魂在于触发判定。根据 ec_switch_matrix.h 中的配置结构体,EC 23U 支持三种触发模式(actuation_mode):

模式含义
0整板统一的自适应触发(APC),按固定阈值判定按下/释放
1快速触发(Rapid Trigger),基于整板统一的触发点做增量判定
2快速触发,基于按键静止点(resting point)做增量判定

config.h中的默认阈值如下:

#define DEFAULT_ACTUATION_MODE 0 #define DEFAULT_MODE_0_ACTUATION_LEVEL 550 // 模式 0 按下阈值 #define DEFAULT_MODE_0_RELEASE_LEVEL 500 // 模式 0 释放阈值 #define DEFAULT_MODE_1_INITIAL_DEADZONE_OFFSET DEFAULT_MODE_0_ACTUATION_LEVEL #define DEFAULT_MODE_1_ACTUATION_OFFSET 70 // 模式 1/2 按下偏移 #define DEFAULT_MODE_1_RELEASE_OFFSET 70 // 模式 1/2 释放偏移 #define DEFAULT_EXTREMUM 1023 #define EXPECTED_NOISE_FLOOR 0 #define NOISE_FLOOR_THRESHOLD 50 #define BOTTOMING_CALIBRATION_THRESHOLD 100 #define DEFAULT_NOISE_FLOOR_SAMPLING_COUNT 30 #define DEFAULT_BOTTOMING_READING 1023 #define DEFAULT_CALIBRATION_STARTER true #define DISCHARGE_TIME 10

关键设计点:

  • 模式 0(APC):ADC 读数低于actuation(550)视为按下,回升超过release(500)视为释放,形成回差(hysteresis)防止抖动。
  • 模式 1/2(Rapid Trigger):不依赖绝对阈值,而是以触发点为基准计算偏移(actuation_offset/release_offset,范围 1–255),实现快速连打时更灵敏的响应;DEFAULT_EXTREMUM(1023)为 ADC 满量程参考值。
  • 按键触底校准bottoming_calibration相关字段支持逐键记录触底读数(bottoming_reading),用于将阈值按每颗键的实际行程重标定(rescale()函数),从而在按键个体差异下保持一致手感。

由于运行时配置需要持久化,config.h将键盘级 EEPROM 数据区大小设为:

#define EECONFIG_KB_DATA_SIZE 57

而 ec_switch_matrix.h 通过编译期断言强制eeprom_ec_config_t结构体大小与之一致:

_Static_assert(sizeof(eeprom_ec_config_t) == EECONFIG_KB_DATA_SIZE, "Mismatch in keyboard EECONFIG stored data");

这保证了在键位固件升级、重新刷写后,用户的触发阈值等校准数据仍能可靠地保存在片内 EEPROM 中。若使用 VIA(VIA_ENABLE),common_cipulot.mk 还会额外编译via_ec.c,让用户可以通过 VIA 图形界面直接调整每颗键的触发阈值。

五、扩展与后续学习

EC 23U 并非 cipulot 唯一的 EC 键盘。在 keyboards/cipulot 目录下还有大量同类产品(如ec_60ec_65xec_980cec_tkl等),它们共享common_cipulot.mk中的同一套 EC 驱动,仅通过各自的config.h区分矩阵规模、AMUX 通道与默认阈值,非常适合对照阅读以理解 EC 键盘驱动的通用设计。

若希望进一步深入,建议按以下路径学习:

  1. keyboards/cipulot/common/ec_switch_matrix.h:理解三种触发模式与阈值结构体;
  2. keyboards/cipulot/common/ec_switch_matrix.c:阅读充放电、ADC 采样与状态机判定实现;
  3. keyboards/cipulot/common/ec_board.c:了解行/列引脚与 AMUX 的板级初始化;
  4. docs/features 下的 QMK 功能文档,了解 NKRO、RGB、自定义矩阵等特性的标准用法。

至此,你已掌握 EC 23U 从编译刷写到电容触发原理的完整链路:make cipulot/ec_23u:default:flash一条命令完成构建与烧录,短接焊盘或QK_BOOT键进入 DFU,APC 与 Rapid Trigger 阈值则可在源码中按需调校,并通过 EEPROM 持久化保存。

【免费下载链接】qmk_firmwareOpen-source keyboard firmware for Atmel AVR and Arm USB families项目地址: https://gitcode.com/GitHub_Trending/qm/qmk_firmware

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 22:35:59

CSS backdrop-filter 实现毛玻璃效果:原理、实战与性能优化

不是,这几年网页设计里"毛玻璃"这个词出现的频率高得吓人——从苹果的系统界面到各种新品发布会页面,再到你随手打开的设计灵感站,几乎到处都能看到那种半透明、背景模糊、边缘还泛着微光的卡片效果。以前想在网页上复刻这种质感,得靠背景图裁切、伪元素复制、甚至手…

作者头像 李华
网站建设 2026/9/19 22:35:14

Spark Join 策略深度对比:优化大数据查询性能的关键

一、Spark Join 策略概述Spark作为大数据处理的利器,Join操作是其最核心也最常见的操作之一。在面对海量数据的Join场景下,选择合适的Join策略对查询性能有着决定性影响。Spark SQL中的Join策略主要分为三类:Broadcast Hash Join(…

作者头像 李华
网站建设 2026/9/19 22:34:21

移动APP测试实战:从Genymotion环境到adb性能与稳定性命令详解

简介:面向移动端测试工程师的APP测试精编合集,内容覆盖从环境搭建到性能分析的完整知识链。资料为PDF文档,共1个文件,包体仅1020KB,便于碎片时间学习与移动端查阅;目前已有230人浏览学习,适合初…

作者头像 李华
网站建设 2026/9/19 22:34:18

LibreChat自托管AI聊天平台:多模型统一接入与Docker部署全攻略

1. LibreChat是什么,以及它解决的到底是什么问题先抛一个场景:你是不是也把 ChatGPT、Claude、Gemini 这些对话页面都开着,哪个好用切哪个?结果就是浏览器标签页开了一排,来回切换,历史记录散落各处&#x…

作者头像 李华
网站建设 2026/9/19 22:33:20

EffectorP3.0实战:从全蛋白组到候选效应子的高效筛选链路

拿到一个病原菌的基因组或转录组,注释出上万条蛋白序列,接下来最重要的是从中把“真正参与致病”的候选效应子捞出来。这一步纯靠实验验证会把人累死,所以业内通行的做法是先跑一遍EffectorP3.0做计算预筛,再结合信号肽、半胱氨酸…

作者头像 李华