200字
基于WCH CH583蓝牙芯片的手机远程控制键盘/鼠标通用方案
2026-02-24
2026-02-24

基于WCH CH583蓝牙芯片的手机远程控制键盘/鼠标通用方案

前言

有没有想过,用手机就能远程操控电脑的键盘和鼠标?

这个需求其实很常见——远程演示PPT、躺在床上操控HTPC、或者给嵌入式设备做无线调试输入。市面上的方案要么贵,要么不够灵活。今天分享一个基于WCH CH583芯片的通用方案,成本低、实现简洁,核心思路是:

手机 → BLE → CH583 → USB HID → 电脑

手机端发送键鼠指令,CH583通过蓝牙接收后,转换为标准USB HID协议输出给电脑。电脑端零驱动,即插即用。


为什么选CH583?

屏幕截图 2026-02-24 232257.png

在做芯片选型的时候,对比了几款常见的BLE SoC:

特性CH583ESP32-C3nRF52832
内核RISC-V 32位RISC-V 32位ARM Cortex-M4
BLE版本5.35.05.0
USB2路(Host+Device)无原生USB无原生USB
Flash512KB4MB(外挂)512KB
SRAM32KB400KB64KB
单价(散片参考)~3元~8元~15元
触摸按键14路

选CH583的核心原因就三个字:便宜、够用、有USB

很多BLE芯片不带原生USB Device控制器,要模拟HID设备还得外挂CH340之类的桥接芯片,增加成本和复杂度。CH583自带2路全速USB,一路做Device输出HID,另一路做Host都行,方案天然简洁。

BLE 5.3的协议栈也是WCH官方提供的,省去了自己移植的麻烦。


系统架构

整体方案分三层:

┌─────────────┐     BLE 5.3      ┌─────────────┐    USB HID     ┌──────────┐
│   手机APP    │ ──────────────→ │   CH583     │ ────────────→ │   电脑    │
│ (Android/iOS)│   GATT通信      │  BLE + USB  │  键盘/鼠标     │ (免驱动)  │
└─────────────┘                  └─────────────┘               └──────────┘

数据流很清晰:

  1. 手机APP采集用户的触摸/按键操作,封装成自定义协议包
  2. 通过BLE GATT Characteristic写入CH583
  3. CH583解析协议包,转换为标准USB HID Report
  4. 电脑识别为标准键盘/鼠标设备,无需安装任何驱动

硬件设计

最小系统非常简单,CH583本身集成度很高,外围器件极少。

核心电路

                    CH583 最小系统
                 ┌──────────────────┐
                 │                  │
    32MHz晶振 ──→│ XI/XO            │
                 │                  │
    32.768K晶振 →│ X32KI/X32KO      │──→ USB D+/D- → 电脑USB口
                 │                  │
    天线匹配网络 ←│ RF               │
                 │                  │
    3.3V LDO ──→│ VCC              │
                 │                  │
                 │ GPIO (可选)      │──→ 状态LED / 物理按键
                 └──────────────────┘

BOM清单(核心部分)

器件型号/规格数量说明
MCUCH583M/F1主控
晶振32MHz1主时钟
晶振32.768KHz1RTC/低功耗时钟
天线2.4G陶瓷天线或PCB天线1BLE射频
匹配网络电感电容若干-参考官方参考设计
LDO3.3V1供电
USB座Type-C1连接电脑
LED06031-2状态指示

整板BOM成本可以控制在10元以内(不含PCB),非常适合DIY和小批量。


软件架构

固件端(CH583)

CH583的固件主要做两件事:BLE通信 + USB HID输出。

