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

【STM32U3评测】2、双串口通信

[复制链接]
网络孤客 发布时间:2025-6-8 11:33

一、CDC-ACM 和 CDC-VCP

以下来自AI CDC-ACM 和 CDC-VCP 都是基于 USB CDC (Communication Device Class) 实现虚拟串口的技术,但它们在标准化程度、驱动需求、功能支持和兼容性上有显著区别:

‌本质与标准化‌

CDC-ACM (Abstract Control Model):‌‌ 这是 USB-IF (USB Implementers Forum) 官方定义的 CDC 子类规范。它是一个标准化的协议,旨在通过 USB 提供一个通用的串行通信抽象模型。遵循 CDC-ACM 规范的设备在主机端应使用操作系统内置的 CDC-ACM 通用驱动程序。 ‌CDC-VCP (Virtual COM Port):‌ 这通常指的是 ‌厂商使用专用驱动实现的虚拟串口方案‌。虽然底层可能利用了 CDC 类的基础通信机制,但 VCP 驱动是芯片厂商(如 FTDI, Silabs, Prolific, Microchip, ST 等)开发的‌专有驱动‌,用于将 USB 设备仿真成一个功能完整的传统 COM 端口(RS-232),并支持高级串口功能。它不是 USB-IF 定义的标准子类描述符名称,而是实践中对这类特定实现方式的称呼。

‌驱动需求与兼容性‌

‌‌CDC-ACM:‌‌ 依赖于操作系统内置的通用 usbser.sys (Windows) 或 cdc_acm.ko (Linux) 驱动。现代操作系统(Win 10/11, Linux, macOS)通常已集成此驱动。但兼容性有时受限: ‌- Windows:‌ 早期版本(如 Win 7, XP)默认不包含或支持有限,需要额外安装 INF 文件或特定驱动包,且可能面临驱动签名问题26。Win 10 及之后版本内置支持较好。 ‌- 功能限制:‌ 通用驱动可能不支持串口的所有高级功能(如硬件流控 RTS/CTS, DTR/DSR)或在高波特率下稳定性不如专用驱动67。 ‌‌‌CDC-VCP:‌‌ 必须安装芯片厂商提供的专用驱动程序(如 FTDI VCP, CP210x VCP, CH340 VCP 等)。优点是:

  • 通常能提供‌完整的串口功能支持‌(波特率、数据位、停止位、校验位、硬件流控等)。
  • 在‌高波特率和持续传输下往往更稳定可靠。
  • 缺点是需要用户手动安装驱动,增加了部署复杂度。

功能支持‌‌

CDC-ACM:‌ 提供基础的 USB 到串行数据透传功能。是否支持完整的串行端口参数配置(波特率、硬件流控等)取决于‌操作系统驱动‌的实现程度以及‌设备固件‌是否实现了相应的 CDC ACM 类特定请求。通用驱动可能不启用或不支持所有功能。 CDC-VCP:‌‌ 专用驱动‌旨在精确模拟传统硬件 COM 端口‌。因此,它通常提供对串口所有标准功能的全面支持,包括硬件流控(RTS/CTS, DTR/DSR)和广泛的波特率范围,并能达到接近原生串口的性能和稳定性。

开发与使用‌

CDC-ACM:‌‌‌ 设备固件开发相对直接,主要遵循 USB CDC ACM 类规范描述符和请求实现数据透传即可69。目标是希望利用操作系统内置驱动实现免驱或简化驱动安装(在现代系统上)。 CDC-VCP:‌‌‌ 设备固件需要实现与‌厂商专用驱动约定的特定协议和描述符‌。开发复杂度可能更高或依赖于厂商提供的库/框架(如 STM32 Cube 库中的 VCP 实现)。目标是提供与物理串口兼容性最好的用户体验,接受安装专用驱动的代价。

二、建立工程

我采用Example中Ux_Device_CDC_ACM样例

1、工程部分

屏幕截图2025-06-08102710.png

建立后,打开配置工程,工程中已配置USART1与USB接口

其中为USB勾选了Threadx和USBX两个Middlewares:

USBX配置选择:UX Device FS,并勾选CDC ACM屏幕截图2025-06-08080812.png

系统Timebase源选择TIM6屏幕截图2025-06-08112148.png

2、代码部分

main.c

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_GPDMA1_Init();
  MX_ICACHE_Init();
  MX_ThreadX_Init();
  ...
  while (1)
  {
  }
}



void MX_USART1_UART_Init(void)
{

/* USER CODE BEGIN USART1_Init 0 */

/* USER CODE END USART1_Init 0 */

/* USER CODE BEGIN USART1_Init 1 */

/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */

/* USER CODE END USART1_Init 2 */

}

/**

* @brief USB Initialization Function
* @param None
* @retval None
  */
  void MX_USB_PCD_Init(void)
  {

/* USER CODE BEGIN USB_Init 0 */

/* USER CODE END USB_Init 0 */

/* USER CODE BEGIN USB_Init 1 */

/* USER CODE END USB_Init 1 */
hpcd_USB_DRD_FS.Instance = USB_DRD_FS;
hpcd_USB_DRD_FS.Init.dev_endpoints = 8;
hpcd_USB_DRD_FS.Init.speed = USBD_FS_SPEED;
hpcd_USB_DRD_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd_USB_DRD_FS.Init.Sof_enable = DISABLE;
hpcd_USB_DRD_FS.Init.low_power_enable = DISABLE;
hpcd_USB_DRD_FS.Init.lpm_enable = DISABLE;
hpcd_USB_DRD_FS.Init.battery_charging_enable = DISABLE;
hpcd_USB_DRD_FS.Init.vbus_sensing_enable = DISABLE;
hpcd_USB_DRD_FS.Init.bulk_doublebuffer_enable = DISABLE;
hpcd_USB_DRD_FS.Init.iso_singlebuffer_enable = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_DRD_FS) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USB_Init 2 */

/* USER CODE END USB_Init 2 */

}

在主程序中,定义

void MX_USART1_UART_Init(void);
void MX_USB_PCD_Init(void);

但在哪调用呢? 原来MX_USART1_UART_Init()、MX_USB_PCD_Init()和HAL_UART_MspDeInit()都在MX_ThreadX_Init()中执行了。 这样使整个初始化步骤更简洁优雅。

三、运行

1、根据电路图连接

屏幕截图2025-06-08080323.png

屏幕截图2025-06-08104628.png

微信图片_2025-06-08_111322_330.jpg

2、运行效果

屏幕截图2025-06-08090444.png

收藏 评论0 发布时间:2025-6-8 11:33

举报

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