这一节,准备基于usb_cdc 例程修改成自定义的大数据传输,我只是抛砖引玉,如果说的有什么不对的地方还请大家指教。 在很多时候通用的usb协议是不能满足我们的使用的,比如我们要传我们自定义的数据和上位机通信(bootloader等),很多人可能会说可以用cdc虚拟串口啊还是现成的,但是这样就面临3个问题1.虚拟串口的速度根本达不到usb的最大速度,2.就是它的上位机驱动是st公司自己的,在成功驱动后显示的是st的名字,这对于很多公司来说是不可接受的。3.就是你不能按照自己的格式发送,只能按照它的要求发送数据。 不废话直接上代码: 1. 用stm32cubemx生成1个usb_cdc 例程,这里就不贴教程了,应该很简单。 2. 修改usbd_desc.c中的报告描述符,原因在与在上位机获取设备描述符时,不让上位机讲我们的设备识别成任何一种设备。 将:bDeviceClass,bDeviceSubClass,bDeviceProtocol,全部改成0x00 /* USB Standard Device Descriptor */ __ALIGN_BEGIN uint8_tUSBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { 0x12, /*bLength */ USB_DESC_TYPE_DEVICE, /*bDescriptorType*/ 0x00, /*bcdUSB */ 0x00, 0x00, /*bDeviceClass*/ 0x00, /*bDeviceSubClass*/ 0x00, /*bDeviceProtocol*/ USB_MAX_EP0_SIZE, /*bMaxPacketSize*/ LOBYTE(USBD_VID), /*idVendor*/ HIBYTE(USBD_VID), /*idVendor*/ LOBYTE(USBD_PID_FS), /*idVendor*/ HIBYTE(USBD_PID_FS), /*idVendor*/ 0x00, /*bcdDevice rel. 2.00*/ 0x02, USBD_IDX_MFC_STR, /*Index of manufacturer string*/ USBD_IDX_PRODUCT_STR, /*Index of product string*/ USBD_IDX_SERIAL_STR, /*Index of serial number string*/ USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/ } ; 3. 修改报告描述符 将接口描述数量改成1个,因为cdc通信默认使用两个接口 /*Configuration Descriptor*/ 0x09, /* bLength: ConfigurationDescriptor size */ USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */ 0x00, 0x01,// 0x02, /* bNumInterfaces: 2interface */ 0x01, /* bConfigurationValue:Configuration value */ 0x00, /* iConfiguration: Indexof string descriptor describing the configuration */ 0xC0, /* bmAttributes: selfpowered */ 0x32, /* MaxPower 0 mA */ /*********************************************************/ 然后修改接口描述符,修改接口类,接口子类等,注释掉Header Functional Descriptor,Call ManagementFunctional Descriptor,ACM Functional Descriptor,Union FunctionalDescriptor 修改端点描述符 整个配置描述符为: /* USB CDC deviceConfiguration Descriptor */ __ALIGN_BEGINuint8_t USBD_CDC_CfgHSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = { /*Configuration Descriptor*/ 0x09, /* bLength: Configuration Descriptor size */ USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returnedbytes */ 0x00, 0x01,// 0x02, /* bNumInterfaces: 2interface */ 0x01, /* bConfigurationValue: Configuration value */ 0x00, /* iConfiguration: Index of string descriptor describing theconfiguration */ 0xC0, /* bmAttributes: self powered */ 0x32, /* MaxPower 0 mA */ /*---------------------------------------------------------------------------*/ /*Interface Descriptor */ 0x09, /* bLength: Interface Descriptor size */ USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ /*Interface descriptor type */ 0x00, /* bInterfaceNumber: Number of Interface */ 0x00, /* bAlternateSetting: Alternate setting */ 0x02,//0x01, /* bNumEndpoints: One endpoints used */ 0xDC,//0x02, /* bInterfaceClass: Communication Interface Class */ 0xA0,//0x02, /* bInterfaceSubClass: Abstract Control Model */ 0xB0,//0x01, /* bInterfaceProtocol: Common AT commands */ 0x00, /* iInterface: */ // /*Header Functional Descriptor*/ // 0x05, /* bLength: Endpoint Descriptor size */ // 0x24, /* bDescriptorType: CS_INTERFACE */ // 0x00, /* bDescriptorSubtype: Header Func Desc */ // 0x10, /* bcdCDC: spec release number */ // 0x01, // // /*Call Management Functional Descriptor*/ // 0x05, /* bFunctionLength */ // 0x24, /* bDescriptorType: CS_INTERFACE */ // 0x01, /* bDescriptorSubtype: Call Management Func Desc */ // 0x00, /* bmCapabilities: D0+D1 */ // 0x01, /* bDataInterface: 1 */ // // /*ACM Functional Descriptor*/ // 0x04, /* bFunctionLength */ // 0x24, /* bDescriptorType: CS_INTERFACE */ // 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ // 0x02, /* bmCapabilities */ // // /*Union Functional Descriptor*/ // 0x05, /* bFunctionLength */ // 0x24, /* bDescriptorType: CS_INTERFACE */ // 0x06, /* bDescriptorSubtype: Union func desc */ // 0x00, /* bMasterInterface: Communication class interface */ // 0x01, /* bSlaveInterface0: Data Class Interface */ // // /*Endpoint 2 Descriptor*/ // 0x07, /* bLength: EndpointDescriptor size */ // USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ // CDC_CMD_EP, /* bEndpointAddress */ // 0x03, /* bmAttributes: Interrupt */ // LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ // HIBYTE(CDC_CMD_PACKET_SIZE), // 0x10, /* bInterval: */ /*---------------------------------------------------------------------------*/ // /*Data class interface descriptor*/ // 0x09, /* bLength: Endpoint Descriptor size */ // USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ // 0x01, /* bInterfaceNumber: Number of Interface */ // 0x00, /* bAlternateSetting: Alternate setting */ // 0x02, /* bNumEndpoints: Two endpoints used */ // 0x0A, /* bInterfaceClass: CDC */ // 0x00, /* bInterfaceSubClass: */ // 0x00, /* bInterfaceProtocol: */ // 0x00, /* iInterface: */ /*Endpoint OUT Descriptor*/ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ CDC_OUT_EP, /* bEndpointAddress */ 0x02, /* bmAttributes:Bulk */ LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), 0x00, /* bInterval:ignore for Bulk transfer */ /*Endpoint IN Descriptor*/ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ CDC_IN_EP, /* bEndpointAddress */ 0x02, /* bmAttributes:Bulk */ LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), 0x00 /* bInterval:ignore for Bulk transfer */ } ; 最好将下面的USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] 和uint8_t USBD_CDC_OtherSpeedCfgDesc[USB_CDC_CONFIG_DESC_SIZ] 也改了因为以备不时之需。 4. 修改发送函数 由于我们还是使用cdc的端点收发,所以不用重新初始化。我们只需要增加我们自己的bulk传输的收发函数就可以了 uint8_tBulkRxBuffer[512]; uint8_t USBD_BULK_ReceivePacket(USBD_HandleTypeDef*pdev) { USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)pdev->pClassData; /* Suspend or Resume USB Out process */ if(pdev->pClassData != NULL) { if(pdev->dev_speed == USBD_SPEED_HIGH ) { /* Prepare Out endpoint to receive nextpacket */ USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, BulkRxBuffer, 512); } else { /* Prepare Out endpoint to receive nextpacket */ USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, BulkRxBuffer, 512); } return USBD_OK; } else { return USBD_FAIL; } } uint8_tBulkTxBuffer[512]; uint8_t USBD_BULK_TransmitPacket(USBD_HandleTypeDef*pdev) { USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)pdev->pClassData; if(pdev->pClassData != NULL) { if(hcdc->TxState == 0) { /* Tx Transfer in progress */ hcdc->TxState = 1; /* Transmit next packet */ USBD_LL_Transmit(pdev, CDC_IN_EP, BulkTxBuffer, 512); return USBD_OK; } else { return USBD_BUSY; } } else { return USBD_FAIL; } } 已经就完成了自定义大数据传输的修改。 调用以上两个函数就可以完成和pc机的通信。 将我们的设备插到上位机上,使用libusb-win32 自动生成这个设备的驱动之后就能正常通信。 是不是很简单。。。
|
你好,usb自定义类设备,PC端驱动你如何安装的?我现在是黄色感叹号,libusb-win32操作写设备时,提示找不到这个usb设备