请选择 进入手机版 | 继续访问电脑版

你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【F769IDISCOVERY评测】高速USB VCP和全速USB VCP 速度对比  

[复制链接]
creep 提问时间:2016-12-3 18:36 /
本帖最后由 creep 于 2017-10-17 14:31 编辑

              STM32F769 Discovery STM32官网板载有一个  USB OTG HS 接口和一个USB 高速PHY USB3320C-EZK,二者配合可以实现高速的虚拟串口和PC或者其他设备进行通信,下面我们就简单的看下高速的VCP的移植和通信速度,并和其他的板子上的全速VCP进行对比。

2016-12-03_172548.png



1、硬件
   USB OTG HS 的外部PHY为USB3320C,和stm32769硬件接口如下,

2016-12-03_173551.png

USB3320C的时钟使用板载的24M晶振,并输出60MHZ的时钟给USB 高速模块,这个全速USB设备的48MHZ时钟有些区别。

2016-12-03_173350.png

移植的时候需要根据STM32F769 Discovery 的原理图确认具体是哪些引脚和USB3320C进行通信。

2、软件移植

    ST官方提供了完善的USB库,移植非常简单,只需要根据具体的硬件设置要初始化的引脚即可,此处一定要注意必须根据原理图连接进行初始化化,不同的ST开发板的接法可能不同:
  1. /* Configure USB HS GPIOs */
  2.     __HAL_RCC_GPIOA_CLK_ENABLE();
  3.     __HAL_RCC_GPIOB_CLK_ENABLE();
  4.     __HAL_RCC_GPIOC_CLK_ENABLE();
  5.     __HAL_RCC_GPIOH_CLK_ENABLE();
  6.                 __HAL_RCC_GPIOI_CLK_ENABLE();

  7.    
  8.     /* CLK */
  9.     GPIO_InitStruct.Pin = GPIO_PIN_5;
  10.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  11.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  12.     GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  13.     GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
  14.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  15.    
  16.     /* D0 */
  17.     GPIO_InitStruct.Pin = GPIO_PIN_3;
  18.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  19.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  20.     GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  21.     GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
  22.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  23.    
  24.     /* D1 D2 D3 D4 D5 D6 D7 */
  25.     GPIO_InitStruct.Pin = GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_5 |\
  26.       GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
  27.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  28.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  29.     GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
  30.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  31.    
  32.     /* STP */
  33.     GPIO_InitStruct.Pin = GPIO_PIN_0;
  34.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  35.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  36.     GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
  37.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  38.    
  39.     /* NXT */
  40.     GPIO_InitStruct.Pin = GPIO_PIN_4;
  41.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  42.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  43.     GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
  44.     HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
  45.    
  46.     /* DIR */
  47.     GPIO_InitStruct.Pin = GPIO_PIN_11;
  48.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  49.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  50.     GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
  51.     HAL_GPIO_Init(GPIOI, &GPIO_InitStruct)
复制代码
然后在编译器的预处理定义中选择高速外设:

2016-12-03_174440.png

最后在main函数中初始化USB即可:
  1. int main(void)
  2. {
  3.                 uint8_t TestBuff[512];
  4.                 uint16_t t;
  5.                 /* Enable the CPU Cache */
  6.                 CPU_CACHE_Enable();
  7.                 HAL_Init();
  8.                 /* Configure the system clock to 216 MHz */
  9.                 SystemClock_Config();

  10.                 USART1_Init();
  11.                 for(t = 0;t < 512;t++)TestBuff[t] = t;        
  12.                 /* Init Device Library */
  13.                 USBD_Init(&USBD_Device, &VCP_Desc, 0);

  14.                 /* Add Supported Class */
  15.                 USBD_RegisterClass(&USBD_Device, USBD_CDC_CLASS);

  16.                 /* Add CDC Interface Class */
  17.                 USBD_CDC_RegisterInterface(&USBD_Device, &USBD_CDC_fops);

  18.                 /* Start Device Process */
  19.                 USBD_Start(&USBD_Device);
  20.   /* Infinite loop */
  21.                 while (1)
  22.                 {
  23.                         USB2PC(TestBuff,512);
  24.                 }
  25. }
