使用CH9329和CH340发送串口数据控制鼠标键盘(键盘控制篇-发送数据包的构成)

关于鼠标数据包的构成可以参考我上一篇的文章 链接: 鼠标控制篇-发送数据包的构成 这里不再赘述!

第一次接触CH9329的伙伴们也可以先观看我的鼠标控制篇,里面有详细讲解。

下面进入主题,今天我要说的是键盘数据包的构成。

官方文档说明

我们先看官方文档中提供的关于发送键盘数据的数据包格式:

在这里插入图片描述
看的出来,和鼠标数据包的格式差不多。
文档上有说 可支持 8+6 个无冲按键 也就是组合按键,8 个控制按键 + 6 个普通按键。 控制按键暂时我们先不管它,我们先构造简单的普通按键的 按下 和 抬起。至于8 个控制按键,会在后面说。

我来给你们分析一下,我提取了几个要素:

  • 帧头: 0x57 0xAB
  • 地址码:0x00
  • 命令码:0x02
  • 后续数据长度 8 ,也就是对后续数据长度的说明, 可以表示为 0x08(16进制)
  • 需要我们编写8个字节的后续数据
  • 最后一位是 前面数据的累加和(为1个字节)

好,现在我们知道要想控制CH3929进行模拟键盘操作,我们同样要向它发送一个数据包,跟模拟鼠标操作的原理一样。