CH583 固件架构
├── BLE层
│   ├── GAP:广播、连接管理
│   ├── GATT Server
│   │   ├── HID Control Service(自定义)
│   │   │   ├── Keyboard Characteristic(Write)
│   │   │   ├── Mouse Characteristic(Write)
│   │   │   └── Config Characteristic(Read/Write)
│   │   └── Device Info Service
│   └── 协议栈回调处理
├── USB层
│   ├── USB Device初始化
│   ├── HID Keyboard Report Descriptor
│   ├── HID Mouse Report Descriptor
│   └── Report发送逻辑
├── 协议解析层
│   ├── BLE数据包解析
│   ├── 键盘指令 → USB Keyboard Report
│   └── 鼠标指令 → USB Mouse Report
└── 系统层
    ├── 低功耗管理
    ├── 状态LED控制
    └── 看门狗

BLE自定义协议

为了通用性和扩展性,定义一个简洁的通信协议:

// 协议包格式(最大20字节,适配BLE MTU)
typedef struct {
    uint8_t type;       // 0x01=键盘, 0x02=鼠标, 0x03=多媒体, 0xFF=配置
    uint8_t length;     // 数据长度
    uint8_t data[];     // 变长数据
} __attribute__((packed)) ble_hid_packet_t;

// 键盘数据格式(兼容USB HID标准)
typedef struct {
    uint8_t modifier;   // 修饰键(Ctrl/Shift/Alt/GUI)
    uint8_t reserved;
    uint8_t keycode[6]; // 最多6个同时按键
} __attribute__((packed)) keyboard_report_t;

// 鼠标数据格式
typedef struct {
    uint8_t buttons;    // 按键状态(左/右/中)
    int8_t  x;          // X轴相对移动 (-127~127)
    int8_t  y;          // Y轴相对移动
    int8_t  wheel;      // 滚轮
} __attribute__((packed)) mouse_report_t;

USB HID描述符(关键代码)

CH583需要同时模拟键盘和鼠标,使用复合HID设备:

// USB HID Report Descriptor - 复合设备(键盘+鼠标)
const uint8_t HID_ReportDescriptor[] = {
    // ========== 键盘部分 ==========
    0x05, 0x01,        // Usage Page (Generic Desktop)
    0x09, 0x06,        // Usage (Keyboard)
    0xA1, 0x01,        // Collection (Application)
    0x85, 0x01,        //   Report ID (1)
  
    // 修饰键(8个bit)
    0x05, 0x07,        //   Usage Page (Keyboard/Keypad)
    0x19, 0xE0,        //   Usage Minimum (Left Control)
    0x29, 0xE7,        //   Usage Maximum (Right GUI)
    0x15, 0x00,        //   Logical Minimum (0)
    0x25, 0x01,        //   Logical Maximum (1)
    0x75, 0x01,        //   Report Size (1)
    0x95, 0x08,        //   Report Count (8)
    0x81, 0x02,        //   Input (Data, Variable, Absolute)
  
    // 保留字节
    0x95, 0x01,        //   Report Count (1)
    0x75, 0x08,        //   Report Size (8)
    0x81, 0x01,        //   Input (Constant)
  
    // 按键数组(6个键)
    0x95, 0x06,        //   Report Count (6)
    0x75, 0x08,        //   Report Size (8)
    0x15, 0x00,        //   Logical Minimum (0)
    0x25, 0xFF,        //   Logical Maximum (255)
    0x05, 0x07,        //   Usage Page (Keyboard/Keypad)
    0x19, 0x00,        //   Usage Minimum (0)
    0x29, 0xFF,        //   Usage Maximum (255)
    0x81, 0x00,        //   Input (Data, Array)
  
    0xC0,              // End Collection
  
    // ========== 鼠标部分 ==========
    0x05, 0x01,        // Usage Page (Generic Desktop)
    0x09, 0x02,        // Usage (Mouse)
    0xA1, 0x01,        // Collection (Application)
    0x85, 0x02,        //   Report ID (2)
    0x09, 0x01,        //   Usage (Pointer)
    0xA1, 0x00,        //   Collection (Physical)
  
    // 鼠标按键(3个bit + 5个padding)
    0x05, 0x09,        //   Usage Page (Buttons)
    0x19, 0x01,        //   Usage Minimum (Button 1)
    0x29, 0x03,        //   Usage Maximum (Button 3)
    0x15, 0x00,        //   Logical Minimum (0)
    0x25, 0x01,        //   Logical Maximum (1)
    0x75, 0x01,        //   Report Size (1)
    0x95, 0x03,        //   Report Count (3)
    0x81, 0x02,        //   Input (Data, Variable, Absolute)
    0x75, 0x05,        //   Report Size (5)
    0x95, 0x01,        //   Report Count (1)
    0x81, 0x01,        //   Input (Constant)
  
    // X, Y, Wheel
    0x05, 0x01,        //   Usage Page (Generic Desktop)
    0x09, 0x30,        //   Usage (X)
    0x09, 0x31,        //   Usage (Y)
    0x09, 0x38,        //   Usage (Wheel)
    0x15, 0x81,        //   Logical Minimum (-127)
    0x25, 0x7F,        //   Logical Maximum (127)
    0x75, 0x08,        //   Report Size (8)
    0x95, 0x03,        //   Report Count (3)
    0x81, 0x06,        //   Input (Data, Variable, Relative)
  
    0xC0,              //   End Collection
    0xC0,              // End Collection
};

