固件嵌入式智能硬件蓝牙【免费下载链接】zmkZMK Firmware Repository项目地址https://gitcode.com/gh_mirrors/zm/zmk点击查看免费下载本文以 ZMK 固件仓库中的电源管理行为文档docs/docs/keymaps/behaviors/power.md为核心系统讲解ext_power行为的工作原理、命令定义、keymap 绑定方法、状态持久化机制以及它在分体键盘上的全局生效特性。读完本文你将能够在自己的 keymap 中正确绑定启用、禁用、切换外部电源的命令并理解底层驱动是如何通过 GPIO 与设置子系统实现省电 断电记忆的完整链路。概述外部电源控制行为解决什么问题ZMK 的**外部电源控制行为External Power Control**允许通过 keymap 按键启用或禁用开发板上的VCC 电源输出从而节省电量。许多外设尤其是部分 LED即使在关闭状态下依然会持续耗电。对于这种情况部分主控板提供了完全切断外部电源的能力外部电源行为就是用来控制该电源输出的。它最适合的场景包括使用 RGB 灯带或状态 LED 的分体键盘在闲置或夜间希望彻底断电外接显示器OLED等外设不需要常开时在同一个按键位上切换供电与断电两种状态。目前官方文档明确列出支持该特性的板子有两款nRFMicronice!nano从仓库源码看这两款板子的 Devicetree overlay 中都定义了EXT_POWER节点例如 nice!nano 的 app/boards/nicekeyboards/nice_nano/nice_nano_nrf52840_zmk_2_0_0.overlay 与 nRFMicro 的 app/module/boards/joric/nrfmicro/nrfmicro_nrf52840_1_1_0.overlay 中均包含EXT_POWER { compatible zmk,ext-power-generic; control-gpios gpio0 13 GPIO_ACTIVE_HIGH; init-delay-ms 50; };control-gpios指定了用于开启/关闭外部电源的 GPIOinit-delay-ms为驱动初始化后的延迟毫秒数。命令定义dt-bindings/zmk/ext_power.h外部电源控制命令的宏定义位于头文件 app/include/dt-bindings/zmk/ext_power.h。要在 keymap 中使用这些命令需要在 keymap 文件顶部加入#include dt-bindings/zmk/ext_power.h例如仓库中 lily58 的 keymap app/boards/shields/lily58/lily58.keymap 就在文件头部同时引入了behaviors.dtsi和dt-bindings/zmk/ext_power.h随后在绑定列表中直接使用ext_power EP_ON等写法。引入该头文件后就可以引用其中定义的动作例如EXT_POWER_OFF_CMD。各宏定义及别名如下DefineActionAliasEXT_POWER_OFF_CMDDisable the external power.EP_OFFEXT_POWER_ON_CMDEnable the external power.EP_ONEXT_POWER_TOGGLE_CMDToggle the external power.EP_TOG在源码中这些宏被定义为一组连续的整数值app/include/dt-bindings/zmk/ext_power.h#define EXT_POWER_OFF_CMD 0 #define EXT_POWER_ON_CMD 1 #define EXT_POWER_TOGGLE_CMD 2 #define EP_ON EXT_POWER_ON_CMD #define EP_OFF EXT_POWER_OFF_CMD #define EP_TOG EXT_POWER_TOGGLE_CMD也就是说EP_ON、EP_OFF、EP_TOG与EXT_POWER_ON_CMD、EXT_POWER_OFF_CMD、EXT_POWER_TOGGLE_CMD是完全等价的两个名字keymap 中既可以写长名字也可以写短别名。行为绑定ext_powerext_power行为的绑定方式如下Referenceext_powerParameter#1命令Command例如EP_ON该行为的 Devicetree 定义位于 app/dts/behaviors/ext_power.dtsi并被 app/dts/behaviors.dtsi 统一引入ext_power: extpower { compatible zmk,behavior-ext-power; #binding-cells 1; display-name External Power; };其中#binding-cells 1表示该行为在 keymap 中需要且仅需要一个绑定参数这个参数就是上表中的命令0/1/2。行为节点名被刻意设计为不超过 8 个字符的extpower以便在分体键盘外设端也能被引用。绑定到按键的标准写法ext_power EP_ON也可以使用完整命令名ext_power EXT_POWER_ON_CMD三种命令的完整示例1. 行为绑定启用外部电源ext_power EP_ON2. 行为绑定禁用外部电源ext_power EP_OFF3. 行为绑定切换外部电源ext_power EP_TOG仓库中 lily58 的 keymapapp/boards/shields/lily58/lily58.keymap提供了一个同时使用三种命令的完整实例trans ext_power EP_ON ext_power EP_OFF ext_power EP_TOG trans ...即将外部电源开、关、切换分别绑定在相邻的三个按键位上便于实时控制供电状态。底层实现按下时如何执行命令ext_power行为的 C 实现位于 app/src/behaviors/behavior_ext_power.c。它在按下回调on_keymap_binding_pressed中通过device_get_binding(EXT_POWER)获取外部电源设备然后根据参数执行对应操作app/src/behaviors/behavior_ext_power.cswitch (binding-param1) { case EXT_POWER_OFF_CMD: return ext_power_disable(ext_power); case EXT_POWER_ON_CMD: return ext_power_enable(ext_power); case EXT_POWER_TOGGLE_CMD: if (ext_power_get(ext_power) 0) return ext_power_disable(ext_power); else return ext_power_enable(ext_power); default: LOG_ERR(Unknown ext_power command: %d, binding-param1); }需要特别注意的是EXT_POWER_TOGGLE_CMD是状态相关命令切换目标取决于当前电源状态。ZMK 通过binding_convert_central_state_dependent_params回调app/src/behaviors/behavior_ext_power.c在触发时先把 TOGGLE 命令换算成明确的 ON 或 OFF 命令if (binding-param1 EXT_POWER_TOGGLE_CMD) { binding-param1 ext_power_get(ext_power) 0 ? EXT_POWER_OFF_CMD : EXT_POWER_ON_CMD; }同时行为在释放回调on_keymap_binding_released中返回ZMK_BEHAVIOR_OPAQUEapp/src/behaviors/behavior_ext_power.c表示该行为只在按下时生效释放时不产生额外动作——因此它适合绑定在普通按键位按下即执行、松开无副作用。这些ext_power_enable/ext_power_disable/ext_power_get调用通过驱动 APIapp/include/drivers/ext_power.h分发到具体驱动实现enable将控制 GPIO 置为有效电平disable置为无效电平get返回当前开关状态1 表示开启0 表示关闭。状态持久化断电与重刷固件后仍能记住开关状态:::note[外部电源状态持久化] 由ext_power行为设置的开关状态会被保存到闪存存储即 ZMK 的 settings 子系统因此在重启和重新刷写固件后仍然保持。不过为了避免对闪存造成不必要的磨损状态只会在CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE毫秒之后才被真正写入。 :::具体实现位于 app/src/ext_power_generic.c每次enable/disable都会把新状态写进ext_power/state/设备名设置项并使用一个可延迟工作项做防抖int ext_power_save_state(void) { int ret k_work_reschedule(ext_power_save_work, K_MSEC(CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE)); return MIN(ret, 0); }当 settings 子系统提交时驱动会根据已保存的状态恢复 GPIO 电平app/src/ext_power_generic.c如果从未保存过任何状态首次启动则默认启用外部电源static int ext_power_settings_commit() { ... if (!data-settings_init) { >enum behavior_locality { BEHAVIOR_LOCALITY_CENTRAL, // 仅在 central 处理 BEHAVIOR_LOCALITY_EVENT_SOURCE, // 仅在触发来源侧处理 BEHAVIOR_LOCALITY_GLOBAL // 全局生效 };ext_power行为的驱动 API 将.locality设置为BEHAVIOR_LOCALITY_GLOBALapp/src/behaviors/behavior_ext_power.c。在 central 侧的分发逻辑中app/src/behavior.c全局行为会先向所有已连接的外设广播执行再在本地执行case BEHAVIOR_LOCALITY_GLOBAL: for (int i 0; i ZMK_SPLIT_CENTRAL_PERIPHERAL_COUNT; i) { zmk_split_central_invoke_behavior(i, binding, event, pressed); } return invoke_locally(binding, event, pressed);这也解释了文档中全局生效的含义无论按键绑在外设侧还是 central 侧外部电源的开关都会同步作用于整把键盘非常适合分体键盘统一控制 LED/外设供电。关于 locality 机制的完整讨论可参考分体键盘特性文档中的 Global Locality Behaviors 一节其中同样把 power management behaviors 列为全局行为之一。实践要点速查在 keymap 顶部#include dt-bindings/zmk/ext_power.h即可使用EP_ON/EP_OFF/EP_TOG使用ext_power行为时参数 #1 必填值为上述三种命令之一行为只在按下时执行释放无副作用适合直接绑定普通按键开关状态通过 ZMK settings 子系统持久化ext_power/state/设备名默认在变更后CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE默认 60000 ms写入闪存分体键盘上该行为是全局行为一次触发同时作用于 central 与 peripheral仅当板级 Devicetree 中存在EXT_POWER节点compatible zmk,ext-power-generic时该行为才真正可用官方支持的板子为 nRFMicro 与 nice!nano配置驱动属性可参考电源管理配置文档中的 External Power Control 一节。赞分享固件嵌入式智能硬件蓝牙【免费下载链接】zmkZMK Firmware Repository项目地址https://gitcode.com/gh_mirrors/zm/zmk点击查看免费下载相关推荐ZMK 电源管理配置完全指南低功耗状态、外部电源控制与软关机唤醒ZMK 电源管理配置完全指南低功耗状态、外部电源控制与软关机唤醒 本篇指南以 ZMK 固件仓库的 电源管理配置文档 https://link.gitcode.固件嵌入式智能硬件蓝牙Electron Fiddle电源管理控制应用电源使用Electron Fiddle电源管理控制应用电源使用 为什么需要电源管理 在开发桌面应用时电源管理常被忽视却至关重要。想象以下场景视频会议应用在电脑休桌面应用开发工具代码编辑器ZMK 固件状态报告第三期键位码体系重构、外部电源控制与输出选择的技术演进ZMK 固件状态报告第三期键位码体系重构、外部电源控制与输出选择的技术演进 本期内容以 ZMK 官方《State Of The Firmware 3》博客固件嵌入式智能硬件蓝牙上一篇在 KernelSU 上跑通 LSPosedZygiskNext 完整部署避坑指南下一篇Docker-Mailserver反垃圾策略构建多层次防御体系的终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考