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_t Current;
- // 存放第x个键盘是否有改变发生的标记
- bool Changed[KBNUM];
- // 存放第x个键盘当前收到的缓冲区长度
- uint8_t BufferSize[KBNUM];
- // 存放第x个键盘收到的缓冲区数据
- uint8_t Buffer[KBNUM][64];
- // 存放第x个键盘的PID 和 VID
- uint16_t PID[KBNUM];
- uint16_t VID[KBNUM];
- private:
- void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); // Called by the HIDUniversal library
- uint8_t BufferSizeOld[KBNUM];
- uint8_t BufferOld[KBNUM][64];
- // 当前收到的键盘数据总数
- uint8_t TotolKB;
- 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[j][i]=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[i], 0x80);
- Notify(PSTR(" "), 0x80);
- }
- }
- */
-
- // 在 KBSET 中查找记录
- KBSET::Current = 0xFF;
- for (uint8_t i = 0; i < KBNUM; i++) {
- //
- if ((KBSET::PID[i] == HIDUniversal::PID) && (KBSET::VID[i] == HIDUniversal::VID)) {
- KBSET::Current = i;
- }
- }
- // 如果查找不到
- if (KBSET::Current == 0xFF) {
- KBSET::Current = KBSET::TotolKB;
- KBSET::PID[KBSET::Current] = HIDUniversal::PID;
- KBSET::VID[KBSET::Current] = HIDUniversal::VID;
- KBSET::BufferSize[KBSET::Current] = len;
- KBSET::TotolKB++;
- }
-
- // 检查本次数据和上次数据是否有差别
- if (memcmp(BufferOld[KBSET::Current], buf, len) == 0) {
- // 没有差别
- KBSET::Changed[KBSET::Current] = false;
- } else {
- memcpy(Buffer[KBSET::Current], buf, len);
- // 有差别
- KBSET::Changed[KBSET::Current] = true;
- memcpy(BufferOld[KBSET::Current], buf, len);
- Serial.print("VID:"); Serial.print(KBSET::VID[KBSET::Current],HEX);
- Serial.print(" PID:"); Serial.println(KBSET::PID[KBSET::Current],HEX);
- for (uint8_t i = 0; i < KBSET::BufferSize[KBSET::Current]; i++) {
- Serial.print((byte)(KBSET::Buffer[KBSET::Current][i]), HEX);
- Serial.print(" ");
- }
- Serial.println("");
- }
- }
复制代码
工作流程:当有按键事件发生时,库会调用 ParseHIDData() 这个函数,从设备获得的设备数据放在buf,产生数据的设备PID和 VID 在HIDUniversal::PID和HIDUniversal::VID中。之后,我们会在KBSET::PIDVID数组中查找当前产生数据的设备是否已存在,如果没有话,将这个设备的PID和VID 加入数组中。之后再将改设备产生的数据存放到Buffer中。之后,再判断新取得的数据和之前的BufferOld中保存的是否相同,如果相同就打印输出。 这样,我们就能分别获得三个设备产生的按键信息。 我是用了一个大键盘,一个小键盘和一个barcodescanner 作为测试设备,可以看到串口能够输出。
|