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

【经验分享】使用 STM32CubeMX 实现 USB 虚拟串口的环回测试功能

[复制链接]
STMCU小助手 发布时间:2022-3-2 22:17
前言
客户在 STM32F401RET6 中使用到了 USB 的虚拟串口功能。要求提供一个在 STM32Cube 中实现虚拟串口进行数据环回测试功能的范例程序。因为在我们目前所提供范例程序中,并没有适合客户需求的范例,所以我们在 STM32CubeMX 中创建一个范例程序给客户进行参考。
环境需求如下:
硬件环境:STM32F401C-Dicovery
电脑操作系统:window 7.x
集成开发环境:MDK、IAR
驱动:ST VCP Driver
STM32CubeMX:4.12.0
STM32CubeF4:1.10.0

STM32CubeMX 中配置流程
实现步骤如下:
首先,打开 STM32CubeMX 软件,选择 STM32F401C-Discovery 板子。

LLE1CBOM1NGI_MAPLHO(]SU.png

在 PinOut 列中选择 USB OTG FS 的 Device Only 选项

6{FI94UXSRQJN_U)79{V7.png

使能 USB 中间件的虚拟串口功能

@S7J8]2CR{N$(A81CD{U7XC.png

直接生成代码,这里我们选择 MDK 的 IDE,工程名字叫 VCP_Test

FL%Q6[]QXH[VX{_LNUJ9DQC.png

在生成的工程代码中的 usbd_cdc_if.c 文件中添加如下几行代码:
  1. #define APP_RX_DATA_SIZE 1024
  2. #define APP_TX_DATA_SIZE 1024
复制代码

这个定义本来就有的,只是建议将定义的值修改为 1024,这样效果更好。这个值的默认值是 4,但是在实际的操作中发现,如果你上位机传输的数据大于 4,且并不是 4 的整数倍的时候,会出现丢数据或者数据不返回的问题。其根本原因是因为虚拟串口的数据是以数据流的方式发送出来的,接收数据不知道每次接收到的数据大小是多少,所以使用了循环队列,但是一旦你的循环队列很小,很容易出现溢出的问题。比如你设置这个值为 5,你发一个 123456 的数据给 MCU,那么 MCU 就会返回 123451这六个数据。最后的一个数据就是溢出了,所以只能被第一个数据所代替。
  1. /* USER CODE BEGIN PRIVATE_MACRO */
  2. USBD_CDC_LineCodingTypeDef LineCoding = {
  3. 115200, /* baud rate */
  4. 0x00, /* stop bits-1 */
  5. 0x00, /* parity - none */
  6. 0x08 /* nb. of bits 8 */
  7. };
  8. uint32_t UserTxBufPtrIn = 0;
  9. uint32_t UserTxBufPtrOut = 0;
  10. /* USER CODE END PRIVATE_MACRO */
复制代码

上边这部分代码是用来做串口参数设置的。下边的代码中会用到。
在 CDC_Control_FS 函数中的对应位置添加如下 code
  1. case CDC_SET_LINE_CODING:
  2. pbuf[0] = (uint8_t)(LineCoding.bitrate);
  3. pbuf[1] = (uint8_t)(LineCoding.bitrate >> 8);
  4. pbuf[2] = (uint8_t)(LineCoding.bitrate >> 16);
  5. pbuf[3] = (uint8_t)(LineCoding.bitrate >> 24);
  6. pbuf[4] = LineCoding.format;
  7. pbuf[5] = LineCoding.paritytype;
  8. pbuf[6] = LineCoding.datatype;
  9. break;
复制代码

在 CDC_Receive_FS 函数中的对应位置添加如下代码
  1. <blockquote>/* USER CODE BEGIN 6 */
复制代码

这是用来接收 USB 传输的数据,并缓存到 UserTxBufferFS 这个数组中。
在最后添加如下函数
  1. /* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
  2. //this function is check the application buffer whether has data
  3. void Main_loop(void)
  4. {
  5. uint32_t buffsize;

  6. if(UserTxBufPtrOut != UserTxBufPtrIn)
  7. {
  8. if(UserTxBufPtrOut > UserTxBufPtrIn) /* Rollback */
  9. {
  10. buffsize= UserTxBufPtrIn;
  11. }
  12. else
  13. {
  14. buffsize = UserTxBufPtrIn - UserTxBufPtrOut;
  15. }

  16. CDC_Transmit_FS((uint8_t*)(UserTxBufferFS+UserTxBufPtrOut),buffsize);
  17. UserTxBufPtrOut += buffsize;
  18. USBD_CDC_ReceivePacket(hUsbDevice_0);
  19. }
  20. }
  21. /* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
复制代码

这个函数实现了一个简单的数据队列操作,一旦有数据收到,就将该数据发送到 PC 端,实现数据的环回功能。
在 main.c 的主循环中,调用 Main_loop 这个函数即可。
  1. /* USER CODE BEGIN WHILE */
  2. while (1)
  3. {
  4. Main_loop();
  5. /* USER CODE END WHILE */
复制代码

最后修改一下堆栈的大小:
在 MDK 中修改堆栈:
P62[[Q33_ATYECBZL]Y7B7S.png

IAR 中配置堆栈大小

F6)XDA532]G{4M1G$D_G(R4.png

编译后直接下载到 MCU 中即可以运行查看结果。
注意:硬件需要一根 Micro USB 线来连接板子的 USB 端口和 PC 机。
PC 端需要已经安装好 ST 提供 VCP 驱动程序。

U~P%L~C[$I2@9FQD94E@_XU.png

UAOUZGD6@8GAN]_BVHD_25H.png

问题总结:

STM32CubeMX 会使 STM32 全系列中的软件移植工作变得更方便。在一些以前看起来比较复杂的程序,在 Cube 中可以很简的完成。




收藏 评论0 发布时间:2022-3-2 22:17

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版