CH552 USB HID键盘

2023-05-16

客制化键盘制作V1——CH552工程

目前正在客制化一个小键盘,计划8月中旬在咸鱼上售卖,功能包括:

  1. 蓝牙有线双模,蓝牙
    5.0(nrf52810),低功耗模式
  2. 按键+旋钮
  3. 自定义按键,可设置组合键和多媒体键,专用软件设置
  4. WS2812灯效
    看到很多人有私信问我,目前我做的是CH583蓝牙双模键盘(半成品,已无限期搁置),已经完成的有CH552G旋钮键盘和CH579的数字键盘,可以去我的网站 www.diypad.top 找找思路哦。

一、CH552简介

CH552是一款包含USB功能的单片机,还包含多个外设,如ADC、PWM、串口、SPI等,可以通过USB外设实现HID键盘和模仿CH340进行串口通信。
CH552输入可以5.0V,无需外部晶振即可工作,使用5.0V电压时,仅需要2个退耦电容。

二、CH552与蓝牙芯片通信

通信可以使用串口、SPI以及其它方法,为方便通信,本次只计划使用串口进行通信。通信波特率选择115200,在这个频率下,可以实现接近1000Hz的通信次数。
当然也可以选择更高的波特率,但是网上资料显示,更高的波特率可能会出现错误。

三、CH552的功能及方案

1. 功能介绍

由于键盘的其它功能都是由蓝牙芯片NRF52810实现,因此仅在有线模式和自定义按键设置时需要该芯片。

有线模式:识别为HID键盘,接收串口的数据,并使用USB发送出去。需要对串口的数据进行校验,发送或接收错误时会串口返回错误码。
自定义按键设置模式:识别为CH340芯片,与电脑进行虚拟串口通信,原封不动地将数据通过串口与蓝牙芯片交换。

2. 方案

模式变化:以上两种模式通过一个外部引脚(检测引脚)进行控制(实际上是通过拨动开关实现),当该引脚为高阻态时进入有线模式,为高电平时进入 自定义按键模式。
识别:当CH552上电时,设置检测引脚为高电平,再为低电平,然后检测引脚状态。注意检测结束后要及时将引脚转换为高电平。实际上,CH552并没有输入模式,他检测高低电平的原理是利用高电平无驱动能力试下的,即将单片机引脚设置为高电平,虽然电压检测引脚是高电平,但实际上是没有向外部输出电流的能力的,如果直接将该引脚接地,也不会有电流输出,但引脚读取的时候,就会读取到低电平。但引脚有灌入电流,当引脚设置为低电平的时候,接高电平的时候电流会有45mA的样子,虽然正常使用,但一段时间后芯片确实有点发热。(由于电路设计不合理,只能暂时这样操作)。

3. 串口数据校验

在有线模式下,需要接收来自蓝牙芯片的串口数据,为了防止数据错误和不同数据类型识别,需要对数据进行封装。封装包括:起始位,数据,校验位和截至位。

起始位A:检测为普通数据,数据位共7Bytes,校验位和截至位没问题时直接发送该7Bytes数据。
起始位B:检测为媒体数据,数据为4Bytes,校验位和截至位没问题时直接发送;但发送前需要检测上一次普通数据是否清零,未清零需要先发送清零的普通数据再发送多媒体数据。
失败:校验位失败则串口返回失败码ERROR。

4. 流程

  1. 上电,检测引脚检测,根据情况配置不同USB模式

5. 已完成代码

  1. 通过引脚判断模式
  2. 通过不同的描述符,配置USB为HID设备或CH340设备
  3. HID设备时,接收串口数据,进行校验后发送出去,包括普通按键和多媒体按键,不做任何处理。
  4. CH340设备实现串口通信一直失败,无法实现单片机与蓝牙模块的串口通信,后来通过官方其它例程,才发现是串口中断没有打开,就很离谱。还以为是HID例程中的函数导致的串口中断问题。

四、CH552单芯片版本(有线单模)

蓝牙键盘焊接后,出现了各种问题,包括整体功耗大,自己焊接的陶瓷天线信号微弱等,由于博主目前无太多精力解决上述问题,因此打算转向单模有线版本。
芯片仍然使用CH552,这是目前了解到的最便宜的带USB功能的芯片了。并没有采用qmk,以及其推荐芯片ATMega型号,打算自己从0开始编写。
以下为最新的键盘情况:旋钮控制音量和播放暂停;按键控制上下曲,以及某些软件的快捷键。

键盘图片

1. 按键读取、EC11旋钮读取

  1. 按键读取方式为间隔2ms读取一次引脚,当连续5次为低电平时,定义该引脚按下。EC11旋钮则引脚A为连续两次为低电平时,读取B引脚,如果为高电平为逆时针选择,否则为顺时钟旋转。
  2. 上述的连续几次读取是软件滤波,可以去除按键抖动的情况,实际体验并没有出现延迟的情况。但旋钮在旋转很快的时候,会出现读取错误,会被认为逆时针和顺时针交替,但一般旋转不影响。

