You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用QMK实现键盘旋钮切换八度/移调?代码调试求助

QMK键盘旋钮实现MIDI八度切换/移调功能的修复方案

我希望通过转动键盘旋钮实现MIDI八度切换或移调功能,但现有代码无法正常触发对应功能,代码如下:

typedef enum {
    ENCODER_MODE_OCTAVE,
    ENCODER_MODE_TRANSPOSE,
} encoder_mode_t;

encoder_mode_t encoder_mode = ENCODER_MODE_OCTAVE;

bool encoder_update_user(uint8_t index, bool clockwise) {
    if (layer_state_is(MIDI_BASE)) {
        if (clockwise) {
            if (encoder_mode == ENCODER_MODE_OCTAVE) {
                tap_code16(MI_OCTU);
            } else {
                tap_code16(MI_TRSU);
            }
        } else {
            if (encoder_mode == ENCODER_MODE_OCTAVE) {
                tap_code16(MI_OCTD);
            } else {
                tap_code16(MI_TRSD);
            }
        }
    }
    return false;
}

当前问题:

  • 转动旋钮时有反应,但未触发MI_OCTx或MI_TRSx对应的MIDI功能
  • 文档说明tap_code16(<kc>)仅支持KC_x类普通键码,对此存疑
  • 在keymap中直接使用MI_OCTx或MI_TRSx是有效的
  • 可通过process_record_user修改MIDI音符值实现,但希望有更简便的方案

修复方案

tap_code16确实仅适用于普通键盘键码,MI_OCTx、MI_TRSx属于QMK MIDI模块的专用键码,这类键码的处理逻辑由MIDI模块在process_record_user中实现,直接调用tap_code16无法触发对应的MIDI操作。最简便的方式是直接调用QMK MIDI模块提供的API函数:

#include "midi.h"  // 必须包含MIDI头文件

typedef enum {
    ENCODER_MODE_OCTAVE,
    ENCODER_MODE_TRANSPOSE,
} encoder_mode_t;

encoder_mode_t encoder_mode = ENCODER_MODE_OCTAVE;

bool encoder_update_user(uint8_t index, bool clockwise) {
    if (layer_state_is(MIDI_BASE)) {
        if (clockwise) {
            if (encoder_mode == ENCODER_MODE_OCTAVE) {
                midi_increase_octave();  // 直接调用八度提升API
            } else {
                midi_increase_transpose();  // 直接调用移调提升API
            }
        } else {
            if (encoder_mode == ENCODER_MODE_OCTAVE) {
                midi_decrease_octave();  // 直接调用八度降低API
            } else {
                midi_decrease_transpose();  // 直接调用移调降低API
            }
        }
    }
    return false;
}

替代方案(模拟键码触发)

如果坚持要通过键码模拟的方式实现,可以手动调用process_record_user来模拟按键按下/释放的过程,效果和keymap中使用键码一致:

typedef enum {
    ENCODER_MODE_OCTAVE,
    ENCODER_MODE_TRANSPOSE,
} encoder_mode_t;

encoder_mode_t encoder_mode = ENCODER_MODE_OCTAVE;

bool encoder_update_user(uint8_t index, bool clockwise) {
    if (layer_state_is(MIDI_BASE)) {
        keyrecord_t record = {
            .event = {
                .key = (keypos_t){.row = 0, .col = 0},  // 位置参数不影响,可随意填写
                .pressed = true
            }
        };
        uint16_t target_code = 0;

        // 确定要触发的键码
        if (clockwise) {
            target_code = (encoder_mode == ENCODER_MODE_OCTAVE) ? MI_OCTU : MI_TRSU;
        } else {
            target_code = (encoder_mode == ENCODER_MODE_OCTAVE) ? MI_OCTD : MI_TRSD;
        }

        // 模拟按键按下和释放
        process_record_user(target_code, &record);
        record.event.pressed = false;
        process_record_user(target_code, &record);
    }
    return false;
}

内容的提问来源于stack exchange,提问作者Max May

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 13:47:40