BLE接收与USB发送的桥接逻辑

// BLE GATT写入回调 → 解析 → USB HID发送
void on_ble_data_received(uint8_t *data, uint16_t len) {
    ble_hid_packet_t *pkt = (ble_hid_packet_t *)data;
  
    switch (pkt->type) {
        case 0x01: { // 键盘
            keyboard_report_t *kb = (keyboard_report_t *)pkt->data;
            uint8_t report[9];
            report[0] = 0x01;           // Report ID
            report[1] = kb->modifier;
            report[2] = 0x00;           // Reserved
            memcpy(&report[3], kb->keycode, 6);
            USB_HID_SendReport(report, sizeof(report));
            break;
        }
        case 0x02: { // 鼠标
            mouse_report_t *ms = (mouse_report_t *)pkt->data;
            uint8_t report[5];
            report[0] = 0x02;           // Report ID
            report[1] = ms->buttons;
            report[2] = (uint8_t)ms->x;
            report[3] = (uint8_t)ms->y;
            report[4] = (uint8_t)ms->wheel;
            USB_HID_SendReport(report, sizeof(report));
            break;
        }
        case 0x03: // 多媒体键(扩展)
            // TODO: 音量、播放/暂停等
            break;
    }
}

手机APP端

APP端的核心功能是BLE连接管理和触摸输入采集。

功能模块

手机APP
├── BLE管理
│   ├── 扫描/连接CH583设备
│   ├── 服务发现
│   └── 断线重连
├── 键盘模式
│   ├── 全键盘布局
│   ├── 快捷键组合(Ctrl+C等)
│   └── 文本直接输入
├── 鼠标/触控板模式
│   ├── 触摸区域 → 相对移动
│   ├── 单击/双击/右键
│   └── 双指滚动
└── 设置
    ├── 鼠标灵敏度
    ├── 按键映射自定义
    └── 设备管理

Android端关键代码(BLE发送)

// 发送键盘按键
fun sendKeyPress(modifier: Int, keycode: Int) {
    val packet = ByteArray(10)
    packet[0] = 0x01  // type: keyboard
    packet[1] = 0x08  // length
    packet[2] = modifier.toByte()
    packet[3] = 0x00  // reserved
    packet[4] = keycode.toByte()
    // packet[5..9] = 0x00 (其余按键为空)
  
    bleCharacteristic?.let { char ->
        char.value = packet
        bleGatt?.writeCharacteristic(char)
    }
}