复制代码
下载程序到板子后应该就可以在电脑设备管理器看到虚拟串口

2016-12-03_174828.png

如果是第一次使用VCP就要安装官方的驱动,有的电脑可能不是正版系统会导致安装驱动失败,解决办法可以参考这个帖子:
虚拟串口驱动安装失败的解决方法

基本上常见的串口驱动问题都可以解决,如果驱动安装成功后还提示设备有问题,可以尝试将代码的堆栈修改大一些试下。


  3、数据传输

    全速的USB VCP一次最多可以发送64个字节,高速的USB VCP 一次可以最多发送512个字节,如果一次发送整个数据包的数据,需要再发送一个数据个数为0的数据包,否则上位机可能没法接收数据。   USB发送数据主要是调用下面的函数:
  1. //发送数据PC
  2. uint8_t UsbSendData(uint8_t *pbuff,uint16_t buffsize)
  3. {
  4.         uint16_t retry = 0;
  5.         USBD_HandleTypeDef   *pdev = &USBD_Device;
  6.         USBD_CDC_HandleTypeDef   *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData;
  7.   
  8.   hcdc->TxBuffer = pbuff;
  9.   hcdc->TxLength = buffsize;  
  10.         
  11.   if(pdev->pClassData != NULL)
  12.   {
  13.     if(hcdc->TxState == 0)
  14.     {
  15.       /* Tx Transfer in progress */
  16.       hcdc->TxState = 1;
  17.       
  18.       /* Transmit next packet */
  19.       USBD_LL_Transmit(pdev,
  20.                        CDC_IN_EP,
  21.                        hcdc->TxBuffer,
  22.                        hcdc->TxLength);               
  23.       
  24.     }
  25.     else
  26.     {
  27.       return USBD_BUSY;
  28.     }
  29.   }
  30.         //等待发送结束        
  31.         while(hcdc->TxState == 1)
  32.         {
  33.                 retry++;
  34.                 if(retry == 0xfff0)
  35.                 {
  36.                         return USBD_FAIL;
  37.                 }               
  38.         }
  39.         return USBD_OK;
  40. }
复制代码
根据上面USB发送数据包的要求,我们使用下面的函数来调用上面的函数来发送任意大小的数据,这个函数会自动在发送最大数据包后再发送一个空的数据包。USB_PACK_SIZE根据USB模式可能为64或者512
  1. //可发送任意字节的数据到PC端
  2. void USB2PC(uint8_t *str,uint16_t len)
  3. {
  4.         uint16_t j = 0;
  5.         if(len < USB_PACK_SIZE)
  6.         {
  7.                 UsbSendData(str,len);
  8.         }
  9.         else
  10.         {
  11.                 for (j = 0;j < len/USB_PACK_SIZE;j++)
  12.                 {
  13.                         UsbSendData((str+USB_PACK_SIZE*j),USB_PACK_SIZE);
  14.                 }
  15.                 UsbSendData((str+USB_PACK_SIZE*j),len%USB_PACK_SIZE);
  16.         }        
  17. }
复制代码
为了测试发送的最大速度,我在main函数中循环调用发送函数一次发送512字节,发送内容为0X00-0XFF.
因为发送数据量比较大,有些串口助手可能会卡死,我使用SecureCRT 进行接收.接收数据如下,因为SecureCRT显示的ASCII,所以有些显示是乱码,但是数据是对的,
11.png

使用监控软件看到发送数据如下,可以每个数据包为512字节,每次发送的内容为0x00-0xFF.数据没有出错。

2016-12-03_121047.png

具体的发送速度如下,多次测试可以看到软件计算的结果有些不同

123.png

456.png

779.png

