打印
[STM32F4]

授人以渔 第五节:基于stm32f4实现usb自定义大数据传输

[复制链接]
6555|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
z755924843|  楼主 | 2017-3-17 10:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这一节,准备基于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 DescriptorCall ManagementFunctional DescriptorACM Functional DescriptorUnion 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 自动生成这个设备的驱动之后就能正常通信。
是不是很简单。。。

评论
qinchxiong 2019-7-31 15:28 回复TA
你好,usb自定义类设备,PC端驱动你如何安装的?我现在是黄色感叹号,libusb-win32操作写设备时,提示找不到这个usb设备 
沙发
mmuuss586| | 2017-3-17 12:38 | 只看该作者
谢谢分享;

使用特权

评论回复
板凳
njchenmin| | 2017-6-11 21:42 | 只看该作者
不错,USB实在太复杂,只能用到哪儿看到哪儿。

使用特权

评论回复
地板
lzbf| | 2017-6-11 22:44 | 只看该作者
USB开发还不是很懂。

使用特权

评论回复
5
lzbf| | 2017-6-11 22:46 | 只看该作者
这个上位机开发是固定的模式吗?

使用特权

评论回复
6
z755924843|  楼主 | 2017-6-13 08:33 | 只看该作者
lzbf 发表于 2017-6-11 22:46
这个上位机开发是固定的模式吗?

对,导入libusb,调用函数就行了。

使用特权

评论回复
7
z755924843|  楼主 | 2017-6-13 08:34 | 只看该作者
lzbf 发表于 2017-6-11 22:46
这个上位机开发是固定的模式吗?

对,导入libusb,调用函数就行了。

使用特权

评论回复
8
likeymh| | 2017-8-2 09:48 | 只看该作者
按照你接受介绍的方法  对usb描述符进行配置    :  PC机驱动可以正常安装。                 但是下位机 每次只能发一次数据  串口usb标志位显示一直busy ,关于收发函数这一块好像存在问题,怎么解决呢?lz给点意见  

使用特权

评论回复
9
qinchxiong| | 2019-7-31 15:16 | 只看该作者
本帖最后由 qinchxiong 于 2019-7-31 17:10 编辑
likeymh 发表于 2017-8-2 09:48
按照你接受介绍的方法  对usb描述符进行配置    :  PC机驱动可以正常安装。                 但是下位机  ...


使用特权

评论回复
10
xiloujushi| | 2020-9-24 18:48 | 只看该作者
您好!我参考你在论坛里的贴子《授人以渔 第五节:基于stm32f4实现usb自定义大数据传输》改造的一个工程,能接收数据,却不能发送数据。不知是为什么?请问您能否把源码给我一份,我的邮箱:xilou@126.com,谢谢!

使用特权

评论回复
11
xiloujushi| | 2020-9-24 18:49 | 只看该作者
关键的是下面:

使用特权

评论回复
12
xiloujushi| | 2020-9-24 18:55 | 只看该作者

/*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, /* bInterfaceClass: Diagnostic Device */
  0xA0,  /* bInterfaceSubClass: Abstract Control Model */
  0xB0,  /* bInterfaceProtocol: Common AT commands */
  0x00,  /* iInterface: */

我需要的类型是0xDC 的。

使用特权

评论回复
13
xiloujushi| | 2020-9-24 19:01 | 只看该作者
我试过调用USB_LLTransmit函数发送数据,但是USB Hound监视不到,不知什么原因。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:嵌入式相关网站喜欢的朋友了解一下http://www.micropython.group

31

主题

260

帖子

39

粉丝