HID高速设备1024byte------上下位机搭建

490 阅读3分钟

Hid High Speed Device 上下位机搭建

HID设备全称:Human Interface Devices ,我们常使用的鼠标键盘,就是HID设备,当然不止这些了,随着USB速率不断提高,HID设备可以用在很多方面了。另外HID设备有一个优点就是免驱,正因为如此,笔者认为在使用USB通信,做上下位机开发,首选HID。像CDC这种(BULK传输方式),很多时候涉及到驱动问题,操作比较麻烦,特别对于用户小白,压根就不想关心这个,所以不是很建议。

在不同速度下,HID设备端点大小有很大的差异,下面是1笔事务下的速率。

低速设备:最大8byte/10ms 800byte/s 左右

全速设备:最大64byte/1ms 64000byte/s 左右

高速设备:最大1024byte/0.125ms 0.125ms最多可3笔事务,可达 24M/s 左右

前期准备:

1.带USB 2.0高速功能的MCU (笔者使用的NXP RT1052)

2.libusb 1.x 版本

3.VS2015 keil (IDE环境选择很多,因人而异)

下位机

1.描述符基本构成

00.png

部分描述符展示:

Device Descriptor:
------------------------------
0x12    bLength
0x01    bDescriptorType
0x0200  bcdUSB
0x00    bDeviceClass      
0x00    bDeviceSubClass   
0x00    bDeviceProtocol   
0x40    bMaxPacketSize0   (64 bytes)
0x0483  idVendor
0x5700  idProduct
0x00C8  bcdDevice
0x01    iManufacturer   "L17"
0x02    iProduct        "Hid High Boot"
0x03    iSerialNumber
0x01    bNumConfigurations
​
Configuration Descriptor:
------------------------------
0x09    bLength
0x02    bDescriptorType
0x0029  wTotalLength   (41 bytes)
0x01    bNumInterfaces
0x01    bConfigurationValue
0x00    iConfiguration
0xC0    bmAttributes   (Self-powered Device)
0x19    bMaxPower      (50 mA)
​
Interface Descriptor:
------------------------------
0x09    bLength
0x04    bDescriptorType
0x00    bInterfaceNumber
0x00    bAlternateSetting
0x02    bNumEndPoints
0x03    bInterfaceClass      (Human Interface Device Class)
0x00    bInterfaceSubClass   
0x00    bInterfaceProtocol   
0x00    iInterface
​
HID Descriptor:
------------------------------
0x09    bLength
0x21    bDescriptorType
0x0110  bcdHID
0x21    bCountryCode
0x01    bNumDescriptors
0x22    bDescriptorType   (Report descriptor)
0x001B  bDescriptorLength
​
Endpoint Descriptor:
------------------------------
0x07    bLength
0x05    bDescriptorType
0x81    bEndpointAddress  (IN endpoint 1)
0x03    bmAttributes      (Transfer: Interrupt / Synch: None / Usage: Data)
0x0400  wMaxPacketSize    (1 x 1024 bytes)
0x01    bInterval         (1 microframes)
​
Endpoint Descriptor:
------------------------------
0x07    bLength
0x05    bDescriptorType
0x02    bEndpointAddress  (OUT endpoint 2)
0x03    bmAttributes      (Transfer: Interrupt / Synch: None / Usage: Data)
0x0400  wMaxPacketSize    (1 x 1024 bytes)
0x01    bInterval         (1 microframes)

除上述展示的描述符外,另外一个特别重要的HID报告描述符也值得注意(特别是:数据域的数量,每个数据域的长度),HID描述符比较复杂就不展开说了,可以下载官方文档或者用报告描述符生成工具去配置深入了解。

Human Interface Devices (HID) Information | USB-IF

HID Descriptor Tool | USB-IF

2.hid发送接收测试

usb_status_t USB_DeviceHidCallback(class_handle_t handle, uint32_t event, void *param)
{
    usb_status_t error = kStatus_USB_Error;
​
    switch (event)
    {
        case kUSB_DeviceHidEventSendResponse:  //发送完成
        {
            iSSendEnd = true;
        }
        break;
​
        case kUSB_DeviceHidEventRecvResponse:    
            if (g_UsbDeviceHidGeneric.attach)
            {
                error = USB_DeviceHidRecv(g_UsbDeviceHidGeneric.hidHandle, USB_HID_GENERIC_ENDPOINT_OUT,
                                     (uint8_t *)g_UsbDeviceHidGeneric.buffer,USB_HID_GENERIC_OUT_BUFFER_LENGTH);
                
                HID_SendBuffer((uint8_t *)g_UsbDeviceHidGeneric.buffer);   //将接收的数据转发给上位机
//              pUSBHidOutCallBack(g_HidOutBuf,USB_HID_GENERIC_OUT_BUFFER_LENGTH);
            }
            break;
        case kUSB_DeviceHidEventGetReport:
        case kUSB_DeviceHidEventSetReport:
        case kUSB_DeviceHidEventRequestReportBuffer:
            error = kStatus_USB_InvalidRequest;
            break;
        case kUSB_DeviceHidEventGetIdle:
        case kUSB_DeviceHidEventGetProtocol:
        case kUSB_DeviceHidEventSetIdle:
        case kUSB_DeviceHidEventSetProtocol:
            break;
        default:
            break;
    }
​
    return error;
}
​
usb_status_t HID_SendBuffer(unsigned char* buff)
{
    iSSendEnd = false;
    return USB_DeviceSendRequest(g_UsbDeviceHidGeneric.deviceHandle,USB_HID_GENERIC_ENDPOINT_IN,buff,HS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE);  
}

下位机将接收到的端点OUT数据,再通过端点IN转发给上位机。

上位机

上位机部分笔者调用的是第三方库:libusb 当然也可以用微软自带库开发。下面简单介绍下,开发流程

1.遍历Windows端口所有usb设备,获取设备数量
libusb_get_device_list
​
2.遍历所有设备的描述符信息,通过PID VID等信息找到我们指定的设备
libusb_get_device_descriptor
​
3.打开指定设备
libusb_open
​
4.根据指定设备查询设备接口类型(项目中有可能是组合设备,存在不同接口类型),找到HID接口,
获取该接口端点IN OUT5.端点上通信(hid 是中断传输,所以调用中断传输sdk)
libusb_interrupt_transfer

具体代码就不展示了,毕竟也是个人成果。

void CHidDealDlg::OnBnClickedButtonSend()
{
#if 1
    int i;
    for (i=0;i<1024;i++)
    {
        hid20buf[i] = i & 0x00ff;
    }
#endif
​
    HidDevice.HID20_Write(hid20buf,1024,10);
​
    InsertMessageToListBox(TEXT("Send 1024 byte data to Mcu!!!"));
}
​
unsigned int WINAPI  xUSB_RxThread(PVOID lpParameter)
{
    CHidDealDlg* pThis = (CHidDealDlg*)lpParameter;
​
    int dataLen;
​
    while (1)
    {
        dataLen = HidDevice.HID20_Read(hid20_Rxbuf,10);
​
        if (dataLen > 0)
        {
            pThis->InsertMessageToListBox(TEXT("Receive 1024 byte data success!!!"));
        }
​
        Sleep(1);
    }
​
    return 0;
}

测试结果如下:

02.png

01.png