为了对比我们测试下STM32F746 Discovery上全速的USB发送速度,
  1. int main(void)
  2. {
  3.                 uint8_t TestBuff[64];
  4.                 uint16_t t;
  5.     CPU_CACHE_Enable();
  6.     HAL_Init();
  7.                 SystemClock_Config();
  8.     LED_Init();
  9.           /* Init Device Library */
  10.                 USBD_Init(&USBD_Device, &VCP_Desc, 0);
  11.                
  12.                 /* Add Supported Class */
  13.                 USBD_RegisterClass(&USBD_Device, USBD_CDC_CLASS);
  14.                
  15.                 /* Add CDC Interface Class */
  16.                 USBD_CDC_RegisterInterface(&USBD_Device, &USBD_CDC_fops);
  17.                
  18.                 /* Start Device Process */
  19.                 USBD_Start(&USBD_Device);
  20.                 for(t = 0;t < 64;t++)TestBuff[t] = t;
  21.     while(1)
  22.     {
  23.                         USB2PC(TestBuff,64);
  24.                 }
  25. }
复制代码


SecureCRT看到的数据

FS-VCP.png

监控软件检测到的数据,数据包大小为64字节

FS-VCP0.png

检测到发送速度

FS-VCP1.png

       全速USB的理论最大速度为12Mbps,高速USB的为480Mpbs,明显上面测的数据和理论的最大数度有些差距。不同的检测软件可能测试得到的数据不同,通过对比可以看到高速USB VCP和全速USB VCP还是有些速度提升的。测试代码使用keil5.20编译,代码没有进行任何优化。USB库是2016的比较新的版本。感兴趣的同学可以使用优化代码或者其他编译器编译代码试下是不是速度有所提升。

    我在测试高速USB VCP的时候因为发送数据量较大,在我电脑上win10安装之后的首次蓝屏,赶紧拍照留念,微软迟早药丸。

76B236E9BF8A73E26DC747D142776ACE.png

测试代码;
STM32F746 Discovery VCP-FS.rar (951.89 KB, 下载次数: 271)

评分

参与人数 5 ST金币 +47 收起 理由
liuzhijun + 1
kylongmu + 20 很给力!
xmshao + 5 赞一个!
zero99 + 20
wofei1314 + 1 赞一个!

查看全部评分

2 收藏 13 评论60 发布时间:2016-12-3 18:36

举报

60个回答
daddyk 回答时间:2017-1-17 11:18:26
楼主你好,我用STM32F7 +CY7C68003(USB PHY)来实现高速usb通信,发现枚举不到usb设备。
我是根据你“ STM32F769 Discovery VCP-HS.rar ’’的例子改的不知道为什么。
STM32用26M晶振时钟配置如下:
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
  HAL_StatusTypeDef  ret = HAL_OK;
  
  /* Enable Power Control clock */
  __HAL_RCC_PWR_CLK_ENABLE();
  
  /* The voltage scaling allows optimizing the power consumption when the device is
     clocked below the maximum system frequency, to update the voltage scaling value
     regarding system frequency refer to product datasheet.  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /* Enable HSE Oscillator and activate PLL with HSE as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 26;
  RCC_OscInitStruct.PLL.PLLN = 432;  
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 9;
  RCC_OscInitStruct.PLL.PLLR = 7;
  
  ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
  if(ret != HAL_OK)
  {
    while(1) { ; }
  }
  
  /* Activate the OverDrive to reach the 216 MHz Frequency */  
  ret = HAL_PWREx_EnableOverDrive();
  if(ret != HAL_OK)
  {
    while(1) { ; }
  }
  /* Select PLLSAI output as USB clock source */
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_CLK48;
  PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48SOURCE_PLLSAIP;
  PeriphClkInitStruct.PLLSAI.PLLSAIN = 432;
  PeriphClkInitStruct.PLLSAI.PLLSAIQ = 9;
  PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV2;
  if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct)  != HAL_OK)
  {
    while(1) { ; }
  }
  
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  
  ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);
  if(ret != HAL_OK)
  {
    while(1) { ; }
  }  