2. CH552 ws2812实现

  1. 虽然ch552拥有PWM,之前使用过STM32和NRF52芯片,均使用PWM+DMA的方式驱动WS2812。但是考虑到CH552性能不佳,还是直接通过操作引脚实现,通过nop进行操作,当系统频率为24MHZ时,每个nop的时间差不多为65us,按照WS2812手册进行编写即可。
  2. 但发现ws2812显示会出现错误数据的情况,排查后发现是上面按键读取中的2ms中断导致的:程序中有一个2ms的定时器中断,用于指示按键读取一次,虽然在中断中只进行了3次赋值操作,但影响很大。解决方法为,在WS2812操作前关闭定时器中断,完成后打开定时器中断,由于WS2812操作,因此不影响。以下查看键盘最新图片:

3. 键鼠多媒体键盘

  1. 一个好的键盘,不仅能够实现普通键盘的功能,还应该集合鼠标、多媒体按键的功能,实现键鼠多媒体按键。另外,传统的HID键盘,由于其报告描述符限制,只能实现6键无冲。
  2. 解决方法:增加设备接口数量,第一个接口为键鼠合集,第二个接口为多媒体按键;或者键鼠多媒体都使用一个接口,使用一个报告描述符。
  3. 测试结果:成功实现键盘、鼠标、多媒体按键功能为一体,并且解决无冲键数量只有6的限制。具体操作为主页中的另一篇博客,但我隐藏了,看情况公开。

4. 自定义按键存取问题

  1. 按键要自定义,首先要保证自定义的数据能够断电存储,但是CH552不像stm32等“高端芯片”那样,可以直接读取内部的flash,有个网友是说CH552利用的是iflash,存取次数只有200次,所以芯片才这么便宜。具体是不是200次,我等之后不断烧录代码测试下。
  2. 添加外部flash或eeprom是一个方法,选择eeprom,价格更加便宜,但是引来另一个问题,即CH552引脚不够。虽然考虑过使用按键扫描芯片,但其只能检测单按键;或移位寄存器,但需要添加二极管防止引脚同时按下的短路。采用矩阵按键,也需要添加按键,电路也更加复杂,放弃。
  3. 解决方法:按键选两个引脚出来,连接到eeprom中。因为存取数据的次数不多,只需要保证这个过程中,没按键按下即可。当然,写入的数据需要校验码验证,防止意外的错误。

