打印
[STM32F3]

基于STM32F1的USB转多路串口(USB-Multiple-CDC)

[复制链接]
5057|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
IversonCar|  楼主 | 2015-9-24 16:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
根据ST英文社区提供的资料,实现的USB转多路串口(USB-Multiple-CDC)例程,利用了STM32F103系列多端点的特性。而STM32F2/F4端点数量较少,不能实现USB-Multiple-CDC,但STM32F2/F4可以外加高速PHY芯片,实现USB2.0高速通讯。应该说F1和F2、F4使用场合不同,所以功能定位有所不同。


例程包下载地址:USB-Multiple-CDC  



注意事项:
1.工程包中含有驱动安装引导文件。
2.3CDC工程包,属于USB转多路串口(USB-Multiple-CDC),驱动的安装可参考“USB-Dual-CDC驱动安装说明书”。
3.采用带参数的宏实现3路串口的DMA发送,这个相对于ST官方的阻塞式发送,更具有实用性。


USB-Dual-CDC驱动安装说明书下载地址: USB-Dual-CDC驱动安装说明书
USB-Dual-CDC驱动安装说明书是之前USB-Dual-RS485产品的驱动安装说明书,可以参考这个安装步骤,3路的驱动,就是多安装1路而已。


三路串口的DMA发送代码部分预览如下:

/* 带参数的宏功能(预编译展开): USB的IN端点 发送数据到PC主机 */
#define EPx_IN_Callback(ENDPx, CDCx_Tx_State, VCPx_Rx_Buffer, VCPx_Rx_ptr_out, VCPx_Rx_length) {\
    uint16_t USB_Tx_ptr;\
    uint16_t USB_Tx_length;\
    if (CDCx_Tx_State == 1) {\
        USB_Tx_ptr = VCPx_Rx_ptr_out;\
        if (VCPx_Rx_length == 0) {\
            CDCx_Tx_State = 0;\
            SetEPTxCount(ENDPx,0);\
            SetEPTxValid(ENDPx);\
        } else {\
            if (VCPx_Rx_length > VIRTUAL_COM_PORT_DATA_SIZE) {\
                USB_Tx_length = VIRTUAL_COM_PORT_DATA_SIZE;\
                VCPx_Rx_ptr_out += VIRTUAL_COM_PORT_DATA_SIZE;\
                VCPx_Rx_length -= VIRTUAL_COM_PORT_DATA_SIZE;\
            } else {\
                USB_Tx_length = VCPx_Rx_length;\
                VCPx_Rx_ptr_out += VCPx_Rx_length;\
                VCPx_Rx_length = 0;\
            }\
            USB_SIL_Write(ENDPx, &VCPx_Rx_Buffer[USB_Tx_ptr], USB_Tx_length);\
            SetEPTxValid(ENDPx);\
        }\
    }\
}


/* 带参数的宏功能(预编译展开): USB的OUT端点 通过物理串口向外发送数据(阻塞方式) */
#define EPx_OUT_Callback(ENDPx, USARTx, GPIOx, GPIO_Pin_x) {\
    uint32_t i;\
    uint16_t USB_Rx_Cnt;\
    USB_Rx_Cnt = USB_SIL_Read(ENDPx | 0x00, USB_Rx_Buffer); \
    GPIOx->BSRR = GPIO_Pin_x;\
    for (i = 0; i < USB_Rx_Cnt; i++) {\
        USARTx->DR = *(USB_Rx_Buffer + i);\
        while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);\
    }\
    SetEPRxValid(ENDPx);\
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);\
    USART_ClearFlag(USARTx, USART_FLAG_TC);\
    GPIOx->BRR = GPIO_Pin_x;\
}

