复合设备是啥,通俗讲就是一个USB物理设备可以实现多个功能,在主机端可以看到多个设备。通常实现HID复合设备有两种方式。第一种是使用同一个接口,修改报告描述符,增加一个功能集合,同时需要使用报告ID来区分哪一个设备,这样主机端和设备端需要增加报告ID处理,但只需要两个端点来实现功能,对于端口资源较少的MCU可以使用;第二种是使用两个接口,每个接口对应不同的报告描述符,不需要特意使用报告ID来区分,但不同接口使用独立的端点。
本文章使用不同接口来实现,基于GD32例程开发。
-
开发准备
(1)下载官方GD32F1x0_Firmware_Library_v3.1.0,使用GD32F1x0_Firmware_Library_v3.1.0\Projects\USBD\HID_custom工程
(2)keil5添加GD系列
(3)连接GDlink和串口工具 -
移植代码
2.1 修改控制控制USBDP上拉电阻引脚,(内部无法直接控制上下拉,因此增加此电路,否则主机不会枚举设备)
#define USB_PULLUP GPIOC //PORT
#define USB_PULLUP_PIN GPIO_PIN_13 //PIN
#define RCC_AHBPeriph_GPIO_PULLUP RCU_GPIOC //时钟
2.2 增加串口1输出调试信息,main函数里添加:
/* uart configuration */
gd_eval_com_init(EVAL_COM1);
添加如下代码实现printf功能
int fputc(int ch, FILE *f)
{
usart_data_transmit(EVAL_COM1, (uint8_t)ch);
while(RESET == usart_flag_get(EVAL_COM1, USART_FLAG_TBE));
return ch;
}
int main(void)
{
/* system clocks configuration */
rcu_config();
/* keys configuration */
key_config();
/* leds configuration */
led_config();
//gd_eval_led_on(LED1);
/* GPIO configuration */
gpio_config();
/* uart configuration */
gd_eval_com_init(EVAL_COM1);
/* USB device configuration */
usbd_core_init(&usb_device_dev);
/* NVIC configuration */
nvic_config();
/* enabled USB pull-up */
gpio_bit_reset(USB_PULLUP, USB_PULLUP_PIN);//使能上拉
/* now the usb device is connected */
usb_device_dev.status = USBD_CONNECTED;
printf("a usart transmit test example!");
while (1)
{
};
}
2.3 修改USB相关描述符
2.3.1 设备描述符:不需要修改
const usb_descriptor_device_struct device_descripter =
{
.Header =
{
.bLength = USB_DEVICE_DESC_SIZE,
.bDescriptorType = USB_DESCTYPE_DEVICE
},
.bcdUSB = 0x0200,
.bDeviceClass = 0x00,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = USBD_EP0_MAX_SIZE,
.idVendor = USBD_VID,
.idProduct = USBD_PID,
.bcdDevice = 0x0200,
.iManufacturer = USBD_MFC_STR_IDX,
.iProduct = USBD_PRODUCT_STR_IDX,
.iSerialNumber = USBD_SERIAL_STR_IDX,
.bNumberConfigurations = USBD_CFG_MAX_NUM
};
2.3.2 配置描述符:需要增加第二个接口的接口描述符,端点描述符
const usb_descriptor_configuration_set_struct configuration_descriptor =
{
.Config =
{
.Header =
{
.bLength = sizeof(usb_descriptor_configuration_struct),
.bDescriptorType = USB_DESCTYPE_CONFIGURATION
},
.wTotalLength = CUSTOMHID_CONFIG_DESC_SIZE,
.bNumInterfaces = 0x02, //==接口数修改为2==
.bConfigurationValue = 0x01,
.iConfiguration = 0x00,
.bmAttributes = 0xc0,
.bMaxPower = 0x32
},
.HID_Interface =
{
.Header =
{
.bLength = sizeof(usb_descriptor_interface_struct),
.bDescriptorType = USB_DESCTYPE_INTERFACE
},
.bInterfaceNumber = 0x00, //==接口序号为0,表示第一个接口==
.bAlternateSetting = 0x00,
.bNumEndpoints = 0x02, //==使用两个接口==
.bInterfaceClass = 0x03,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.iInterface