而每一个数据包又包括

  • 帧头
  • 地址码
  • 命令码
  • 后续数据长度(对发送数据长度的说明,就是说你要发送多长的数据,长度一般是官方规定)
  • 后续数据 (要发送的数据)
  • 累加和 (所有数据累加和

数据包格式梳理:

数据包的构成:
    帧头 + 地址码 + 命令码 + 发送数据长度声明 + 要发送的数据 + 前面数据的总和
    
    帧头:               0x570xAB
    地址码:              0x00
    命令码:              0x02
    发送数据长度声明:      0x08
    要发送的数据:         0x000x000x000x000x000x000x000x00  # 假设发送的数据不对鼠标有任何操作
    
    前面数据的总和:        暂时不知道

格式知道了,那我们只需要把要发送的数据包结合上述格式发送个CH9329 就行了。

按下的数据包

数据有8位,我来分别说一下每一位代表什么:

        第一位:控制按键, 一个字节的控制按键,用于组合按下中使用,比如说 win + R 是打开运行窗口的,我们先不予理会,默认为 0x00 即可。
        
        第二位:固定写法 0x00
            
        第三位, 第四位, 第五位, 第六位, 第七位, 第八位:6个字节普通按键值,最多可以表示6个按键按下,如果无按键按下则填写0x00

一条命令中,我们暂时只需要关注 3-8 位即可。

假如我现在想按下键盘中的 A 键,我该如何构造数据包呢?

要想按下 A 键, 我们首先要知道在CH9329 中 A 键的键码,在官方文档中给我们提供了一张键码表,我整理了一些常用的,如下:

key_code = {
                "Q": "14",
                "W": "1A",
                "E": "08",
                "R": "15",
                "T": "17",
                "Y": "1C",
                "U": "18",
                "I": "0C",
                "O": "12",
                "P": "13",
                "Z": "1D",
                "X": "1B",
                "C": "06",
                "V": "19",
                "B": "05",
                "N": "11",
                "M": "10",
                "A": "04",
                "S": "16",
                "D": "07",
                "F": "09",
                "G": "0A",
                "H": "0B",
                "J": "0D",
                "K": "0E",
                "L": "0F",
                "0": "1E",
                "1": "1F",
                "2": "20",
                "3": "21",
                "4": "22",
                "5": "23",
                "6": "24",
                "7": "25",
                "8": "26",
                "9": "27",
            }

按键 A 的键码是 “04”, 注意:键码是16进制

知道键码后,我们就可以构造数据包了
按键按下后,没有收到抬起命令会一直长按,测试需要注意,拔下设备可以终止,后面会说到抬起的数据包

# 数据包一共 8 位,前面两位可以暂时理解成固定写法为: 
0x000x00
# 后 6 位为 6 个需要按下的键盘位,由于我们只需要按下 A 键,所以只填写第一位即可,后面默认。
0x040x000x000x000x000x00

# 完整 8 位数据包为:
0x000x000x040x000x000x000x000x00

知道数据包以后,我们只需要添加前面的帧头,地址码 , 命令码,最后加总作为最后 1 位即可

# 完整的一帧数据:
0x570xAB0x000x020x080x000x000x040x000x000x000x000x000x10

这样,我们就成功构造了一帧按下键盘 A 键的数据。

但是,一帧数据可以同时按下 6 个键,我们一帧只按下一个键,有时候还满足不了日常需求。

下面,我们多按下几个键试试。

其实,原理相同,掌握的上面的,同时按下多个键,自然是手拿把掐。
模拟日常需求:同时按下 W 和 A 键

# 首先,我们先构造一帧空数据包(包括帧头,地址码等等)
0x570xAB0x000x020x080x000x000x000x000x000x000x000x000x00

# 其次,我们找到 W A 键 的键码,添加进空帧数据中.
# 注意:键码的先后顺序,会影响先按下的键。

# 先按下 W 键,在按下 A 键。
0x570xAB0x000x020x080x000x000x1A0x040x000x000x000x000x2A

# 先按下 A 键,在按下 W 键。
0x570xAB0x000x020x080x000x000x040x1A0x000x000x000x000x2A

这样,我们就构造了一个帧数据包 同时操作两个键。
注意:并非是同时按下,有先后顺序,靠前优先,顺序按下

注意:在发送两条或多条帧数据按下键盘多个按键的时候,设备会默认抬起前一帧的所有按键,按下最后一帧的按键

# 先按下 A 键,在按下 W 键。
0x570xAB0x000x020x080x000x000x040x1A0x000x000x000x000x2A

# 先按下 B 键,在按下 D 键。
0x570xAB0x000x020x080x000x000x040x070x000x000x000x000x17

"""
在这两帧数据先后发送给设备的时候,设备会先按下 A 键,在按下 W 键。
然后,设备会抬起 A 键和 W 键 再次 按下 B 键,和 D 键。
最后,只有 B 键,和 D 键 处于按下状态。
"""

抬起的数据包

按下的数据包说完了以后,下面说说关于抬起的数据包。

抬起的数据包是向设备发送一帧空数据,设备会抬起所有按下的按键

# 空数据,这一帧数据是固定的,发送这一帧数据可以抬起所有按下的按键。
0x570xAB0x000x020x080x000x000x000x000x000x000x000x000x0C

关于单独抬起某个按键

官方文档并没有明确给出帧数据格式或者命令来完成单独抬起某个按键的操作。(也有可能是我没有找到,希望 知道的大佬不吝赐教!)
我的方法是通过多条帧数据的覆盖特性,前面有说,设备默认抬起前面所有帧数据的按键,(是按下后在抬起,不是没有按下)。只按下最后一帧数据中的按键,我们可以完成这样一个操作。

假设现在我要按下 A S D 三个按键,然后,抬起 S 按键,只保留 A D 按键处于按下状态 。

我构造了两帧数据。

# 按下 A S D 的数据包,要在一帧数据中。
0x570xAB0x000x020x080x000x000x040x160x070x000x000x000x2D

# 按下 A D 的数据包,要在一帧数据中。
0x570xAB0x000x020x080x000x000x040x000x070x000x000x000x17

"""
我先发送第一条数据,设备会按下 A S D 三个按键。
然后再发送第二条数据,设备会弹起 A S D 三个按键,然后按下 A D 这两个按键,间接把 S 弹起。
"""

关于控制按键

下面说说控制按键,看下这张图片:
在这里插入图片描述

在构造的 8 位数据中,后 6 位我们知道是 普键盘按键,前两位我们一直是默认 0x00,在官方文档中说明,要想按下控制按键,就要修改第一位数据的值。

可以看到,官方把 Windows, Alt, Shift, Ctrl 这 4 种按键称之为 控制按键,这 4 种按键,我们键盘上一共有 8 个(左右各一个)
要想知道如何去按下这些个按键,我们要知道 字节的概念。在上一篇 鼠标控制篇-发送数据包的构成 中我有详细说过,这里不再做详细解释,简单说一下。

在计算机中,最小的单位是 Bit,我们可以把他想想成一个灯泡,这个灯泡可以表示两种状态,灭 或者 亮,对应到 Bit 中就是 0 或者 1。

8个灯泡放进一个条形盒子里并排排开,就组成了一个字节,这 8 个灯泡有 256 中 亮灭排列。

8个按键,8个Bit,这不是巧合…

一个字节表示方法是:
0b 0 0 0 0 0 0 0 0 (0b是可以理解未修饰符,表示二进制数据)

8个 0 ,对应 8 个按键。
当我想要按下 左Windows 按键的时候,我只需要修改对应位置的 0 ,让 0 变成 1 就行了
0b 0 0 0 0 1 0 0 0
这个数据就表示 我们按下 左Windows 按键 , 接下来就是进制的转换了。

2进制 转换成 16 进制,关于进制的转换 在上一篇 CH9329鼠标控制篇-发送数据包的构成 中我也有详细说过,这里不再赘述。
0b 0 0 0 0 1 0 0 0 转换成 16进制的数据为: 0x08。
我们只需要将第一位数据改为 0x08 即可。

# 按下 左Windows  按键 的帧数据包
0x570xAB0x000x020x080x080x000x000x000x000x000x000x000x14

需求:通过快捷键打开我的电脑 (快捷键:左Windows + E)
E键 的键码是 08

# 先算出 左Windows键 的16进制 数据
0 0 0 0 0 0 0 0             左Windows键对应第 4 位,修改第 4 位的 0,结果是 0 0 0 0 1 0 0 0    转换成16进制是 0x08
# 快捷键打开我的电脑 的帧数据包
0x570xAB0x000x020x08       0x08        0x080x000x000x000x000x000x00         0x1C
      # 帧头数据                # 控制按键                     # 普通按键                     # 数据加总

(补充)进制的解释

计算机有4种进制

  • 二进制
  • 八进制
  • 十进制
  • 16进制

所谓进制,就是逢几进位,我们平时最常用的是 10进制,逢10进1,以此类推

二进制逢2进1,八进制逢8进1,16进制逢16进1(是 不是

二进制 :0-1
八进制:0-7
16进制:0-F (10:A,11:B,12:C,13:D,14:E,15:F)

二进制用 0b或者0B修饰 比如说 0b1001,0B1001
八进制用 0o或者0O修饰 比如说 0o11,0O11
16进制用 0x或者0X修饰 比如说 0x9,0X9

上面举例数字都在表示十进制的数字 9

我们知道了 1字节8Bit

用1个字节表示进制的范围:
二进制 0b00000000-0b11111111
八进制 0o000-0o377
十进制 0-255
16进制 0x00-0xFF

(补充)进制的转换

二进制 转 十进制

看下面这组二进制数据
0 表示0
1 表示1
10 表示2
11 表示3
100 表示4
101 表示5
110 表示 6
111 表示 7
1000 表示 8

有个规律,
10
100
1000
分别表示 2, 4, 8。推断一下 10000 表示16?

确实 16 的二进制 是 10000,32就是 100000, 64就是 1000000, 128就是 10000000

那 10110 是多少呢?
1 0 1 1 0 一共 5 位,我们暂时把它看成 1 0 0 0 0 + 1 0 0 + 10
1 0 0 0 0 是 16
1 0 0 是 4
1 0 是 2
16 + 4 + 2 = 22
所以 10110 的十进制 就是 22
这就是 二进制转 十 进制

十进制 转 十六进制

16进制分别表示为
0 1 2 3 4 5 6 7 8 9 A B C D E F
十进制的 14 用十六进制表示是 E
十进制的 22 用十六进制表示是 16
类似于 逢16 进 1

到这里,关于向CH9329发送数据控制键盘就说完了,有些地方可能说的不够明白,希望大家理解,不清楚的也可以私信,留言,我看到都会回复。

后续会有使用Python实现发送数据包基于Python控制CH3929实现的简易自动化控制

关于基于Python控制CH3929实现的简易自动化控制这一篇,希望大家有简单的项目可以推荐,简单为主,(逻辑复杂的一两句话说不明白)主要是对控制鼠标键盘做一个总结。

注意: 文中仅为个人观点,如有错误,还请多多包涵,也希望我没有说明白的地方,给我留言,私信。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