一、系统概述
USB CDC(Communications Device Class,通信设备类) 是USB协议中用于模拟串行通信的标准类,可将STM32虚拟为"USB转串口"设备,支持批量传输(Bulk Transfer) 模式(可靠、大数据量传输)。本方案基于STM32F103C8T6(USB Full Speed,12Mbps)和STM32CubeIDE(HAL库),实现USB CDC类的批量数据传输,核心功能包括:
-
虚拟串口通信(PC端识别为COM口);
-
批量数据收发(支持大文件/高速数据流);
-
自动枚举与配置(免驱或通用驱动)。
二、硬件设计
2.1 核心组件
| 模块 | 型号/参数 | 功能说明 |
|---|---|---|
| 主控 | STM32F103C8T6(64KB Flash,20KB RAM) | USB CDC协议处理、数据收发、批量传输管理 |
| USB接口 | Mini USB(DP/DM引脚) | 连接PC,实现USB 2.0全速通信(12Mbps) |
| 晶振 | 8MHz外部晶振(HSE) | 为USB提供48MHz时钟(需PLL倍频:8MHz×6=48MHz) |
| 电源 | 5V USB供电(或3.3V LDO) | 为STM32和USB模块供电 |
2.2 硬件连接
| 模块 | 引脚(STM32F103C8T6) | 说明 |
|---|---|---|
| USB DP | PA12(USB_D+) | USB数据正线(D+) |
| USB DM | PA11(USB_D-) | USB数据负线(D-) |
| 晶振 | OSC_IN(PD0)、OSC_OUT(PD1) | 8MHz外部晶振(HSE) |
三、软件设计(STM32CubeIDE + HAL库)
3.1 开发环境
-
IDE:STM32CubeIDE 1.13.0+
-
库:STM32Cube_FW_F1_V1.8.0(HAL库)
-
工具链:GCC ARM Embedded
3.2 CubeMX配置(关键步骤)
-
时钟配置:
- 选择HSE(8MHz),配置PLL:8MHz×6=48MHz(USB时钟需48MHz),系统时钟72MHz。
-
USB配置:
-
使能USB_OTG_FS(全速模式,设备模式);
-
选择Communication Device Class (CDC),配置参数:
-
厂商ID(Vendor ID):0x0483(ST官方)
-
产品ID(Product ID):0x5740(自定义)
-
字符串描述符:厂商、产品、序列号(可选)。
-
-
-
端点配置:
-
CDC类默认使用3个端点:
-
控制端点(EP0):默认,用于枚举;
-
批量IN端点(EP1):数据从STM32→PC(地址0x81,最大包长64字节);
-
批量OUT端点(EP2):数据从PC→STM32(地址0x02,最大包长64字节)。
-
-
-
生成代码:选择"Generate peripheral initialization as a pair of .c/.h files per peripheral",生成工程。
3.3 核心代码实现
3.3.1 USB CDC初始化(自动生成+补充)
CubeMX生成的usbd_cdc_if.c文件包含CDC接口函数,需补充数据收发逻辑:
c
#include "usbd_cdc_if.h"
#include "usbd_cdc.h"
// 数据接收缓冲区(PC→STM32)
uint8_t CDC_OutBuffer[1024]; // 1KB缓冲区
uint16_t CDC_OutLen = 0; // 接收长度
// 数据发送缓冲区(STM32→PC)
uint8_t CDC_InBuffer[1024]; // 1KB缓冲区
// CDC接收回调(PC→STM32,批量OUT端点数据到达)
static int8_t CDC_ReceiveCallback(uint8_t* Buf, uint32_t *Len) {
CDC_OutLen = *Len; // 记录接收长度
memcpy(CDC_OutBuffer, Buf, *Len); // 复制到缓冲区
USBD_CDC_ReceivePacket(&hUsbDeviceFS); // 准备接收下一包
return (USBD_OK);
}
// CDC接口结构体(注册回调函数)
USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = {
CDC_Init,
CDC_DeInit,
CDC_Control,
CDC_ReceiveCallback // 接收回调
};
// 发送数据(STM32→PC,批量IN端点)
void CDC_SendData(uint8_t *data, uint16_t len) {
if (len > sizeof(CDC_InBuffer)) len = sizeof(CDC_InBuffer); // 限幅
memcpy(CDC_InBuffer, data, len);
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, CDC_InBuffer, len); // 设置发送缓冲区
USBD_CDC_TransmitPacket(&hUsbDeviceFS); // 启动发送
}
3.3.2 主函数(数据收发测试)
c
#include "main.h"
#include "usbd_cdc_if.h"
int main(void) {
HAL_Init();
SystemClock_Config(); // 时钟配置(含USB 48MHz)
MX_GPIO_Init();
MX_USB_DEVICE_Init(); // 初始化USB CDC
uint8_t tx_data[] = "Hello CDC Bulk Transfer!\r\n";
uint16_t tx_len = sizeof(tx_data) - 1; // 不含结束符
while (1) {
// 1. 发送数据(每1秒发一次)
CDC_SendData(tx_data, tx_len);
HAL_Delay(1000);
// 2. 接收数据(若有数据到达)
if (CDC_OutLen > 0) {
// 回传接收数据( echo )
CDC_SendData(CDC_OutBuffer, CDC_OutLen);
CDC_OutLen = 0; // 清空接收标志
}
}
}
3.3.3 关键函数说明
-
USBD_CDC_TransmitPacket():
- 启动批量IN端点(EP1)传输,将数据从
CDC_InBuffer发送到PC,需等待传输完成(可通过USBD_CDC_GetTxState()查询状态)。
- 启动批量IN端点(EP1)传输,将数据从
-
USBD_CDC_ReceivePacket():
- 在接收回调中调用,通知USB核心"已处理完当前OUT端点数据,准备接收下一包",避免端点挂起。
-
数据缓冲管理:
- 使用双缓冲(如
CDC_OutBuffer和CDC_InBuffer)避免数据覆盖,大文件传输时可分块读写。
- 使用双缓冲(如
参考代码 STM32 USB批量传输 CDC类 www.youwenfan.com/contentcss/56562.html
四、批量传输优化
4.1 高速传输配置
-
增大端点包长:在CubeMX中修改端点最大包长(如从64字节→512字节,需USB FS支持,实际最大64字节@全速);
-
使用DMA:配置USB DMA传输(HAL库支持),减少CPU干预,提升效率。
4.2 数据校验与重传
-
CRC校验:在应用层添加CRC16/32校验(如STM32硬件CRC模块),确保数据完整性;
-
重传机制:若PC未收到数据(如超时),STM32可重发(需自定义协议,如添加序列号)。
4.3 多数据包处理
- 分块传输 :大文件(>64字节)需分多个批量包发送,PC端用
ReadFile循环读取,STM32用CDC_ReceiveCallback累积数据。
五、测试与验证
5.1 硬件连接
- STM32通过Mini USB线连接PC,PC端识别为"Virtual COM Port"(如COM3)。
5.2 测试工具
-
串口助手(如XCOM、Putty):选择对应COM口,波特率任意(CDC类不依赖波特率),发送数据到STM32,观察回传。
-
Bus Hound(高级测试):监控USB批量传输包,分析数据正确性。
5.3 预期结果
-
PC发送"Test"→STM32回传"Test";
-
发送1KB数据→STM32正确接收并回传,无丢包/错包。
六、关键问题与解决方案
6.1 USB枚举失败
-
原因:USB时钟未配置为48MHz(STM32F103需HSE 8MHz+PLL×6=48MHz);
-
解决 :检查
SystemClock_Config()中RCC_OscInitStruct.PLL.PLLMUL是否为RCC_PLL_MUL6。
6.2 数据接收卡顿
-
原因 :接收缓冲区过小(如<64字节),或未及时调用
USBD_CDC_ReceivePacket(); -
解决 :增大缓冲区(如1KB),在
CDC_ReceiveCallback中立即调用USBD_CDC_ReceivePacket()。
6.3 驱动问题
-
免驱方案 :使用ST官方提供的
stmcdc.inf驱动(Windows),或Linux/macOS原生支持; -
自定义VID/PID:需在PC端安装对应驱动(避免与现有设备冲突)。
七、总结
本方案基于STM32F103和USB CDC类实现了批量数据传输,核心是虚拟串口通信+批量端点(BULK)传输。通过CubeMX快速配置+HAL库函数调用,可快速实现高速、可靠的数据交互,适用于工业控制、数据采集、设备调试等场景。