usb硬件初始化如下:
   /* Configure USB HS GPIOs */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
   // __HAL_RCC_GPIOH_CLK_ENABLE();
         //        __HAL_RCC_GPIOI_CLK_ENABLE();

   
    /* CLK */
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
   
    /* D0 */
    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
   
    /* D1 D2 D3 D4 D5 D6 D7 */
    GPIO_InitStruct.Pin = GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_5 |\
      GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
   
    /* STP */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
   
    /* NXT */
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
   
    /* DIR */
    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE();
seawwh 回答时间:2017-1-12 15:40:49
关于STM32 VCP FULL SPEED 最高上传速率

我的测试环境 F205,120M运行, Host: XP, AMD 2GHz

我测试的结果,在Host不很繁忙的情况下,F205发往Host的速率可达670K字节以上。
测试的方法是:

  循环下列动作:
  Host 发送一个传输命令,F205立即发送8K字节的数据到Host.
  Host 接收到数据后效验。
  10000次循环之后累计数据流量。
  其中Host 等待和发送命令有一些开销。每次传输的数据块愈长,这些开销占比例愈小。

  那么,在Full speed 下USB Bulk 传输的最大速度是多少呢?
  这取决于Host 发出 In 令牌的速率,据我测试 In 令牌大约是15-16个/ms
核算出速率约为 1M Byte/s; 这应该是极限速率。
liuzhijun 回答时间:2019-9-12 10:23:11
请教个问题  我用了你这个代码  STM32F767 +USB3300 做了个高速 的USB CDC 类的设备 ,从芯片 上传数据到PC 能达到 32MB 字节/秒  而从PC下发数据到芯片才 8.5MB 字节/秒  搞不懂是什么问题,而使用STM32F407 上行,下行分别能达到  32MB 字节/秒  和 19MB 字节/秒
霹雳之火 回答时间:2016-12-3 19:31:39
好贴必须顶起 win10被你弄死机了
风子 回答时间:2016-12-3 20:09:11
跟着大神学USB
Stm32McuLover 回答时间:2016-12-3 20:34:06
厉害
Paderboy 回答时间:2016-12-3 20:49:06
顶起,学习了。。。
moyanming2013 回答时间:2016-12-3 20:57:13
你拿USB VCP虚拟串口的速度和全速/高速USB的速度对比,这。。。
creep 回答时间:2016-12-3 22:02:21
moyanming2013 发表于 2016-12-3 20:57
你拿USB VCP虚拟串口的速度和全速/高速USB的速度对比,这。。。

大神,让您见笑了。
我就是顺便对比下。。。
给有需要的人或者想知道差别的同学一个基本的参考。
creep 回答时间:2016-12-3 22:03:43
霹雳之火 发表于 2016-12-3 19:31
好贴必须顶起 win10被你弄死机了

微软大法好,升级了win10后,好多年的旧笔记本又满血复活了。
abswzp 回答时间:2016-12-4 09:06:57
vcp速度上不去是因为你的usb没有做双缓冲,做一下就好了。不过开启stm32 IN端点的双缓冲时序还是蛮复杂的,并且官方没有任何参考历程
斜阳 回答时间:2016-12-4 09:37:58
没有蓝屏不微软
creep 回答时间:2016-12-4 10:08:54
abswzp 发表于 2016-12-4 09:06
vcp速度上不去是因为你的usb没有做双缓冲,做一下就好了。不过开启stm32 IN端点的双缓冲时序还是蛮复杂的, ...

老早之前弄过双缓冲没有搞好,现在的速度用在产品上已经够用了所以就没有折腾,如果您有双缓冲参考代码的话可以分享下。
wofei1314 回答时间:2016-12-4 15:36:51
好资料,收藏~
5265325 回答时间:2016-12-4 16:32:17
wolfgang 回答时间:2016-12-4 17:11:19
好贴必须顶起 win10被你弄死机了
creep 回答时间:2016-12-4 17:16:49

感谢打赏
1234下一页
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版