23182浏览
查看: 23182|回复: 1

[ESP8266/ESP32] USB Host Shield 通过USB Hub 连接多个键盘

[复制链接]
USB Host Shield 本身是支持USBHub的,这样我们可以方便的一次性连接多个USB设备。这次以USB键盘为例进行测试。
USB Hub 的使用还是比较简单的,连接好之后,建议运行 USB_Host_Shield_Library_2.0\examples\hub_demo 这个示例代码进行测试,它会枚举当前USBHub上的所有 USB 设备的描述符信息,通过这样的方法我们可以知道硬件是否能够工作正常。
前述代码测试通过后,我们就可以编写代码来获得按键信息了。
1. KBUnderHub.ino 代码中必须使用 USBHub ,之后,因为测试有3个键盘,所以要声明 kb1 kb3 三个设备
  1. USB Usb;
  2. USBHub     Hub(&Usb);
  3. KBSET kb1(&Usb);
  4. KBSET kb2(&Usb);
  5. KBSET kb3(&Usb);
复制代码
2. KeyboardSets.h 代码中,申明一些我们需要的结构体如下:

  1. // 当前支持的键盘数量
  2. #define KBNUM 3
  3. class KBSET : public HIDUniversal {
  4.   public:
  5.     KBSET(USB *p) : HIDUniversal(p) {};
  6.     bool connected() {
  7.       return HIDUniversal::isReady();
  8.     };
  9.     // 本次收到数据的键盘编号
  10.     uint8_t  Current;
  11.     // 存放第x个键盘是否有改变发生的标记
  12.     bool     Changed[KBNUM];
  13.     // 存放第x个键盘当前收到的缓冲区长度
  14.     uint8_t  BufferSize[KBNUM];
  15.     // 存放第x个键盘收到的缓冲区数据
  16.     uint8_t  Buffer[KBNUM][64];
  17.     // 存放第x个键盘的PID 和 VID
  18.     uint16_t PID[KBNUM];
  19.     uint16_t VID[KBNUM];
  20.   private:
  21.     void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); // Called by the HIDUniversal library
  22.     uint8_t  BufferSizeOld[KBNUM];
  23.     uint8_t  BufferOld[KBNUM][64];
  24.     // 当前收到的键盘数据总数
  25.     uint8_t  TotolKB;
  26.     uint8_t OnInitSuccessful() { // Called by the HIDUniversal library on success
  27.       KBSET::TotolKB = 0;
  28.       for (uint8_t j = 0; j < KBNUM; j++) {
  29.         for (uint8_t i = 0; i < 64; i++) {
  30.           KBSET::BufferOld[j][i]=0xFF;
  31.         }
  32.       }
  33.       return 0;
  34.     };
  35. };
复制代码
3. KeyboardSets.cpp
  1. #include "KeyboardSets.h"
  2. void KBSET::ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
  3.   /*
  4.     if (len && buf)  {
  5.       Notify(PSTR("\r\n"), 0x80);
  6.       for (uint8_t i = 0; i < len; i++) {
  7.         D_PrintHex<uint8_t > (buf[i], 0x80);
  8.         Notify(PSTR(" "), 0x80);
  9.       }
  10.     }
  11.   */
  12.   // 在 KBSET 中查找记录
  13.   KBSET::Current = 0xFF;
  14.   for (uint8_t i = 0; i < KBNUM; i++) {
  15.     //
  16.     if ((KBSET::PID[i] == HIDUniversal::PID) && (KBSET::VID[i] == HIDUniversal::VID)) {
  17.       KBSET::Current = i;
  18.     }
  19.   }
  20.   // 如果查找不到
  21.   if (KBSET::Current == 0xFF) {
  22.     KBSET::Current = KBSET::TotolKB;
  23.     KBSET::PID[KBSET::Current] = HIDUniversal::PID;
  24.     KBSET::VID[KBSET::Current] = HIDUniversal::VID;
  25.     KBSET::BufferSize[KBSET::Current] = len;
  26.     KBSET::TotolKB++;
  27.   }
  28.   // 检查本次数据和上次数据是否有差别
  29.   if (memcmp(BufferOld[KBSET::Current], buf, len) == 0) {
  30.     // 没有差别
  31.     KBSET::Changed[KBSET::Current] = false;
  32.   } else {
  33.     memcpy(Buffer[KBSET::Current], buf, len);
  34.     // 有差别
  35.     KBSET::Changed[KBSET::Current] = true;
  36.     memcpy(BufferOld[KBSET::Current], buf, len);
  37.     Serial.print("VID:"); Serial.print(KBSET::VID[KBSET::Current],HEX);
  38.     Serial.print(" PID:"); Serial.println(KBSET::PID[KBSET::Current],HEX);
  39.     for (uint8_t i = 0; i < KBSET::BufferSize[KBSET::Current]; i++) {
  40.       Serial.print((byte)(KBSET::Buffer[KBSET::Current][i]), HEX);
  41.       Serial.print(" ");
  42.     }
  43.     Serial.println("");
  44.   }
  45. }
复制代码

工作流程:当有按键事件发生时,库会调用 ParseHIDData() 这个函数,从设备获得的设备数据放在buf,产生数据的设备PID VID HIDUniversal::PIDHIDUniversal::VID中。之后,我们会在KBSET::PIDVID数组中查找当前产生数据的设备是否已存在,如果没有话,将这个设备的PIDVID 加入数组中。之后再将改设备产生的数据存放到Buffer中。之后,再判断新取得的数据和之前的BufferOld中保存的是否相同,如果相同就打印输出。
这样,我们就能分别获得三个设备产生的按键信息。
我是用了一个大键盘,一个小键盘和一个barcodescanner 作为测试设备,可以看到串口能够输出。







lrj0331  学徒

发表于 2023-10-4 20:02:48

hello啊,请问usb host shield上的usb端口名称叫什么呢?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail