目录

  • 简介
  • 1、引脚介绍
    • 部分引脚说明
  • 2、工作模式
    • 上传速度设置
    • 工作模式设置:
  • 3、电路连接
  • 4、数据格式
    • 通信协议
  • 5、驱动程序
    • 定义一个缓存空间
    • 创建键码数组
    • 键码发送
  • 6、参考资料
  • 资料获取

简介

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

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

.

.

.

1、引脚介绍

部分引脚说明

(详细说明在 参考资料 中的网址下载说明文档)

.

.

.

.

2、工作模式

上传速度设置

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

.

.

工作模式设置:

工作模式 IO2电平 IO3电平 IO4电平 功能说明
模式0 1 1 1 该模式仅支持将可见ASCII码(如 a-z、0-9、@、#、$ 等)对应的字符转成标准的USB键值。特殊功能:接收到的串口数据包如果遇到 0x1B 时,则丢弃当前包中 0x1B 之后的数据,并将 0x1B 转换成回车键。
模式1 1 0 1 该模式仅支持将可见ASCII码(如 a-z、0-9、@、#、$ 等)对应的字符转成标准的USB键值。
模式2 1 1 0 该模式仅支持将可见ASCII码(如 a-z、0-9、@、#、$ 等)对应的字符转成标准的USB键值。特殊功能:接收到的串口数据包如果遇到 0x28 时,将 0x28 转换成回车键。
模式3 0 1 1 该模式为透传模式,不仅仅用于传输可见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键盘 目录下。

原理篇4、CH9328使用相关推荐

  1. 《CDN 之我见》系列二:原理篇(缓存、安全)

    2019独角兽企业重金招聘Python工程师标准>>> <CDN之我见>共由三个篇章组成,分为原理篇.详解篇和陨坑篇.本篇章适合那些从未接触过.或仅了解一些 CDN 专业 ...

  2. 检查压缩包是否损坏_修复损坏的gzip压缩文件之原理篇

    接修复损坏的gzip压缩文件之原理篇,再次引用GZIP结构图: 已知修复一个损坏的gzip文件的关键环节在于找到下一个正常压缩包的起始点.根据结构图中的信息可知,每个压缩包的开始结构中有是否到达尾部标 ...

  3. Tomcat 原理篇

    TOMCAT 原理篇 一.Tomcat 组成(Tomcat 由以下组件组成) 1.server a) Server是一个Catalina Servlet容器: b) Server 可以包含一个或多个s ...

  4. React Native JSBundle拆包之原理篇

    概述 RN作为一款非常优秀的移动端跨平台开发框架,在近几年得到众多开发者的认可.纵观现在接入RN的大厂,如qq音乐.菜鸟.去哪儿,无疑不是将RN作为重点技术栈进行研发. 不过,熟悉RN的开发者也知道, ...

  5. 通过“四大行为”对WCF的扩展[原理篇]

    整个WCF框架由两个基本的层次构成,即服务模型层和信道层.对信道层的扩展主要通过针对绑定的扩展实现,具体来说就是自定义绑定元素,以及相关的信道管理器(信道监听器和信道工厂).信道来改变对消息的处理和传 ...

  6. 《CDN 之我见》原理篇——CDN的由来与调度

    2019独角兽企业重金招聘Python工程师标准>>> CDN是将源站内容分发至全国所有的节点,从而缩短用户查看对象的延迟,提高用户访问网站的响应速度与网站的可用性的技术.它能够有效 ...

  7. 原理篇 | 推荐系统之矩阵分解模型

    导语:本系列文章一共有三篇,分别是 <科普篇 | 推荐系统之矩阵分解模型> <原理篇 | 推荐系统之矩阵分解模型> <实践篇 | 推荐系统之矩阵分解模型> 第一篇用 ...

  8. Kubernetes应用部署模型解析(原理篇)

    2019独角兽企业重金招聘Python工程师标准>>> Kubernetes应用部署模型解析(原理篇) 博客分类: Kubernetes [编者按]Kubernetes可用来管理Li ...

  9. [zz]GMM-HMM语音识别模型 原理篇

    GMM-HMM语音识别模型 原理篇 分类: Data Structure Machine Learning Data Mining 2014-05-28 20:52 20662人阅读 评论(34) 收 ...

  10. InnoDB原理篇:Change Buffer是如何提升索引性能的?

    前言 相信很多小伙伴设计索引时,考虑更多的是索引是否能覆盖大部分的业务场景,却忽略了索引的性能. 什么?不同的索引,性能还不一样? 是的,这要从change buffer说起.   Change Bu ...

最新文章

  1. 葡萄城报表介绍:复杂报表
  2. 编程语言中的Lambda 函数是如何产生的 它究竟有什么用
  3. MSMQ 安装问题的解决过程
  4. 四则运算(可怜的二柱子)2
  5. UVa 1368 - DNA Consensus String
  6. 基于FP5207的5V升12V电路设计
  7. 拓扑学+计算机,拓扑学与物理学结合,量子计算机正在成为现实
  8. S3C2440c语言汇编传参点灯
  9. 利用FlashPaper在web页面中显示PDF文件(兼容各浏览器)
  10. iso国家代码 三位字母_ISO 2字母语言代码
  11. stderr/stdout用法
  12. 移动机器人下位机软件
  13. 12月31日起涉线上支付的微信小程序需设置订单中心页
  14. echarts - 折线图 - 每分钟刷新数据并显示
  15. 201612-3-炉石传说
  16. IE浏览器对象不支持Blob属性或方法,IE浏览器不支持canvas toBlob()方法的Polyfill
  17. 适用于 Windows 的 5 大 PDF 编辑器
  18. 华为配置动态路由ISIS协议
  19. 连载 大学生求职七大昏招(五)说谎 4
  20. 省常高NOIP模拟 寻梦fantasy

热门文章

  1. VS打开后界面找不到win32或者x64的选项怎么办?
  2. 013、静态网页开发
  3. 无压低温烧结银:SiC芯片封装的关键材料
  4. 虚拟机(Ubuntu18.04版本)中文字体乱码或混乱的一种解决方案
  5. 保险公司风控是什么意思?风控时代买保险要注意哪些问题?
  6. 西乔:我在过着很奢侈的生活
  7. 2017年最受欢迎的十篇神秘的程序员漫画
  8. 写给程序猿的把妹指南:概述篇
  9. 天腾动力携Motinova 和 Welling E-bike电驱新品亮相EUROBIKE 2022
  10. Bootstrap 4 Alpha 4发布