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键盘 的相关文章

  • 关闭 USB 端口的电源

    我正在寻找扭转的方法power关闭 然后重新打开 USB 端口 解决方案可以是 C bash 等 我使用运行 32 位 Ubuntu 16 04 的 BeagleBone for armhf gt uname srvm Linux 4 4
  • 仿蓝牙人机界面设备

    我想知道应用程序是否有可能通过 Android 设备的蓝牙模拟人机接口设备 在我的上下文中 这将是一个模拟鼠标的应用程序 应该被计算机识别为蓝牙鼠标 理想情况下 这应该可以在 java 中实现 我知道这个问题过去已经被问过好几次了 但我想知
  • 如何检查 Android 上是否启用 USB 连接模式?

    我在 Android 市场上有一个应用程序 用户经常将他们的设备连接到计算机以将音乐添加到应用程序文件夹中 我在说明中特别指出 当启用 USB 连接模式时 Android 应用程序无法与 SD 卡通信 显然这还不够愚蠢的证据 有没有办法在j
  • USB 传输数据

    我正在尝试通过 USB 发送和接收数据 我的设备 Acer Iconia A500 拥有连接到设备所需的一切 一切都很好并且工作正常 但是当我尝试发送和接收数据时 它的行为并不像预期的 这是我的代码 for this is the main
  • 使用 DeviceWatcher 监视 USB 驱动器并检索设备信息?

    I m a WinForms开发人员和我已经知道如何使用 WMI 监视连接或断开连接的 USB 但不久前我发现了设备观察者 http msdn microsoft com en us library windows devices enum
  • 如何在 OSX Catalina (10.15) 中使用 Wireshark 捕获 USB 流量

    我正在尝试让 Wireshark USB 捕获工作 显然 Catalina 之前的技巧就是调出界面 以便 Wireshark 可以看到它 https forums developer apple com thread 95380 https
  • 软件和与外部设备串行通信的波特率限制

    我使用 USB 端口作为虚拟 COM 端口运行 以使用 MATLAB 或 Visual Basic 6 实现与外部设备的串行通信 我面临波特率限制 具体取决于我用于与设备通信的软件 MATLAB 2018a 没有问题 因为它可以设置高波特率
  • python的跨平台usb模块?

    我有兴趣在 python 中使用 USB 设备进行一些跨平台工作 关于可以执行此类操作的模块有任何提示或建议吗 我浏览了 SF 和 googlecode 但运气不佳 thanks ct PyUSB http pyusb berlios de
  • adb 未检测到 micromax a111

    最近我购买了 micromax a111 Android 设备 我是安卓开发者 因此尝试使用该设备进行调试选项 但 adb 无法检测到该设备 我也更改了设置 但没有成功 如果有人有解决方案 请帮助我解决这个问题 micromax没有官方的P
  • USB 调试 - 安装 Epson Moverio 驱动程序时出现问题

    Android 开发新手 我使用以下命令制作了一个小应用程序Eclipse http en wikipedia org wiki Eclipse 28software 29在虚拟 Android 设备上完美运行 现在 我想在真实的设备上运行
  • 在 Python 中将 USB 视频捕获设备友好名称与 OpenCV 端口号相关联

    我想在 Windows 平台上使用 Python 获取外部 USB 视频捕获设备的友好名称和 USB 端口号 我正在使用 OpenCV 从 USB 捕获设备捕获视频 OpenCV 将 USB 端口称为 1 找到的第一个工作摄像头 0 对我来
  • 在 Linux (libusb-1.0) 上访问 USB 设备?

    我正在编写一个小程序 使用 Linux 上的 libusb 1 0 与特定 USB HID 产品 由供应商和产品 ID 标识 进行通信 现在 我必须以 root 身份运行该程序 因为 libusb 需要对 USB 设备节点的写访问权限 有没
  • LibUsb 声明接口访问被拒绝 Java

    我希望能够从 USB 计步器读取数据 我正在 Java 中尝试此操作 并且使用 LibUsb 和 Usb4Java 库 我似乎无法认领 USB 管道或类似的东西 我正在使用的代码 final Context context new Cont
  • 如何将 Android USB 连接模式更改为仅充电? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案
  • 时间:2019-03-17 标签:c#usbdecision

    我们当前的应用程序中有几个进程 一个进程处理 USB 加载程序的检测和删除 处理检测和删除的代码如下 protected override void WndProc ref Message m switch m Msg case Win32
  • Android USB_DEVICE_ATTACHED 持久权限

    如何让 Android 在每次重新连接 USB 设备时都不再请求权限 我想让它记住 USB 设备的 默认使用 复选标记 这样我就不必每次都向同一设备授予权限 我以编程方式检测 USB 设备 Android 手机 何时连接到我的主机设备 An
  • 如何使用 python / pywinusb 将 hid 数据发送到设备?

    我正在尝试使用 pywinusb 将输出报告发送到 pic18f4550 该设备可以接收数据 我已经使用 C 应用程序对其进行了测试 效果很好 另外 我可以使用 pywinusb 从设备读取数据 但我在尝试发送数据时遇到问题 这是我正在运行
  • 获取已连接 USB 设备的端口名称

    当USB设备连接到计算机时 如何使用C 代码获取它所连接的端口名称 我找到了很多方法来查找 USB 何时连接 断开 驱动器号 路径 设备 ID 等 但没有找到任何明确的示例来说明如何知道它连接到哪个端口 我看到了一种可能的解释 但这涉及很多
  • Delphi - 如何获取 USB 可移动硬盘和记忆棒的列表?

    在我的应用程序 Delphi 中 我需要列出所有 USB 存储设备 这些可以是闪存棒or外部存储驱动器 有一个Jvcl成分JvDriveCombo 并且它有DriveType属性 问题是我是否选择DriveType Fixed那么除了外部驱
  • 使用 Windows 原始访问 API 直接访问 USB 驱动器

    在USB物理驱动器的末尾 我想使用Windows原始访问API直接写入数据 我不想使用内核驱动程序来做到这一点 据我所知 出于安全原因 Windows XP SP2 或 SP3 阻止了 HDD 直接访问 我不确定 USB 驱动器是否如此 请

随机推荐