# CH9329 Arduino **Repository Path**: chiyoooo/ch9329-arduino ## Basic Information - **Project Name**: CH9329 Arduino - **Description**: CH9239 arduino库, 便于快速使用 - **Primary Language**: C++ - **License**: BSD-3-Clause - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 13 - **Forks**: 2 - **Created**: 2022-10-20 - **Last Updated**: 2025-02-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Arduino CH9239 Library CH9239 arduino 库, 便于快速使用 这个库的更改日志可以在 CHANGELOG 中找到。 ## 已经实现的功能 1. 设置 PID, VID, 厂商描述符, 产品描述符, 序列号描述符等 2. 实现自定义 HID 通讯 3. 实现键盘按下 `press()` 释放 `release()` 点击 `click()` 打印字符串 `printstr` 等功能 4. 实现鼠标 按下`press()` 释放 `release()` 点击 `click()` 滚动滑轮`scrioll()` 移动光标位置`moveby()` 移动绝对光标位置 `moveto` 按住拖拽`start_drag()` `stop_drag()` 等功能 注意: 1. 由于 ch9329 只支持除 Win Ctrl Shift Alt 外,最多 6 键无冲突, 所以在 `press()` `release()` `click()` 函数中, 不要添加多余 6 个 普通键键值(除 Win Ctrl Shift Alt 和多媒体键之外的键值) 2. 鼠标键盘的重载函数不同, 所以请不要在 `press()` `release()` `click()` 中混用键盘鼠标两种键值.即 ```cpp // 错误 ch9329.press(KEY_SHIFT,MOUSE_BUTTON_MIDDLE,END); // 正确 ch9329.press(MOUSE_BUTTON_MIDDLE,END); ch9329.press(KEY_SHIFT,END); ``` 3. `press()` `release()` `click()`三个函数中, 参数列表的最后一次值一定要加上 END, 做为结束判断标志, 使用不定参数模板可以去掉这个 END, 但是代码会比复杂, 笔者水平不够, 暂时没有采用此方法实现 ## TODO 1. 目前波特率默认 9600.与芯片保持一致,但是如果要修改成 115200 必须用 9600 的串口修改芯片命令后再修改代码中通讯的波特率 或者使用官方提供的配置测试工具进行配置, 都是比较麻烦的, 下一版将优化这个问题 2. 目前电源控制相关的三个键值, 休眠, 关机和唤醒还没去实现,将在下一版优化 3. 不知道什么原因, 部分多媒体按键比如 打开浏览器 无法生效,原因真正查找 ## 快速使用 ### 引入头文件并创建一个实例 ```CPP #include "Ch9329.h" Ch9329 ch9329; ``` ### 在`setup()`中配置芯片 ```CPP ch9329.set_usb_manufacturer_string("WCH"); // 设置厂家名称 delay(200); ch9329.set_usb_product_string("MyCH9329"); // 设置产品名称 delay(200); ch9329.set_usb_serial_string("20221020"); // 设置产品序列号 delay(200); ch9329.set_configure(0x1234, 0x5678); // 设置 PID 厂家代码和 VID 产品代码 ``` ### 注册状态事件 ch9329 芯片在 USB 枚举完成,或者是键盘指示灯改变后,都会发一条信息到 MCU, 此处用 `usb_connect_cb()` 函数接收 ```CPP ch9329.attach_usb_connect(usb_connect_cb); // 注册 USB 链接回调 ch9329.attach_get_results(get_result_cb); // 注册 异常应答包触发回调 void usb_connect_cb() { Serial.println("success to connect PC"); Serial.printf("num_lock[%d] caps_lock[%d] scroll_lock[%d] \n", ch9329.num_lock_light, ch9329.caps_lock_light, ch9329.scroll_lock_light); } // 异常应答包触发回调 void get_result_cb(RESULTS res) { Serial.printf("CMD: 0x%02x Results: 0x%02x \n", res.cmd, res.error); } ``` ```cpp /*cmd指令码*/ #define CMD_GET_INFO 0x01 // 获取芯片获取版本号、 USB 枚举状态、键盘大小写指示灯状态等信息 #define CMD_SEND_KB_GENERAL_DATA 0x02 // 发送 USB 键盘普通数据 #define CMD_SEND_KB_MEDIA_DATA 0x03 // 发送 USB 键盘多媒体数据 #define CMD_SEND_MS_ABS_DATA 0x04 // 发送 USB 绝对鼠标数据 #define CMD_SEND_MS_REL_DATA 0x05 // 发送 USB 相对鼠标数据 #define CMD_SEND_MY_HID_DATA 0x06 // 发送 USB 自定义数据 #define CMD_READ_MY_HID_DATA 0x87 // 读取 USB 自定义数据 #define CMD_GET_PARA_CFG 0x08 // 获取芯片参数配置 #define CMD_SET_PARA_CFG 0x09 // 设置芯片参数配置 #define CMD_GET_USB_STRING 0x0A // 获取字符串描述符配置 #define CMD_SET_USB_STRING 0x0B // 设置字符串描述符配置 #define CMD_SET_DEFAULT_CFG 0x0C // 恢复出厂默认配置 #define CMD_RESET 0x0F // 复位芯片 ``` 如果通讯发生异常, 芯片会发一条异常码给 MCU, 对应的关系如下 | 异常码代号 | HEX 值 | 含义 | | --------------------- | ------ | --------------------- | | `DEF_CMD_SUCCESS` | `0x00` | 命令执行成功. | | `DEF_CMD_ERR_TIMEOUT` | `0xe1` | 串口接收一个字节超时. | | `DEF_CMD_ERR_HEAD` | `0xe2` | 串口接收包头字节出错. | | `DEF_CMD_ERR_CMD` | `0xe3` | 串口接收命令码错误. | | `DEF_CMD_ERR_SUM` | `0xe4` | 累加和检验值不匹配. | | `DEF_CMD_ERR_PARA` | `0xe5` | 参数错误. | | `DEF_CMD_ERR_OPERATE` | `0xe6` | 帧正常,执行失败. | ### 建议开始时候的时候,打开调试信息 在 vscode + PlatformIO + arduino 中, 只需要在 platformIO.ini 文件中加入. 运行正常后建议关闭 ```CPP build_flags = -DCORE_DEBUG_LEVEL=4 ``` ## 键鼠使用 ### 引入头文件并实例化对象,出于演示目的, 用到了 OneButton 库,这是一个非常好用的按键库 ```cpp #include #include "OneButton.h" Keymouser ch9329; OneButton btn1(19, true); ``` ### 第一个函数演示 打开电脑笔记本, 然后写字符串 "Hello World!" ```cpp void sayHello() { ch9329.click(KEY_WIN, END); delay(200); ch9329.printstr("text"); delay(200); ch9329.click(KEY_ENTER, END); delay(2000); ch9329.printstr("Hello world!"); } ``` ### 按键按下电脑静音 ```cpp void btn1_click_cb(void) { ch9329.click(KEY_MEDIA_MUTE); } ``` ### 按键长按将模拟 3D 软件中的视图操作, 很多 3D 软件旋转视图都需要用到鼠标中键, 按多了手疼, 此处简单演示了如何实现 ```cpp void btn1_press_start_cb(void) // 按键按下的时候 将一直按着 SHIFT 和鼠标 MIDDLE 键, 并且向右移动光标2px { ch9329.press(KEY_SHIFT, END); ch9329.start_drag(MOUSE_BUTTON_MIDDLE, 2, 0); } void btn1_press_cb(void) { ch9329.press(KEY_SHIFT, END); ch9329.start_drag(MOUSE_BUTTON_MIDDLE, 2, 0); } void btn1_press_stop_cb(void) // 按键释放的时候, 释放 SHIFT 和鼠标 MIDDDLE 键 { ch9329.release(KEY_SHIFT, END); ch9329.stop_drag(MOUSE_BUTTON_MIDDLE); } ```