原理篇4、CH9328使用

简介

1、CH9328 是一款串口转 HID 芯片,在电脑上识别为标准的 USB HID 类键盘设备。CH9328 用于单向数据传输,可以接收串口发送过来的数据(如 ASCII 码),并按照 HID 类键盘设备规范,将数据打包成标准的键盘码值通过 USB 口上传给计算机。通过提供的上位机软件,用户也可自行配置芯片的 VID、PID,以及各种字符串描述符。

2、默认串口通信波特率为 9600bps

.

.

.

1、引脚介绍

在这里插入图片描述

部分引脚说明

(详细说明在 参考资料 中的网址下载说明文档)
在这里插入图片描述
.在这里插入图片描述

.

.

.

2、工作模式

上传速度设置

CH9328的 IO1 引脚用于配置芯片的上传速度,上电时该引脚为高电平则速度配置为普通模式,上电时该引脚为低电平则速度配置为高速模式,高速模式的速度大概为普通模式的 1 倍。

.

.

工作模式设置:

工作模式IO2电平IO3电平IO4电平功能说明
模式0111该模式仅支持将可见ASCII码(如 a-z、0-9、@、#、$ 等)对应的字符转成标准的USB键值。特殊功能:接收到的串口数据包如果遇到 0x1B 时,则丢弃当前包中 0x1B 之后的数据,并将 0x1B 转换成回车键。
模式1101该模式仅支持将可见ASCII码(如 a-z、0-9、@、#、$ 等)对应的字符转成标准的USB键值。
模式2110该模式仅支持将可见ASCII码(如 a-z、0-9、@、#、$ 等)对应的字符转成标准的USB键值。特殊功能:接收到的串口数据包如果遇到 0x28 时,将 0x28 转换成回车键。
模式3011该模式为透传模式,不仅仅用于传输可见ASCII码字符。该模式下可以实现标准的USB全键盘功能。串口数据每8个字节组成一包,芯片每接收到8个字节后,直接打包通过USB口上传。即芯片为透传模式,不分析转换串口数据,直接按8个字节一包上传。故串口数据必须按照标准的USB键盘数据包进行发送。比如模拟“A”按下,则串口发送数据包为:0x00、0x00、0x04、0x00、0x00、0x00、0x00、0x00;比如模拟“A”释放,则串口发送数据包为:0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00;比如模拟“A+SHIFT”同时按下,则串口发送数据包为:0x02、0x00、0x04、0x00、0x00、0x00、0x00、0x00;比如模拟“A+SHIFT”同时释放,则串口发送数据包为:0x00、0x00、x00、0x00、0x00、0x00、0x00、0x00

.

.

.

3、电路连接

键盘上的电路连接原理图:
在这里插入图片描述
上图中已将 CH9328IO1,IO3IO4设置为高电平,IO2设置为低电平。
通过电平设置可将其工作模式设置为普通模式下的模式3(透传模式)。

.

数据手册中的电路原理图:
在这里插入图片描述

.

.

.

4、数据格式

工作模式设置的模式3说明中已经大致说了数据格式。
以下为具体说明。

通信协议

使用的是CH9328的模式3。
在模式3,一次向CH9328发送8个字节的数据。
数据格式为:

[byte1][byte2][byte3][byte4][byte5][byte6][byte7][byte8]

其中第一个字节(byte1)用来标识特殊按键

[byte1]
	---bit0:左Ctrl 	按下为1,否则为0---bit1:左Shift 按下为1
	---bit2:左Alt	按下为1
	---bit3:左GUI	按下为1
	---bit4:右Ctrl 	按下为1
	---bit5:右Shift	按下为1
	---bit6:右Alt	按下为1
	---bit7:右GUI	按下为1

.
按下左Shift 则第一个字节应该为 0000 0010,即0x02。
完整发送的数据为

{0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

.
若按下左Shift右Ctrl 则第一个字节应该是 0000 0010|0001 0000 的值,结果为 0x12
注意:这里的 ‘|’ 是 ‘’ 符号,功能是按位相或。)
完整发送的数据为

{0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

.
第二个字节为保留字节 全部为0即可,即0x00。

第三到第八个字节为普通按键的键值,所以不加上特殊按键最多可以发送六个按键。
若按下 左Shift左CtrlA1/ 这五个键,完整的发送数据为

{0x03, 0x00, 0x04, 0x1E, 0x38, 0x00, 0x00, 0x00};

其中 左Shift左Ctrl 为 0x02 | 0x01 得到 0x03
A的键值为 0x041 的键值为 0x1E/ 的键值为 0x38

若仅有 A 按下,然后其余按键都松开,则完整的发送数据为

{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00};

.

.

.

5、驱动程序

定义一个缓存空间

//USB发送数据 8字节大小缓存
uint8_t key_code[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

.

创建键码数组

定义键盘上每个按键对应的键码

//USB 未按下Fn时的键码
const uint8_t USB_KEY_CODE[KEYBOARD_ROW][KEYBOARD_COLUMN] = {
    //` ~               1 !        2 @        3 #        4 $        5 %        6 ^        7 &        8 *        9 (        0 )        - _          = +            backspace
    {KEY_USB_SEPARATOR, KEY_USB_1, KEY_USB_2, KEY_USB_3, KEY_USB_4, KEY_USB_5, KEY_USB_6, KEY_USB_7, KEY_USB_8, KEY_USB_9, KEY_USB_0, KEY_USB_SUB, KEY_USB_EQUAL, KEY_USB_BACKSPACE},
    //tab         Q q        W w        E e        R r        T t        Y y        U u        I i        O o        P p        [ {               ] }               \ |
    {KEY_USB_TAB, KEY_USB_Q, KEY_USB_W, KEY_USB_E, KEY_USB_R, KEY_USB_T, KEY_USB_Y, KEY_USB_U, KEY_USB_I, KEY_USB_O, KEY_USB_P, KEY_USB_LBRACKET, KEY_USB_RBRACKET, KEY_USB_BSLASH},
    //caps lock         A a        S s        D d        F f        G g        H h        J j        K k        L l        ; :                ' "             --  Enter
    {KEY_USB_CAPS_LOCK, KEY_USB_A, KEY_USB_S, KEY_USB_D, KEY_USB_F, KEY_USB_G, KEY_USB_H, KEY_USB_J, KEY_USB_K, KEY_USB_L, KEY_USB_SEMICOLON, KEY_USB_SQUOTES, 0, KEY_USB_RETURN},
    //shift              Z z        X x        C c        V v        B b        N n        M m        , <            . >            / ?             shift                ↑                DELETE
    {KEY_USB_LEFT_SHIFT, KEY_USB_Z, KEY_USB_X, KEY_USB_C, KEY_USB_V, KEY_USB_B, KEY_USB_N, KEY_USB_M, KEY_USB_COMMA, KEY_USB_FSTOP, KEY_USB_FSLASH, KEY_USB_RIGHT_SHIFT, KEY_USB_UP_ARROW, KEY_USB_DELETE},
    //ctrl              Win               alt               ----  space         --------- Fn ctrl                ←                   ↓                   →
    {KEY_USB_LEFT_CTRL, KEY_USB_LEFT_GUI, KEY_USB_LEFT_ALT, 0, 0, KEY_USB_SPACE, 0, 0, 0, 0, KEY_USB_RIGHT_CTRL, KEY_USB_LEFT_ARROW, KEY_USB_DOWN_ARROW, KEY_USB_RIGHT_ARROW}};

//USB 按下Fn时第一行按键的键码
uint8_t FN_USB_Code[14] = {KEY_USB_ESC, KEY_USB_F1, KEY_USB_F2, KEY_USB_F3, KEY_USB_F4, KEY_USB_F5, KEY_USB_F6, KEY_USB_F7, KEY_USB_F8, KEY_USB_F9, KEY_USB_F10, KEY_USB_F11, KEY_USB_F12, KEY_USB_F13};

键码发送

更改第一个字节

//参数为此按键的键码和按键状态(按下为1,松开为0)。
void first_bit(uint8_t key_, uint8_t state);

.
实现方法
对缓存空间内第0字节的位操作可实现发送数据的更改。

void first_bit(uint8_t key_, uint8_t state)
{
//判断键码是否正确
    if (key_ != 0)
    {
    	//如果按键为按下
        if (state == 1)
        {
            key_code[0] = key_code[0] | key_;
        }
        else//否则当按键此按键松开
        {
            key_ = ~key_;
            key_code[0] = key_code[0] & key_;
        }
    }
}

.

.

更改其余字节

//参数为此按键的键码和按键状态(按下为1,松开为0)。
//因为CH9328只能发送六个普通按键的状态,
//所以当按下的按键数量大于6时,将无法发送,
//此函数可返回0/1,表示是否设置成功,
//当已经按下6个普通按键,再按下一个普通按键时,将无法设置,返回0。
uint8_t other_bit(uint8_t key_, uint8_t state)

.
实现方法

uint8_t other_bit(uint8_t key_, uint8_t state)
{
	//返回值,先设置为0,如果以下代码未将键码存入缓冲区,
	//返回值未改变,为0,
	//意味着已经按下6个按键,此按键无法设置。
    uint8_t o_ = 0;
  	//判断键码是否正确
    if (key_ != 0)
    {
    	//如果状态为按下(1)
        if (state == 1)
        {
        	//从缓冲区的 第2字节开始查询空的位置
            for (uint8_t i = 2; i < 8; i++)
            {
            	//如果在第 i 字节找到空位置
                if (key_code[i] == 0x00)
                {
                	//将键码存入空位置中
                    key_code[i] = key_;
                    o_ = 1;//返回1 ,表示设置成功
                    break;
                }
            }
        }
    	//如果状态为松开(0)
        else if (state == 0)
        {
        	//从缓冲区的 第2字节开始查询此键码所在的位置
            for (uint8_t i = 2; i < 8; i++)
            {
            	//如果找到此键码保存的位置
                if (key_code[i] == key_)
                {	
                	//将键码删除,使此位置为空(0x00)。
                    key_code[i] = 0x00;
                    o_ = 1;//返回1 ,表示设置成功
                    break;
                }
            }
        }
    }
    return o_;
}

.

.

发送缓存空间数据
原理图中ESP32的串口1连接 CH340C,用于代码下载和键盘调试,
串口2连接CH9328,用于发送按键数据。

先将ESP32的串口2打开。

Serial2.begin(9600);//波特率9600

.
发送缓存空间的数据。

Serial2.write(key_code, 8);

.

.

.

6、参考资料

1、沁恒CH9328数据手册
http://www.wch.cn/downloads/file/224.html?time=2021-01-02%2023:41:25&code=rYSU24iPmeAbHiFXl8Oyf3PsP0W8Pza8XGbBUDPw

.

.

资料获取

全部工程文件进ESP32工程群(483217976)自行下载,所有文件在 ESP32键盘 目录下。

STM32F103C8 Serial(UART) to USB HID Keyboard Mouse 串口 转 USB键盘鼠标 (1) 使用Composite Device 组合(复合)设备 (1.1) 1个Device -> 1个 Configuation -> 2个Interfance (Keyboard & Mouse) (1.2) Keyboard Interfance -> HID (boot mode) -> 2个Endpoint(IN_0x81 & OUT_0x01) -> KeyboardReportDescriptor(不使用Report ID) (1.3) Mouse Interfance -> HID (boot mode) -> 1个Endpoint(IN_0x82) -> MouseReportDescriptor(不使用Report ID) (1.4) 使用HID boot模式, 不使用Report ID, 以便兼容在 计算器设定BIOS模式 中的操作 (2) 串口接收 命令 (2.1) UART协议: 115200, n, 8, 1 (2.2) 1帧发送字符串格式, 以 '{'开始; '}'结束; ','分隔. 共9个10进制数字 例如: {1,2,3,4,5,6,7,8,9} (2.3) 第9位 区分 Keyboard(64) 或是 Mouse(128) 命令 例如: {0,0,0,0,0,0,0,0,64} --- 发送Keyboard命令 {0,0,0,0,0,0,0,0,128} --- 发送Keyboard命令 (3) 发送Keyboard键盘命令时 : 第1~8位 分别如下 (3.1) 第1位 : Key_Release = 0x00, Left_Control = 0x01, Left_Shift = 0x02, Left_Alt = 0x04, Left_GUI = 0x08, Right_Control = 0x10, Right_Shift = 0x20, Right_Alt = 0x40, Right_GUI = 0x80, 例如: {8,0,0,0,0,0,0,0,64} --- 发送 Win_Key键 {128,0,0,0,0,0,0,0,64} --- 发送 WinApp_Key键 {32,0,0,0,0,0,0,0,64} --- 发送 右Shift键 (3.2) 第2位 : 保留,不使用,一律填0 (3.3) 第3~8位 : 可以同时发送6个Keyboard按键 例如: {0,0,4,5,6,7,8,9,64} --- 发送 'abcdef'键 {2,0,4,5,6,7,8,9,64} --- 按住 左Shift 发送 'abcdef'键 => 'ABCDEF' {0,0,0,5,0,7,0,9,64} --- 发送 'bdf'键 (0表示 无按键) 按键码 可参阅: (HID Usage ID) http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf https://www.hiemalis.org/~keiji/PC/scancode-translate.pdf https://gist.github.com/MightyPork/6da26e382a7ad91b5496ee55fdc73db2 http://www.usb.org/developers/hidpage/Hut1_12v2.pdf (4) 发送Mouse鼠标命令时 : 第1~8位 分别如下 (4.1) 第1位 : Button_Release = 0x00, Left_Button = 0x01, Right_Button = 0x02, Mid_Button = 0x04, 例如: {1,0,0,0,0,0,0,0,128} --- 点击 左键 {2,0,0,0,0,0,0,0,128} --- 点击 右键 {4,0,0,0,0,0,0,0,128} --- 点击 中键 (4.2) 第2~4位 : 移动(X,Y), 滚轮(Wheel) X: -127~127:左右移动鼠标 Y: -127~127:上下移动鼠标 Wheel: -127~127:上下转动滚轮 例如: {0,20,-10,0,0,0,0,0,128} --- 鼠标 右移20,上移10 {0,0,0,-30,0,0,0,0,128} --- 滚轮-30 (4.2) 第5~8位 : 保留,不使用,一律填0
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值