基于STM32F103xx的USB转多路串口(USB-Multiple-CDC)测试已完成,全部开启DMA自动发送功能。简要说明如下:
1. 支持通过DMA方式连续发送超过64字节大小的数据包。而且在DMA发送的同时,继续接收来自PC主机的数据。发完64字节后,RS485不换向,可以立即发送剩余的数据。
2. USB转多路串口(USB-Multiple-CDC)支持在大虾103核心板,USB-Dual-RS485板上运行,代码无需修改。在其它板子上运行,需要修改USB控制脚和RS485控制脚。
3. 三路CDC串口,均支持DMA发送功能,接收仍为中断方式。TLL通信使用时,波特率不要超过921600bps。RS232/RS485通信时,硬件限制一般不能超过250000/500000bps。
STM32_USB-FS-Device_Lib_V7.0.0.2014.12.20_3CDC_for_DX103.zip 可不用修改直接运行在大虾103核心板上。其它STM32F103xx板子需要修改。
备注: USB-Dual-RS485板的通信部分为专用磁耦隔离的RS485芯片,只需要一个USB端口,就能同时连接两台PLC
刷新程序。目前USB-Dual-RS485板处于缺货状态,但有大虾103核心板大量供应。
附录:“USB复合设备”和“USB组合设备”的区别
关键字
Communication Device Class,简称CDC
USB Compound Device,USB复合设备
USB Composite Device,USB组合设备
摘要
Compound Device内嵌Hub和多个Function,每个Function都相当于一个独立的USB外设,有自己的PID/VID/DID。
Composite Device内只有一个Function,只有一套PID/VID/DID,通过将不同的interface定义为不同的类来实现
多个功能的组合。
正文
Compound Device内嵌Hub和多个Function,每个Function都相当于一个独立的USB外设,有自己的PID/VID/DID。
Composite Device内只有一个Function,只有一套PID/VID/DID,通过将不同的interface定义为不同的类来实现多个功能的组
合。很多人认为一个USB接口上实现多个设备,就是指复合设备,其实,这是不确切的,虽然USB Compound Device和USB Composite Device 都会被百度翻译为USB复合设备。
在一个USB接口上实现多个设备有2中方法,一种是Compound Device,就是复合设备;另一种是Composite Device,就是组合设备。
在USB2.0的标准协议中,定义如下:
When multiple functions are combined with a hub in a single package, they are referred to as a compound device.
A device that has multiple interfaces controlled independently of each other is referred to as a
composite device.
所以,复合设备其实就是几个设备通过一个USB Hub形成的单一设备;组合设备也就是具有多个接口的设备,每个接口代表一个独立的设备。显然,如果是想同样的功能的话,组合设备的方法要简单很多(可以去看一下USB2.0协议中,USB2.0 Hub的复杂度)。
附录:USB Serial Tools工具软件的特殊功能介绍
一般的串口调试工具,不会针对USB插拔做专门的检测和处理,比较容易崩溃,例如微软收购的超级终端等。
USB Serial Tools 是本人自2009-2012年,个人业余时间开发的一个带有USB插拔检测的串口调试软件。
和其它串口调试工具相比,是专用软件,值得一提的功能如下:
1 支持高波特率。(支持该功能的串口调试工具屈指可数,大部分串口调试工具仅支持到115200)
2 支持USB插拔检测。(支持该功能的串口调试工具屈指可数,大部分串口调试工具都会因此崩溃)
3 支持STM32虚拟串口的USB端点号显示(该工具特有的支持,和嵌入式及PC的底层驱动相关)。
1. USB数据接收及阻塞式串口发送,部分源代码浏览如下:
/* 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;
}
2. USB数据接收及DMA式串口发送,部分源代码浏览如下
/* 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;
}
}
}
以上两段代码是带参数的宏,由于是多个USB端点和串口之间的通信数据转发,思路是一样的,但写代码的时候,
就非常容易写错,因此用带参数的宏代替。每个虚拟串口通信函数内,都插入这些带参数的宏,编译器在编译预
处理时,会将这些宏展开, 然后再进行编译。只要调好了一个虚拟串口,另外两个就调好了,非常方便。编译器
是不会出现书写错误的。
One CDC function requires 2 IN / 1 OUT endpoints (interrupt IN/ bulk IN/ bulk OUT), other than the default EP.
Available endpoints of each STM32F family are,
STM32F102/103
- FS Device core: 7 IN / 7 OUT
STM32F105/107
- OTG_FS: 3 IN / 3 OUT
STM32F2xx/4xx
- OTG_FS: 3 IN / 3 OUT
- OTG_HS: 5 IN / 5 OUT
STM32F102/103 - 3x CDC composite
STM32F105/107 - just one CDC
STM32F2xx/4xx - 2x CDC composite on OTG_HS
|
0
|
|
|
|