他这个需求多少有点非主流,看着像是蓝牙键盘,但是物理上却是USB HID设备,并不是BLE的HID,BLE在这里只是用来吸罢手机发送的数据。
起初我也没太负责想如何实现,就随手发到我们的嵌入式互换群里,各路高手们纷纭提出了自己的方案:

这4种方案从事理上来说都可以实现我这个同学的需求,说到我这个大学同学,请许可我临时跑个题,当年上学时,他住我宿舍正对面,是个不折不扣的单片机迷,最初玩51单片机,后来捣鼓AVR单片机、然后自学uCosII操作系统,后来不知道怎么又自学了Java,技能上特殊爱专研。大学毕业后,我们就一南一北各自闯天涯了,他南下深圳直接事情了,从事安卓干系研发事情,这么多年一贯在这个领域,在深圳也是纯凭借个人能力攒钱买了屋子。不得不感慨,干移动互联网的便是比干嵌入式的更随意马虎搞钱啊。

那他为什么要整这个USB蓝牙吸收器呢?由于他们新开拓的这款APP用在国外,而这个蓝牙吸收器是用来掌握彩票机的,大概意思便是在手机点一点,实现在彩票机购买彩票的功能。至于为什么不直接在彩票机上购买,他给我阐明了一通智能的观点,听的我一头懵逼。
最近和BLE老扯上关系,前段韶光才研究了那个超便宜的BLE芯片KT6368A,这又来了一个BLE的干系需求,索性就考虑用群友heibus提出的CH9328+KT6368A方案来实现看看。
不过随着后来进一步的需求沟通,创造用CH9328+KT6368A还弗成,缘故原由是它手机端发送的按键并不是原封不动的透传过去就行了,须要做转换,比如说手机端发送十进制1,对应到USB HID 两组8字节的16进制数据是:00 00 08 00 00 00 00 00和00 00 00 00 00 00 00 00,这样的话纯挚硬件肯定是实现不了,须要涉及到软件开拓。
关于00 00 08 00 00 00 00 00和00 00 00 00 00 00 00 00这两组数据分别表示什么含义,那就得大略补习点USB HID的根本知识了。
键盘发送给PC的数据每次是8个字节:BYTE1 BYTE2 BYTE3 BYTE4 BYTE5 BYTE6 BYTE7 BYTE8定义分别是:BYTE1 :分外按键,详细各位含义如下: |--bit0: Left Control是否按下,按下为1 |--bit1: Left Shift 是否按下,按下为1 |--bit2: Left Alt 是否按下,按下为1 |--bit3: Left GUI 是否按下,按下为1 |--bit4: Right Control是否按下,按下为1 |--bit5: Right Shift 是否按下,按下为1 |--bit6: Right Alt 是否按下,按下为1 |--bit7: Right GUI 是否按下,按下为1 BYTE2:保留
BYTE3-BYTE8 :这六个为普通按键,键值可以参考USB HID to PS/2 Scan Code Translation Table.
举几个例子,比如按键a对应的一帧数据是:00 00 0x04 0x00 00 00 00 00,第3字节04便是由下面这个表定义的:
这么说有点抽象,来点更直不雅观的,电脑端我们可以用Bushound等USB剖析软件,我这里用的是Free USB Analyzer :
我用的条记本电脑,先外接一个USB键盘在软件左侧找到USB键盘对应的设备,开始监控,这里只选择Raw Data View3.按一下按键a并松开,这时软件界面就会显示收到了一串数据,它实在是对应了两组8字节数据,可以看到a确实对应04,其余00 00 00 00 00 00 00 00表示的是按键弹起
如果一贯按住a不松手,那么显示的就会是如下信息:
只有当你弹起按键a时才会显示00 00 00 00 00 00 00 00
如果你要同时按下并松开SHIFT+a组合按键,那么对应的数据就如下:
第一个字节就表示左侧的Shift键。
当然如果是你先按下Shift键,再按下a键,再松开a键,末了松开Shift键,那么就对应4组数据,分别为:
刚开始我并不知道这些USB的根本知识,为了搞清楚花了不少韶光。再次回到他的蓝牙吸收器需求,手机端输入的范围是数字1-83,有的数字对应2个8字节数据,表示的是一个按键的按下和松开,有的数字对应4个字节,表示的是Shift+按键的组合按下和松开,并且每8个字节数据之间的韶光间隔是200ms。
既然KT6368A弗成,那就换一个可以编程的蓝牙模块,比如TI的CC2541模块、Nordic NRF51822模块都可以,由于我原来支持过NXP的QN9021芯片,对它相对熟一点,以是就用QN9021来实现了。
用QN9021来实现上述软件功能(蓝牙吸罢手机发送过来的一串数据,然后转码输出)本来我以为分分钟就搞定了,结果实际调试起来并不是想象的那么大略。由于常规的蓝牙透传利用办法是串口吸收数据然后蓝牙发送,这个需求恰好是一个反向的操作。个中涉及到几个关键的问题:
手机端发送过来的是一串长度可能长、可能短的数据。由于QN9021是BLE 4.0芯片,一次发送字节最多是20个字节,以是要考虑超过20字节的情形。蓝牙芯片一边蓝牙吸收数据,一边串口发送数据,要考虑串口没有发送完,蓝牙又来数据的的情形。手机发送的不同键值,程序里要实现转码(有的是对应发送2个8字节数据,有的是对应4个8字节数据,每个8字节数据中间都是200ms)的代码实现问题。有履历的程序高手可能不以为是什么问题,但是对我这样好久没实际写代码的人,还是折腾了不少韶光。
上述问题1只能通过手机端分包来办理,问题2办理办法是加一个行列步队,把蓝牙吸收的数据放到行列步队里缓存起来,串口从行列步队取数发送。问题3我是在200ms定时器函数里通过设置标志位switch/case做了一个小状态机来实现的。
末了我们再来总结下这几种方案,
方案
特点
价格(元器件)
CH551+KT6368A
CH551可编程,蓝牙只透传不编程
几元钱
CH9328+BLE (NRF51822/CC2541/QN9021等)
BLE 可编程,CH9328硬件实现串口转USB HID
数十元
单BLE(NRF52840/QN9080等)
SOC可编程
数十元
CH340+KT6368A
硬件不编程,PC上编程
几元钱
这几种方案从硬件角度来看,都具备BLE和USB功能,只不过软件部分实现的位置不同,终极都可以实现所须要的功能。
至于在实际项目或产品中,到底选取哪一种方案,实际上是须要综合考虑多方面的成分的,比如开拓周期、本钱、软件开拓难易、乃至芯片是否好买等。
下一步我会再研究第一个方案的实现,即CH551+KT6368A,后面大概率用这个方案,缘故原由大家该当都明白吧。