/* 带参数的宏功能(预编译展开): USB的OUT端点 通过物理串口向外发送数据(DMA方式) */
#define EPx_OUT_Callback_DMA(Flag_VCPx_Tx_Buf_Use, ENDPx, VCPx_Tx_Buffer1,VCPx_Tx_Buffer2,\
    GPIOx, GPIO_Pin_x, DMA1_Channelx, VCPx_Tx_Buffer_Cnt, Flag_VCPx_Tx_Buf_Full) {\
    uint16_t USB_Rx_Cnt;\
    if(Flag_VCPx_Tx_Buf_Use == 0){\
        USB_Rx_Cnt = GetEPRxCount(ENDPx & 0x7F);\
        PMAToUserBufferCopy(&VCPx_Tx_Buffer1[0], GetEPRxAddr(ENDPx & 0x7F), USB_Rx_Cnt);\
        SetEPRxValid(ENDPx);\
        GPIOx->BSRR = GPIO_Pin_x;\
        DMA1_Channelx->CNDTR = USB_Rx_Cnt;\
        DMA_Cmd(DMA1_Channelx, ENABLE);\
        Flag_VCPx_Tx_Buf_Use = 1;\
        VCPx_Tx_Buffer_Cnt = 0;\
    } else {\
        USB_Rx_Cnt = GetEPRxCount(ENDPx & 0x7F);\
        if(VCPx_Tx_Buffer_Cnt < (1024-128)){\
          PMAToUserBufferCopy(&VCPx_Tx_Buffer2[VCPx_Tx_Buffer_Cnt], GetEPRxAddr(ENDPx & 0x7F), USB_Rx_Cnt);\
          VCPx_Tx_Buffer_Cnt += USB_Rx_Cnt;\
          SetEPRxValid(ENDPx);\
        } else {\
          PMAToUserBufferCopy(&VCPx_Tx_Buffer2[VCPx_Tx_Buffer_Cnt], GetEPRxAddr(ENDPx & 0x7F), USB_Rx_Cnt);\
          VCPx_Tx_Buffer_Cnt += USB_Rx_Cnt;\
          Flag_VCPx_Tx_Buf_Full = 1;\
        }\
    }\
}



沙发
mmuuss586| | 2015-9-24 17:52 | 只看该作者

不错,谢谢分享;

使用特权

评论回复
板凳
yklstudent| | 2015-9-24 21:19 | 只看该作者
马人口,xiexie楼主的资料

使用特权

评论回复
地板
gejigeji521| | 2015-9-24 22:18 | 只看该作者
根据ST英文社区提供的资料,实现的USB转多路串口(USB-Multiple-CDC)例程,利用了STM32F103系列多端点的特性。
竟然可以这样,需要什么转接器吗

使用特权

评论回复
5
0406445| | 2015-10-4 00:39 | 只看该作者
大神,连接挂了,可以直接给我吗,我的邮箱:564386237@qq.com

使用特权

评论回复
6
ticomi| | 2015-10-4 08:37 | 只看该作者
理解了USB的端点功能后,很容易实现这样的功能,不建议直接要代码。如果不明白USB的底层问题,即便是实现了功能,也很难修改为自己需要的功能,所以最好还是理解USB后再看代码会很好。

使用特权

评论回复
7
0406445| | 2015-10-4 17:18 | 只看该作者
ticomi 发表于 2015-10-4 08:37
理解了USB的端点功能后,很容易实现这样的功能,不建议直接要代码。如果不明白USB的底层问题,即便是实现了 ...

我的是F302的,想实现usb虚拟多串口,多添加了接口部分,但是每次都是蓝屏,在想是不是电脑驱动问题,用IAD的话,不知道linux支不支持,请问有什么好的方法介绍下
我配置好接口描述符部分后,比如是双串口,那是不是还要初始化端点的部分才可以枚举?

使用特权

评论回复
8
ticomi| | 2015-10-7 09:16 | 只看该作者
0406445 发表于 2015-10-4 17:18
我的是F302的,想实现usb虚拟多串口,多添加了接口部分,但是每次都是蓝屏,在想是不是电脑驱动问题,用I ...

具体实现不是一句话可以说的清楚的,我在使用多端点时也是多次试验才最终成功的。这个还是要看下USB的协议内容后参照协议去实现了。

使用特权

评论回复
9
0406445| | 2015-10-7 20:31 | 只看该作者
ticomi 发表于 2015-10-7 09:16
具体实现不是一句话可以说的清楚的,我在使用多端点时也是多次试验才最终成功的。这个还是要看下USB的协 ...

多谢回复,能给个思路吗,就描述符上的就好

使用特权

