CH9329鼠标控制篇-发送数据包的构成
通过计算机向CH9329发送窗口数据,控制鼠标(发送数据构成部分)
使用CH9329和CH340发送串口数据控制鼠标键盘(鼠标控制篇-发送数据包的构成)(详细讲解)
CH9329简介(来自官方文档):
CH9329 是一款串口转标准USB HID设备(键盘、鼠标、自定义HID)芯片,根据不同的工作模式,
在电脑上可被识别为标准的USB键盘设备、USB鼠标设备或自定义HID类设备。该芯片接收客户端发
送过来的串口数据,并按照HID类设备规范,将数据先进行打包再通过USB口上传给计算机。

官方文档难免说的太官方,翻译过来就是:当你把它插在电脑上的时候,它可以接收你发送的串口数据,它会把你发送给它的串口数据翻译成鼠标键盘操作的数据(标准USB设备的数据),然后进行打包,在通过CH340发送给电脑。电脑接收到数据,以为是人为操作鼠标,鼠标发送的数据,就会傻傻的去执行.
简单理解就是说:它可以模拟鼠标键盘进行操作。
至于如何模拟鼠标和键盘进行操作,我们需要发送什么样的数据,它才可以翻译,就是今天我要说的。
注意:本片文章面会尽我最大努力详细讲解,不懂的地方可以留言,可以私信。
要想向CH9329发送数据,我们要知道它接收什么样的数据。
通信方式说明(来自官方文档):
通信以帧为单位,即以数据包的形式发送,每帧数据都带有帧头字节、地址码、命令码、
后续数据长度、后续数据以及累加和。
简单说就是它接收的数据是一个数据包,这些数据包中包含了一些特定数据。今天主要讲解对于鼠标的控制。所以我们来看控制鼠标发送的数据包的格式:
看不懂没关系,我来给你们分析一下,我提取了几个要素:
- 帧头: 0x57 0xAB
- 地址码:0x00
- 命令码:0x04
- 后续数据长度 7 ,也就是对后续数据长度的说明, 可以表示为 0x07(16进制)
- 需要我们编写7个字节的后续数据
- 最后一位是 前面数据的累加和(为1个字节)
好,现在我们知道要想控制CH3929进行模拟鼠标操作,我们要向它发送一个数据包
而每一个数据包又包括
- 帧头
- 地址码
- 命令码
- 后续数据长度(对发送数据长度的说明,就是说你要发送多长的数据,长度一般是官方规定)
- 后续数据 (要发送的数据)
- 累加和 (所有数据累加和)
数据包格式梳理:
数据包的构成:
帧头 + 地址码 + 命令码 + 发送数据长度声明 + 要发送的数据 + 前面数据的总和
帧头: 0x57、0xAB
地址码: 0x00
命令码: 0x04
发送数据长度声明: 0x07
要发送的数据: 0x00、0x00、0x00、0x00、0x00、0x00、0x00 # 假设发送的数据不对鼠标有任何操作
前面数据的总和: 暂时不知道
知道这些以后,我们就可以构造数据进行发送了。
字节大小的解释
我们知道,发送的数据有7个字节。一个字节有多大呢?
计算机最小的单位是Byt,1Byt只能表示 0 或者 1 两种状态,你可以把 1Byt 想象成一个灯泡,这个灯泡亮了就表示 1 灭了就表示 0
1字节 就是 8Byt ,相当于 8 个 灯泡。这 8 个灯泡可以表示 256 种状态 0-255
进制的解释
计算机有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字节 有 8Byt
用1个字节表示进制的范围:
二进制 0b00000000-0b11111111
八进制 0o000-0o377
十进制 0-255
16进制 0x00-0xFF
知道了字节的大小和进制,我们开始构造要发送的数据。
构造发送数据
数据有7位,我来分别说一下每一位代表什么:
第一位:固定写法 0x02
第二位:鼠标按键控制位
[0x00]:释放所有按键
[0x01]:鼠标左键按下
[0x02]:鼠标右键按下
[0x04]:鼠标滚轮按下 # 至于为什么不是 [0x03]后面会说。
第三位, 第四位, 第五位, 第六位:鼠标绝对移动的 x, y 轴坐标
x 坐标是: 第三位, 第四位
y 坐标是: 第五位, 第六位
设备默认屏幕分辨率为 4096*4096, 我们需要根据自身屏幕分辨率进行公式计算
输出x = (用户需要移动的x坐标 * 4096) / 用户屏幕分辨率x
输出y = (用户需要移动的y坐标 * 4096) / 用户屏幕分辨率y
然后, 将 输出x, 输出y 转换成 16 进制, 低位在前, 高位在后
例子: 假设用户屏幕分辨率是 1920 * 1080, 想将鼠标移动到 500, 500 位置:
输出x = (500 * 4096) / 1920 = 1066 转到 16 进制就是 42A
输出y = (500 * 4096) / 1080 = 1896 转到 16 进制就是 768
# 可以在计算器上转换结果
低位在前, 高位在后
42A 低位是 2A, 高位是 4
768 低位是 68, 高位是 7
输出x = 0x2A, 0x04
输出y = 0x68, 0x07
第三位:0x2A 第四位:0x04 第五位:0x68 第六位:0x07
第七位:鼠标滚轮滚动齿数
[0x00]:表示不滚动
[0x01-0x7F]:表示上滚动 换算成十进制整数 1-127
[0x81-0xFF]:表示下滚动 换算成十进制整数 129-255
这是每个字节数据代表的意思,下面,我举个例子理解一下:
假设,我的电脑分辨率是 1920*1080 现在,我想让鼠标移动到 桌面 (x=460, y=480) 坐标的位置,鼠标的按键不做操作,
首先,第一位是固定写法 0x02, 第二位由于鼠标按键不做操作,所以是 0x00
鼠标移动的坐标 x=460,
第三位, 第四位 是鼠标x坐标的数据
套入公式:输出x = (用户需要移动的x坐标 * 4096) / 用户屏幕分辨率x
可以得出:输出x = (460 * 4096) / 1920 = 981 = 0x3D5
第三位是低位,0x3D5的低位是 0xD5,所以,第三位是 0xD5
第四位是高位,0x3D5的高位是 0x03,所以,第四位是 0x03
继续计算第五位,第六位
鼠标移动的坐标 y=480,
第五位, 第六位 是鼠标y坐标的数据
套入公式:输出y = (用户需要移动的y坐标 * 4096) / 用户屏幕分辨率y
可以得出:输出y = (480 * 4096) / 1080 = 1820 = 0x71C
第五位是低位,0x71C的低位是 0x1C,所以,第三位是 0x1C
第六位是高位,0x71C的高位是 0x07,所以,第四位是 0x07
第七位是鼠标滚轮操作,由于鼠标滚轮不做任何操作,所以是 0x00
7个字节的数据包为:
"0x02", "0x00", "0xD5", "0x03", "0x1C", "0x07", "0x00"
我们知道,一个完整数据包的格式
数据包的构成:
帧头 + 地址码 + 命令码 + 发送数据长度声明 + 要发送的数据 + 前面数据的总和
下面将我们构造的数据加上 帧头 + 地址码 + 命令码 + 发送数据长度声明
"0x57", "0xAB", "0x00", "0x04", "0x07", "0x02", "0x00", "0xD5", "0x03", "0x1C", "0x07", "0x00"
最后在算所有数据的和,结果为 0x20A ,但是最后一位只有一个字节,所以取低位 0x0A 作为最后一位。
最后数据包为:
"0x57", "0xAB", "0x00", "0x04", "0x07", "0x02", "0x00", "0xD5", "0x03", "0x1C", "0x07", "0x00", "0x0A"
这样,我们就构造了一个 CH9329 可以翻译的数据包(官方文档称一个数据包为一帧)
例子(包含鼠标按键,鼠标滚轮,鼠标移动)
鼠标移动
假设,我的电脑分辨率是 1920*1080 现在,我想让鼠标移动到 桌面 (x=800, y=800) 坐标的位置,鼠标的按键不做操作。
完整数据包:
"0x57", "0xAB", "0x00", "0x04", "0x07", "0x02", "0x00", "0xAA", "0x06", "0xDA", "0x0B", "0x00", "0xA4"
鼠标按键
假设,我的电脑分辨率是 1920*1080 现在,我想让鼠标移动到 桌面 (x=500, y=300) 坐标的位置,鼠标的右键单击。
分析下,首先要有鼠标移动的数据包,还要有鼠标右键按下的数据包,最后还要鼠标右键弹起的数据包。
完整数据包:
# 鼠标移动的数据包
"0x57", "0xAB", "0x00", "0x04", "0x07", "0x02", "0x00", "0x2A", "0x04", "0x72", "0x04", "0x00", "0xB3"
# 鼠标右键按下的数据包
"0x57", "0xAB", "0x00", "0x04", "0x07", "0x02", "0x02", "0x00", "0x00", "0x00", "0x00", "0x00", "0x11"
# 鼠标右键弹起的数据包
"0x57", "0xAB", "0x00", "0x04", "0x07", "0x02", "0x00", "0x00", "0x00", "0x00", "0x00", "0x00", "0x0F"
鼠标滚轮滚动
假设,我现在想让鼠标滚轮向下滚动 1 个齿数 其他不操作。
完整数据包:
# 注意:1-127 是向上滚动,129-255 是向下滚动
# 1 表示向上滚动1个齿数, 2 表示向上滚动2个齿数
# 255 表示向下滚动1个齿数, 254表示向下滚动2个齿数
"0x57", "0xAB", "0x00", "0x04", "0x07", "0x02", "0x00", "0x00", "0x00", "0x00", "0x00", "0xFF", "0x0E"
思考一下
可不可以发送一个数据包,包含鼠标移动,鼠标按键按下呢?
关于鼠标滚轮按下数据为 0x04 而不是 0x03 的解释
看这张图
我们知道,二个字节表示鼠标按键状态,那么,请问:一个字节有多大呢?
没错,一个字节有 8 Byt 也就是 8 个灯泡…
上面这张图也是 8 个Byt。
可以表示为下面这个二进制数:
0 0 0 0 0 0 0 0
这八个0 ,就对应图上面的 BIT7 - BIT0
当 BIT2 为1 的时候,表示 中键,也就是滚轮按下,
可以表示为:
0 0 0 0 0 1 0 0
那么请问:0 0 0 0 0 1 0 0 的十进制是多少呢?
推一下:
- 0 = 0
- 1 = 1
- 2 = 10
- 3 = 11
- 4 = 100
- 5 = 101
可以看出,4 的二进制是 100,也就是 0 0 0 0 0 1 0 0
以此类推:
左键按下是 0 0 0 0 0 0 0 1 也就是 1, 1的十六进制是:0x01
滚轮按下是 0 0 0 0 0 0 1 0 也就是 2, 4的十六进制是:0x02
滚轮按下是 0 0 0 0 0 1 0 0 也就是 4, 4的十六进制是:0x04
到这里,关于向CH9329发送数据控制鼠标就说完了,有些地方可能说的不够明白,希望大家理解,不清除的也可以私信,留言,我看到都会回复。
后续会有键盘控制篇-发送数据包的构成,使用Python实现发送数据包, 基于Python控制CH3929实现的简易自动化控制,
关于基于Python控制CH3929实现的简易自动化控制这一篇,希望大家有简单的项目可以推荐,简单为主,(逻辑复杂的一两句话说不明白)主要是对控制鼠标键盘做一个总结。
注意: 文中仅为个人观点,如有错误,还请多多包涵,也希望我没有说明白的地方,给我留言,私信。
更多推荐



所有评论(0)