// 发送鼠标移动
fun sendMouseMove(dx: Int, dy: Int, buttons: Int = 0) {
    val packet = ByteArray(6)
    packet[0] = 0x02  // type: mouse
    packet[1] = 0x04  // length
    packet[2] = buttons.toByte()
    packet[3] = dx.coerceIn(-127, 127).toByte()
    packet[4] = dy.coerceIn(-127, 127).toByte()
    packet[5] = 0x00  // wheel
  
    bleCharacteristic?.let { char ->
        char.value = packet
        bleGatt?.writeCharacteristic(char)
    }
}

触控板手势处理

// 触控板区域的触摸事件处理
class TouchpadView(context: Context) : View(context) {
    private var lastX = 0f
    private var lastY = 0f
    private val sensitivity = 1.5f
  
    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                lastX = event.x
                lastY = event.y
            }
            MotionEvent.ACTION_MOVE -> {
                val dx = ((event.x - lastX) * sensitivity).toInt()
                val dy = ((event.y - lastY) * sensitivity).toInt()
                if (dx != 0 || dy != 0) {
                    sendMouseMove(dx, dy)
                    lastX = event.x
                    lastY = event.y
                }
            }
            MotionEvent.ACTION_UP -> {
                // 短按判定为点击
                val duration = event.eventTime - event.downTime
                if (duration < 200) {
                    sendMouseClick()
                }
            }
        }
        return true
    }
}

低功耗设计

既然是蓝牙设备,功耗管理很重要。CH583本身支持多种低功耗模式:

// 空闲时进入低功耗模式
void enter_low_power(void) {
    if (ble_connected && no_data_timeout > 5000) {
        // BLE连接状态下,拉长连接间隔
        GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, 2, &interval_max);
        // 进入Idle模式,保持BLE连接
        LowPower_Idle();
    } else if (!ble_connected && adv_timeout > 30000) {
        // 长时间无连接,进入深度睡眠
        // 通过GPIO按键唤醒
        LowPower_Shutdown(RB_SLP_GPIO_WAKE);
    }
}
工作状态典型电流
BLE广播~0.3mA (1s间隔)
BLE连接空闲~0.1mA
BLE收发+USB发送~8mA
深度睡眠~0.3μA

用一颗200mAh的纽扣电池,待机可以撑很久。


实际应用场景

这个方案的通用性体现在几个方面:

  1. 远程演示:手机当PPT翻页器,上下键翻页,鼠标指哪打哪
  2. HTPC控制:躺在沙发上用手机操控客厅电脑
  3. 嵌入式调试:给没有键盘接口的设备通过USB输入
  4. 游戏手柄(扩展):映射WASD和鼠标,手机变手柄
  5. 无障碍辅助:为行动不便的用户提供替代输入方式

开发资源

WCH官方提供了比较完整的开发资源:

  • SDK:MounRiver Studio(基于Eclipse的RISC-V IDE)
  • BLE协议栈:官方提供lib,有HID键盘/鼠标的例程
  • USB例程:SDK中包含USB HID Device的完整示例
  • 参考设计:官方EVT开发板原理图

基本上把官方的BLE HID例程和USB HID例程合并,再加上协议解析层,固件的主体框架就出来了。


总结

CH583做这类BLE转USB HID的桥接方案,确实是性价比很高的选择。RISC-V内核+BLE 5.3+原生USB的组合,在同价位几乎找不到对手。整个方案的核心就是三件事:

  • BLE收数据
  • 解析协议
  • USB发HID Report

硬件简单,软件逻辑清晰,很适合作为一个通用的无线HID方案来推广。后续还可以扩展多媒体键、手写输入、甚至语音转文字输入等功能,可玩性很高。

如果你也对这个方案感兴趣,欢迎留言交流。后续会更新实际的PCB设计和完整固件代码。

基于WCH CH583蓝牙芯片的手机远程控制键盘/鼠标通用方案
作者
WuQingYang
发表于
2026-02-24
License
CC BY-NC-SA 4.0