zoologist 发表于 2022-3-21 14:24:58

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 三个设备USB Usb;
USBHub   Hub(&Usb);
KBSET kb1(&Usb);
KBSET kb2(&Usb);
KBSET kb3(&Usb);
2. KeyboardSets.h 代码中,申明一些我们需要的结构体如下:
// 当前支持的键盘数量
#define KBNUM 3

class KBSET : public HIDUniversal {
public:
    KBSET(USB *p) : HIDUniversal(p) {};
    bool connected() {
      return HIDUniversal::isReady();
    };
    // 本次收到数据的键盘编号
    uint8_tCurrent;
    // 存放第x个键盘是否有改变发生的标记
    bool   Changed;
    // 存放第x个键盘当前收到的缓冲区长度
    uint8_tBufferSize;
    // 存放第x个键盘收到的缓冲区数据
    uint8_tBuffer;
    // 存放第x个键盘的PID 和 VID
    uint16_t PID;
    uint16_t VID;
private:
    void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); // Called by the HIDUniversal library
    uint8_tBufferSizeOld;
    uint8_tBufferOld;
    // 当前收到的键盘数据总数
    uint8_tTotolKB;
    uint8_t OnInitSuccessful() { // Called by the HIDUniversal library on success
      KBSET::TotolKB = 0;
      for (uint8_t j = 0; j < KBNUM; j++) {
      for (uint8_t i = 0; i < 64; i++) {
          KBSET::BufferOld=0xFF;
      }
      }
      return 0;
    };
};
3. KeyboardSets.cpp#include "KeyboardSets.h"

void KBSET::ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
/*
    if (len && buf){
      Notify(PSTR("\r\n"), 0x80);
      for (uint8_t i = 0; i < len; i++) {
      D_PrintHex<uint8_t > (buf, 0x80);
      Notify(PSTR(" "), 0x80);
      }
    }
*/

// 在 KBSET 中查找记录
KBSET::Current = 0xFF;
for (uint8_t i = 0; i < KBNUM; i++) {
    //
    if ((KBSET::PID == HIDUniversal::PID) && (KBSET::VID == HIDUniversal::VID)) {
      KBSET::Current = i;
    }
}
// 如果查找不到
if (KBSET::Current == 0xFF) {
    KBSET::Current = KBSET::TotolKB;
    KBSET::PID = HIDUniversal::PID;
    KBSET::VID = HIDUniversal::VID;
    KBSET::BufferSize = len;
    KBSET::TotolKB++;
}

// 检查本次数据和上次数据是否有差别
if (memcmp(BufferOld, buf, len) == 0) {
    // 没有差别
    KBSET::Changed = false;
} else {
    memcpy(Buffer, buf, len);
    // 有差别
    KBSET::Changed = true;
    memcpy(BufferOld, buf, len);
    Serial.print("VID:"); Serial.print(KBSET::VID,HEX);
    Serial.print(" PID:"); Serial.println(KBSET::PID,HEX);
    for (uint8_t i = 0; i < KBSET::BufferSize; i++) {
      Serial.print((byte)(KBSET::Buffer), HEX);
      Serial.print(" ");
    }
    Serial.println("");
}
}

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





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

hello啊,请问usb host shield上的usb端口名称叫什么呢?
页: [1]
查看完整版本: USB Host Shield 通过USB Hub 连接多个键盘