5. 在线实时修改参数

  1. 一个好的客制化键盘,需要能够用户自己修改按键的值以及其他参数,如WS2812灯效等。不能让用户重新烧录,一方面麻烦,另一方面也透露了自己的代码(虽然之后我会开源代码)。
  2. 开始思考的方法是键盘通电时选择模式为HID模式,或模仿为ch340串口芯片,当为串口模式时,用户可以通过串口给单片机传输数据。这个已经实现了,但是发现过于占用CH552为数不多的资源,也比较麻烦。
  3. 在看到键鼠多媒体键盘的实现思路之后,想到一个方法:即再加入一个接口,多一个用户自定义的HID设备,通过这个HID设备进行数据通信。目前已经完成了该接口的数据收发,对键盘的LED灯进行实时修改,但仍有一个小问题,出现了数组内存移位的问题,需要之后验证。但该方法就需要上位机访问到该设备,相比于串口通信,需要的步骤更为复杂,也更为底层,因此需要使用到C++语言进行编写。博主C++本来就不佳,上次写C++应用程序还是3年前的大学一门课上。原来python早已封装好了库,使用pywinusb即可。
  4. 之前测试发送单片机接收sub数据正常,但是发送数据出现数据移位的问题,开始还不知道为什么,原来是启动数据的发送和接收,那么单片机端的数据发送存放的buf地址,需要在接收buf地址之后,两个buf并不是互用的。因此发送的时候,需要将待发送buf加上最大地址长度,即可试下正常的数据收发。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CH552 USB HID键盘 的相关文章

  • 使用 python 检测 Windows 10 上的 USB 设备插入

    我无法获取以下代码检测USB设备插入 http timgolden me uk python win32 how do i detect device insertion html在我的 Windows 10 64 位 计算机上使用 Pyt
  • Mac中如何获取usb设备的设备描述符和配置描述符?

    I have minimum exposure to xcode and I Okit framework I have seen device descriptor and configuration descriptor of a us
  • 通过 USB 记忆棒携带和操作整个开发盒。可行的?

    最近我一直在考虑投资一个有价值的 USB 笔式驱动器 类似于 并在虚拟机上安装操作系统并开始在其上进行开发 我的想法是 我希望能够携带我的开 发箱 成为一名Windows 发行版用于 Net 开发和Linux发行版像 RoR Perl 之类
  • 无法使用 Android Studio、Windows 7 连接到 Samsung Galaxy Tab S

    我有一台漂亮的新三星 Galaxy Tab S 我正在尝试将其与 Android Studio 连接 我已在平板电脑上启用 USB 调试 并通过执行 SAMSUNG USB Driver for Mobile Phones v1 5 45
  • 在 Mac 上通过 USB 访问 iOS 设备

    我有一个移动应用程序需要将文件传输到数据库 然而 其规范之一是 如果用户没有设置无线网络 则应该能够将其插入 Mac 并将文件传输到数据库 然而 我遇到的问题是如何将上述文件从 iPad 上通过 USB 传输到计算机上 上周我研究了各种解决
  • USB 调试 - 安装 Epson Moverio 驱动程序时出现问题

    Android 开发新手 我使用以下命令制作了一个小应用程序Eclipse http en wikipedia org wiki Eclipse 28software 29在虚拟 Android 设备上完美运行 现在 我想在真实的设备上运行
  • 如何在没有窗口句柄的情况下使用 RegisterDeviceNotification?

    我正在编写一个 DLL 库 该库使用 VB NET 中的 winusb 连接到 USB 设备 由于它是一个 DLL 所以我没有窗口 而且我的库的用户也可能没有窗口 例如命令行应用程序 我见过的检测设备连接和分离的示例都使用RegisterD
  • 如何枚举 USB 设备*并*对其进行读/写?

    我需要与一个自定义 USB 设备进行通信 它没有特定的驱动程序 该设备不显示为 dev tty I 发现 http www signal11 us oss udev 我该如何使用libudev枚举 USB 设备 假设我设法获得相应的stru
  • Silverlight 能否访问可访问 USB 端口的 .Net 库?

    我们有一个 Net 库 可以通过 USB 端口访问一些自定义硬件 我读到 Silverlight 包含 Net 运行时的子集 所以 我的问题是 这个子集足以让 Net 库运行吗 不可以 您不能使用从 Silverlight 内部访问 USB
  • WriteFile 返回错误代码 87

    我正在开发一个写入 HID 设备的程序 但收到错误 87 WriteFile 函数参数无效 我从 Jan Axelson 的 USB Complete 获得了这些功能 所以我不确定为什么会收到错误 我用它来查找我的设备 private vo
  • 我无法找到 libftdi 的 mpsse (SPI) 模式的示例代码

    这不是一个家庭作业问题 尽管这是一个工作问题 几个月前 我刚写完一份规范 老板就会把它外包出去 因为资金紧张 所以我正在尝试自己做这件事 我是一个很弱的 C 编码员 如果 gcc 能输出一些运行时不会出现段错误的东西 或者有时根本没有任何东
  • Android 版 usbmon

    我想分析我的设备的 USB 通信 SGS4 我到处都看到需要配置 usbmon 并将其编译到内核中 Afaik 这个模块没有内置在android linux系统中 我在编译内核方面没有太多经验 但如果有必要 我会这样做 您能说出这样做的步骤
  • 如何查找USB盘符?

    我正在编写一个安装程序来将应用程序安装到 USB 驱动器 该应用程序只能从 USB 驱动器使用 因此它可以通过自动选择要安装的 USB 驱动器来为用户节省额外的步骤 我可能会尝试使用 Nullsoft 或 MSI 进行安装 但由于我最熟悉
  • USB接口条码扫描器

    不完全是一个编程问题 但很接近 无论如何我都会试试运气 The 键盘楔子 扫码机插入 读者之间的翻译装置 和键盘 数据发送通过 楔形看起来就像是被输入的 电脑 而键盘 本身仍保持完整功能 因为电脑使用键盘 楔子无法区分 在输入的数据之间 扫
  • LibUsb 声明接口访问被拒绝 Java

    我希望能够从 USB 计步器读取数据 我正在 Java 中尝试此操作 并且使用 LibUsb 和 Usb4Java 库 我似乎无法认领 USB 管道或类似的东西 我正在使用的代码 final Context context new Cont
  • 如何使用 python / pywinusb 将 hid 数据发送到设备?

    我正在尝试使用 pywinusb 将输出报告发送到 pic18f4550 该设备可以接收数据 我已经使用 C 应用程序对其进行了测试 效果很好 另外 我可以使用 pywinusb 从设备读取数据 但我在尝试发送数据时遇到问题 这是我正在运行
  • 如何在非零端点(libusb)上发送 USB 控制事务?

    我正在编写代码来了解 Freescale Kinetis 微控制器上的 USB 外设 我已经设法在 Linux 主机上完成枚举 并且可以使用 EP0 上的供应商自定义代码发送和接收数据包 与 libusb 测试程序交互 看起来我可以在微控制
  • 当前有哪些 USB 设备(友好名称)连接到 PC?

    我可以获得当前连接到计算机的设备列表吗 我检查了this https stackoverflow com q 3331043 75500 and this https stackoverflow com questions 3685615
  • 在 Windows 中以编程方式重新启动 USB 设备

    我正在开发的一些软件需要 USB 设备 我作为串行端口与 USB 转 UART 桥进行交互 有时 计算机从休眠状态重新启动后 无法检测到该设备 并且我无法再通过串行端口写入或读取该设备 需要对设备进行读 写访问 我不能依赖用户采取任何操作
  • 在 Python 中窗口“失焦”时读取 HID 输入

    我在一个问题上苦苦挣扎了好几天 但无法让它发挥作用 我刚刚开始使用 python 现在已经面临着我在这个项目中将面临的最大问题 情况是这样的 我必须编写一个扫描条形码的程序 将其传达给在线服务并打印 PDF 这一切都很好 但我也想在窗口 失

随机推荐