评论回复
10
ticomi| | 2015-10-8 08:16 | 只看该作者
0406445 发表于 2015-10-7 20:31
多谢回复,能给个思路吗,就描述符上的就好
/* USB HID&MSC device Configuration Descriptor */
static uint8 USBD_CfgDesc[USB_HIDMSC_CONFIG_DESC_SIZ] =
{
  0x09,     //bLength: Configuration Descriptor size
  USB_CONFIGURATION_DESCRIPTOR_TYPE,    //bDescriptorType: Configuration
  USB_HIDMSC_CONFIG_DESC_SIZ,           //wTotalLength: Bytes returned
  0x00,
  0x02,         //bNumInterfaces: 1 interface
  0x01,         //bConfigurationValue: Configuration value
  0x00,         //iConfiguration: Index of string descriptor describing the configuration
  0xC0,         //bmAttributes: bus powered and NOT Support Remote Wake-up
  0x00,         //MaxPower 0 mA: this current is used for detecting Vbus
  
  
  /** Mass Storage interface (09)**/
  0x09,         //bLength: Interface Descriptor size
  0x04,         //bDescriptorType:
  0x00,         //bInterfaceNumber: Number of Interface
  0x00,         //bAlternateSetting: Alternate setting
  0x02,         //bNumEndpoints*/
  0x08,         //bInterfaceClass: MSC Class
  0x06,         //bInterfaceSubClass : SCSI transparent
  0x50,         //nInterfaceProtocol
  0x05,         //iInterface:
  /** Mass Storage IN Endpoints (18) **/
  0x07,         //Endpoint descriptor length = 7
  0x05,         //Endpoint descriptor type
  MSC_IN_EP,    //Endpoint address (IN, address 1)
  0x02,         //Bulk endpoint type
  LOBYTE(MSC_MAX_PACKET),
  HIBYTE(MSC_MAX_PACKET),
  0x00,         //Polling interval in milliseconds
  /** Mass Storage OUT Endpoints (25) **/
  0x07,         //Endpoint descriptor length = 7
  0x05,         //Endpoint descriptor type
  MSC_OUT_EP,   //Endpoint address (OUT, address 1)
  0x02,         //Bulk endpoint type
  LOBYTE(MSC_MAX_PACKET),
  HIBYTE(MSC_MAX_PACKET),
  0x00,         //Polling interval in milliseconds
  
  
  /* Descriptor of Custom HID interface (32)*/
  0x09,         //bLength: Interface Descriptor size
  0x04,         //bDescriptorType: Interface descriptor type
  0x01,         //bInterfaceNumber: Number of Interface
  0x00,         //bAlternateSetting: Alternate setting
  0x02,         //bNumEndpoints
  0x03,         //bInterfaceClass: HID
  0x00,         //bInterfaceSubClass : 1=BOOT, 0=no boot
  0x00,         //nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse
  0,            //iInterface: Index of string descriptor
  /** Descriptor of Custom HID (41) **/
  0x09,         //bLength: HID Descriptor size
  HID_DESCRIPTOR_TYPE, //bDescriptorType: HID
  0x10,         //bcdHID: HID Class Spec release number
  0x01,
  0x00,         //bCountryCode: Hardware target country
  0x01,         //bNumDescriptors: Number of HID class descriptors to follow
  0x22,         //bDescriptorType
  HID_REPORT_DESC_SIZE,//wItemLength: Total length of Report descriptor
  0x00,
  /** Descriptor of IN endpoint(50) **/
  0x07,         //bLength: Endpoint Descriptor size
  0x05,         //bDescriptorType:  
  HID_IN_EP,    //bEndpointAddress: Endpoint Address (IN)
  0x03,         //bmAttributes: Interrupt endpoint
  HID_IN_PACKET,//wMaxPacketSize: 64 Byte max
  0x00,
  0x01,         //bInterval: Polling Interval (1 ms)
  /** Descriptor of OUT endpoint (57) **/
  0x07,             //bLength: Endpoint Descriptor size
  0x05,             //bDescriptorType:
  HID_OUT_EP,       //bEndpointAddress: Endpoint Address (IN)
  0x03,             //bmAttributes: Interrupt endpoint
  HID_OUT_PACKET,   //wMaxPacketSize: 64 Byte max
  0x00,
  0x01,             //bInterval: Polling Interval (1 ms)
};

使用特权

评论回复
11
android2| | 2015-10-8 11:05 | 只看该作者
USB-Multiple-CDC  ,USB-Dual-CDC驱动安装说明书,这两个链接好像失效了啊

使用特权

评论回复
12
huangqi412| | 2015-10-8 12:20 | 只看该作者
0406445 发表于 2015-10-4 17:18
我的是F302的,想实现usb虚拟多串口,多添加了接口部分,但是每次都是蓝屏,在想是不是电脑驱动问题,用I ...

单片机USB转多串口,似乎都是用IAD描述符。网上好多现成F103代码

使用特权

评论回复
13
0406445| | 2015-10-8 14:05 | 只看该作者

大神,有cdc类的吗,

使用特权

评论回复
14
ticomi| | 2015-10-8 14:14 | 只看该作者
0406445 发表于 2015-10-8 14:05
大神,有cdc类的吗,

没有,起始可以参考这个写个出来的,我现在也不使用这个了,而是采用新的复合设备方式,一样的思路!

使用特权

评论回复
15
0406445| | 2015-10-8 15:08 | 只看该作者
huangqi412 发表于 2015-10-8 12:20
单片机USB转多串口,似乎都是用IAD描述符。网上好多现成F103代码

对啊,都是IAD的,我想linux应该是不支持IAD的

使用特权

评论回复
16
lxs_14| | 2019-11-11 22:29 | 只看该作者
楼主,连接挂了,可以直接给我吗,我的邮箱:103819240@qq.com ,谢谢

使用特权

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

本版积分规则

50

主题

344

帖子

0

粉丝