目前市面上最成熟的 USB Host 库当属Oleg Mazurov的USB Host Shield Library 2.0(项目地址 https://github.com/felis/USB_Host_Shield_2.0),几乎可以兼容市面上的所有 Arduino 板,从 Atmel 328P/32U4到 ATMage 2560 再到 EP32都能够使用这个库来驱动 USB 设备。这次我专门为 FireBeetle设计了一个Shield 使得FireBeetle能够驱动一些USB 设备。
首先,依然是硬件设计部分。USB Host Shield Library是基于 MAX3421e实现的,下面可以看作是这个芯片的一个最小系统,需要外接一颗12Mhz 的晶振。此外可以看到这个芯片本身带有GPIO引脚,可以用来做 GPI或者 GPO ,在一些情况下可以弥补主控 GPIO 不足的缺点,但是本次设计并未使用这些引脚。

上述芯片和 FireBeetle接口如下图,二者是通过 SPI 来进行通讯的。下图中IO18/23/19/13 就是 SPI 接口。特别注意,我在板子上预留了 JP3/JP2 这是为以后堆叠使用可能发生的引脚冲突预留的,正常使用的时候 JP1和JP3(称作短接电阻) 是需要焊接起来的;JP2 的功能是预留给某些情况下 USB 设备需要功耗较高,FireBeetle 无法提供时就需要考虑使用外部5V进行供电,此时如果你还使用FIreBeetle 上的 USB端口调试,既有可能出现外部5V 和USB 上面的5V 电压不同的情况。因此,这种情况下需要断开 JP2。

接下来继续进行硬件设计,绘制PCB。特别注意,下面电路图时有缺陷的,再晶振下面走线,有可能对信号有影响。建议需要的朋友重新设计 PCB。

3D 预览结果:

之后,打板,焊接成品如下,黑色PCB 很 DFRobot 出品的感觉。

接下来就用这个板子配合 FireBeetle来实现一个 USB 键盘转蓝牙的作品。
- 为了驱动这个 USB Host Shield 需要对 USB Host Library 做一点修改。
- 1 UsbCore.h 中修改为我们使用的SS和INT Pin
1 2 3 4 | #elif defined(ESP32) //LABZ typedef MAX3421e<P5, P17> MAX3421E; // ESP32 boards typedef MAX3421e<P13, P26> MAX3421E; // ESP32 boards // LABZ #else |
- 2 usbhost.h 中修改为我们使用的 SPI
1 2 3 4 | #elif defined(ESP32) //LABZ typedef SPi< P18, P23, P19, P5 > spi; typedef SPi< P18, P23, P19, P13 > spi; // LABZ #else |
2. 蓝牙键盘功能的实现。这里我们需要用到 ESP32 BLE Keyboard library,在 https://github.com/T-vK/ESP32-BLE-Keyboard 可以找到这个项目。
3.最终的代码如下:
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 | #include <hidboot.h> #include <SPI.h> #include <BleKeyboard.h> BleKeyboard bleKeyboard; class KbdRptParser : public KeyboardReportParser { void Parse(USBHID * hid, bool is_rpt_id, uint8_t len, uint8_t * buf); }; void KbdRptParser::Parse(USBHID * hid, bool is_rpt_id, uint8_t len, uint8_t * buf) { if (bleKeyboard.isConnected()) { KeyReport _keyReport; _keyReport.modifiers = buf[ 0 ]; for ( int i = 2 ; i < 8 ; i + + ) { _keyReport.keys[i - 2 ] = buf[i]; } bleKeyboard.sendReport( & _keyReport); } Serial.print ( "Received " ); Serial.println (len); for ( int i = 0 ; i < len; i + + ) { Serial.print (buf[i]); Serial.print ( " " ); } Serial.println ( " " ); } USB Usb; HIDBoot<USB_HID_PROTOCOL_KEYBOARD> HidKeyboard( & Usb); KbdRptParser Prs; void setup () { Serial.begin ( 115200 ); Serial.println ( "Start" ); if (Usb.Init() = = - 1 ) Serial.println ( "OSC did not start." ); bleKeyboard.begin(); delay ( 200 ); HidKeyboard.SetReportParser( 0 , & Prs); } void loop () { Usb.Task(); } |
简单的说上电之后,在PC上搜索蓝牙设备,配对之后就可以通过 USB Host Shield 解析键盘数据,然后将这个数据直接填写到蓝牙键盘的结构体中,FIreBeetle 随即将这个信息传递给 PC,PC上就能收到你的按键信息了。

电路图文件和PCB 在这里下载:
工作的视频可以在 B站看到