首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >USB CDC串口通信详解:把USB变成“智能串口线”

USB CDC串口通信详解:把USB变成“智能串口线”

作者头像
一个平凡而乐于分享的小比特
发布2026-02-02 16:13:52
发布2026-02-02 16:13:52
7350
举报

🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习 🎬擅长领域:驱动开发,嵌入式软件开发,BSP开发 ❄️作者主页:一个平凡而乐于分享的小比特的个人主页 ✨收录专栏:通信协议,本专栏为记录项目中用到的知识点,以及一些硬件常识总结 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖

在这里插入图片描述
在这里插入图片描述

USB CDC串口通信详解:把USB变成“智能串口线”

一、CDC是什么?——USB时代的串口革命

CDC(Communications Device Class,通信设备类) 是一种USB设备类规范,它让USB设备可以模拟传统的串口(COM口),但性能大幅提升。

传统串口 vs USB CDC串口
代码语言:javascript
复制
传统串口(RS-232)时代:
┌─────────┐  串口线(9针)  ┌─────────┐
│ 单片机 │←---慢速+大电压--→│  电脑  │
└─────────┘ 最大115.2Kbps  └─────────┘
    问题:速度慢、需要专用接口、电压高

USB CDC时代:
┌─────────┐  USB CDC虚拟  ┌─────────┐
│ 嵌入式 │←---高速+即插即用--→│  电脑  │
└─────────┘ 可达12Mbps    └─────────┐
    优势:快、简单、标准、可供电

二、CDC在USB体系中的位置

代码语言:javascript
复制
USB设备类体系:
┌─────────────────────────────────┐
│      USB标准设备类               │
├─────────────────────────────────┤
│ 1️⃣ 大容量存储类(U盘、移动硬盘)  │
│ 2️⃣ HID类(键盘、鼠标)           │
│ 3️⃣ **CDC类(串口、网卡、调制解调器)**│ ← 今天的主角
│ 4️⃣ 音频类(耳机、麦克风)         │
│ 5️⃣ 视频类(摄像头)              │
└─────────────────────────────────┘

CDC子类(重点看串口):
• CDC ACM(Abstract Control Model):虚拟串口
• CDC ECM(Ethernet Control Model):虚拟网卡
• CDC NCM(Network Control Model):网络聚合
• CDC PCC(Phone Control Model):电话控制

三、CDC-ACM虚拟串口架构

CDC-ACM设备内部结构图
代码语言:javascript
复制
CDC-ACM设备内部端点配置:
┌─────────────────────────────────┐
│        CDC-ACM设备               │
│                                  │
│  控制接口(端点0 - 必需)         │ ← 管理命令
│   ├─ 类特定描述符                 │
│   └─ 端点0(双向控制端点)        │
│                                  │
│  数据接口(端点1、2 - 数据传输)   │
│   ├─ 端点1 IN(设备→主机)        │ ← 发送数据
│   └─ 端点2 OUT(主机→设备)       │ ← 接收数据
│                                  │
│  可选的端点3 IN(通知端点)       │ ← 状态变化通知
└─────────────────────────────────┘

四、CDC-ACM通信协议栈

代码语言:javascript
复制
CDC-ACM通信层次:
应用层(用户程序)
    ↓
串口API(COM1, COM2...)
    ↓
USB CDC驱动程序(usbser.sys / cdc_acm.ko)
    ↓
USB核心驱动
    ↓
USB主机控制器
    ↓
物理USB连接

五、CDC-ACM描述符详解(设备的“身份证”)

描述符集合结构
代码语言:javascript
复制
标准USB描述符 + CDC类特定描述符:

1. 设备描述符:我是CDC设备
   ┌─────────────────────────┐
   │ bDeviceClass:    0x02   │ ← 通信设备类
   │ bDeviceSubClass: 0x00   │
   │ bDeviceProtocol: 0x00   │
   └─────────────────────────┘

2. 配置描述符:我有两个接口
   ┌─────────────────────────┐
   │ 接口0:通信控制接口      │ ← 管理串口参数
   │ 接口1:数据接口          │ ← 实际数据传输
   └─────────────────────────┘

3. CDC类特定描述符(关键!):
   ┌─────────────────────────────────┐
   │ 头部功能描述符                   │
   │  • bDescriptorType: 0x24        │
   │  • bDescriptorSubtype: 0x00     │
   ├─────────────────────────────────┤
   │ 呼叫管理功能描述符               │
   │  • bmCapabilities: 0x00         │
   │  • bDataInterface: 0x01         │ ← 指向数据接口
   ├─────────────────────────────────┤
   │ ACM功能描述符                   │
   │  • bmCapabilities: 0x02         │ ← 支持线路控制
   ├─────────────────────────────────┤
   │ 联合功能描述符                  │
   │  • bControlInterface: 0x00      │ ← 控制接口编号
   │  • bSubordinateInterface: 0x01  │ ← 数据接口编号
   └─────────────────────────────────┘

六、CDC-ACM控制命令(串口参数设置)

标准串口控制命令表

命令代码

功能

参数

对应传统串口操作

0x00

SET_LINE_CODING

波特率、数据位等

配置串口参数

0x01

GET_LINE_CODING

读取当前设置

读取串口配置

0x02

SET_CONTROL_LINE_STATE

RTS/DTR控制

硬件流控

0x03

SEND_BREAK

发送Break信号

特殊通信信号

0x04-0x1F

保留

-

-

0x20-0xFF

类特定命令

厂商自定义

扩展功能

关键命令详解:SET_LINE_CODING
代码语言:javascript
复制
数据格式(7字节):
┌─────────┬─────────┬─────────┬─────────┬─────────┐
│ 波特率   │ 停止位  │ 校验位  │ 数据位  │ 特殊位  │
│ (4字节)  │ (1字节) │ (1字节) │ (1字节) │ (1字节) │
├─────────┼─────────┼─────────┼─────────┼─────────┤
│ 115200  │   1位    │  无校验  │  8位    │   0     │
│ 0x0001C200│  0x00   │  0x00   │ 0x08   │  0x00   │
└─────────┴─────────┴─────────┴─────────┴─────────┘

常用波特率对应值:
• 9600    → 0x00002580
• 115200  → 0x0001C200  
• 921600  → 0x000E1000
• 1000000 → 0x000F4240

七、完整通信流程示例

场景:STM32通过CDC虚拟串口发送"Hello"
代码语言:javascript
复制
时间线分析:
┌─[设备插入]─────────────────────────────┐
│ 1. 主机枚举设备,识别为CDC-ACM         │
│ 2. 加载usbser.sys驱动                  │
│ 3. 创建COM3虚拟串口                    │
├─[用户打开串口助手]─────────────────────┤
│ 4. 串口助手打开COM3,设置115200-8-N-1  │
│ 5. 发送SET_LINE_CODING命令             │
│ 6. 发送SET_CONTROL_LINE_STATE(1,1)     │
├─[STM32发送数据]───────────────────────┤
│ 7. STM32准备数据 "Hello\r\n"           │
│ 8. 通过端点1 IN发送数据包              │
│    PID=IN, 地址=xx, 端点=0x81          │
│    DATA=[0x48,0x65,0x6C,0x6C,0x6F,0x0D,0x0A]│
│ 9. 主机回复ACK                         │
├─[用户发送数据]────────────────────────┤
│ 10. 用户输入"AT\r"                     │
│ 11. 主机通过端点2 OUT发送              │
│     DATA=[0x41,0x54,0x0D]              │
│ 12. STM32接收并回复ACK                 │
└───────────────────────────────────────┘

八、CDC-ACM数据端点工作机制

数据流示意图
代码语言:javascript
复制
双向全双工通信:
┌─────────────┐               ┌─────────────┐
│   主机       │               │   设备       │
│ (Windows/Linux)│             │(STM32/ESP32)│
├─────────────┤               ├─────────────┤
│ 串口应用     │               │ 应用程序     │
│    ↓         │               │    ↓        │
│ CDC驱动      │               │ CDC固件     │
│    ↓         │               │    ↓        │
│ USB核心      │←---USB总线--→│ USB控制器   │
└─────────────┘               └─────────────┘

端点使用:
• 端点0:控制传输(配置命令)
• 端点1 IN:设备→主机(TX)
• 端点2 OUT:主机→设备(RX)
• 端点3 IN:通知(可选)
数据包大小优化
代码语言:javascript
复制
USB全速模式(12Mbps):
• 最大包大小:64字节
• 实际有效数据:≤63字节(1字节状态)
• 建议:一次发送≤60字节,避免碎片

USB高速模式(480Mbps):
• 最大包大小:512字节
• 可批量传输大块数据

九、实际开发:嵌入式CDC实现

STM32 CDC固件示例(简化)
代码语言:javascript
复制
// 1. USB设备描述符配置
const uint8_t CDC_DeviceDescriptor[] = {
  0x12,        // 描述符长度
  0x01,        // 设备描述符类型
  0x00, 0x02,  // USB 2.0
  0x02,        // 设备类:通信设备
  0x00,        // 设备子类
  0x00,        // 设备协议
  0x40,        // 端点0最大包大小
  // ... 厂商ID、产品ID等
};

// 2. CDC类特定描述符
const uint8_t CDC_ClassDescriptor[] = {
  // 头部功能描述符
  0x05,        // 长度
  0x24,        // 描述符类型:CS_INTERFACE
  0x00,        // 头部功能描述符子类型
  0x10, 0x01,  // USB CDC规范1.10
  
  // ACM功能描述符
  0x04,        // 长度
  0x24,        // CS_INTERFACE
  0x02,        // ACM功能描述符
  0x02,        // 能力:支持线路控制
  
  // 联合功能描述符
  0x05,        // 长度
  0x24,        // CS_INTERFACE
  0x06,        // 联合功能描述符
  0x00,        // 控制接口编号
  0x01,        // 数据接口编号
};

// 3. 处理控制命令
void CDC_ControlRequest(uint8_t cmd) {
  switch(cmd) {
    case 0x00: // SET_LINE_CODING
      // 读取波特率、数据位等参数
      USBD_CDC_SetLineCoding(&line_coding);
      break;
      
    case 0x01: // GET_LINE_CODING
      // 返回当前串口配置
      USBD_CDC_GetLineCoding(&line_coding);
      break;
      
    case 0x02: // SET_CONTROL_LINE_STATE
      // 设置RTS/DTR状态
      USBD_CDC_SetControlLineState();
      break;
  }
}

// 4. 数据发送函数
void CDC_Transmit_DATA(uint8_t* data, uint16_t length) {
  // 通过端点1 IN发送数据
  USBD_CDC_TransmitPacket(CDC_IN_EP, data, length);
}

十、CDC与其他通信方式对比

特性

CDC-ACM虚拟串口

传统UART串口

USB HID

USB大容量存储

速度

12Mbps(全速)

115.2Kbps

1.5Mbps(低速)

480Mbps(高速)

驱动需求

系统自带

系统自带

系统自带

系统自带

开发复杂度

中等

简单

中等

复杂

实时性

好(有中断端点)

最好

典型延迟

1-10ms

可变

1-10ms

100ms+

适用场景

调试、配置、通信

板间通信

人机交互

文件传输

十一、常见CDC设备实例

1. CP2102/CH340 USB转串口芯片
代码语言:javascript
复制
工作流程:
电脑 ←USB(CDC)→ CP2102 ←UART(串口)→ 单片机
           ↓                   ↓
      虚拟COM口            真实串口信号

特点:
• 成本低(几元钱)
• 驱动广泛
• 支持多种波特率
2. STM32内置USB CDC
代码语言:javascript
复制
STM32F4系列:
┌─────────────────┐
│   STM32F407     │
│                 │
│ 应用程序        │
│    ↓            │
│ USB CDC固件库   │
│    ↓            │
│ USB OTG控制器  │←USB线→电脑
│    ↓            │
│ UART外设        │←可连接其他设备
└─────────────────┘
优势:节省外部芯片,成本更低
3. ESP32-S2/S3 USB CDC
代码语言:javascript
复制
ESP32-S3双芯片模式:
┌─────────────────┐
│    ESP32-S3     │
│                 │
│ 主CPU:运行用户程序 │
│    ↓            │
│ USB CDC协议栈   │
│    ↓            │
│ USB外设        │←用于程序下载+调试
│    ↓            │
│ UART0          │←连接外部设备
└─────────────────┘

十二、CDC通信的性能优化技巧

优化建议表

问题

原因

解决方案

数据丢失

缓冲区溢出

增加端点缓冲区大小

延迟大

轮询间隔长

使用中断传输代替批量

吞吐量低

小包发送

合并数据,使用最大包大小

CPU占用高

频繁中断

使用DMA传输

兼容性问题

描述符不规范

严格按照CDC规范

高级特性:USB CDC双通道
代码语言:javascript
复制
双虚拟串口设备(STM32示例):
端点分配:
• 端点0:控制端点
• 端点1 IN:CDC1 TX
• 端点2 OUT:CDC1 RX
• 端点3 IN:通知端点
• 端点4 IN:CDC2 TX
• 端点5 OUT:CDC2 RX

应用场景:
1. 调试日志输出(CDC1)
2. AT命令通信(CDC2)
3. 互不干扰,独立波特率

十三、调试与故障排查

常见问题及解决

现象

可能原因

排查步骤

设备无法识别

描述符错误

使用USB分析仪查看枚举过程

串口不显示

驱动问题

检查设备管理器,重新安装驱动

数据乱码

波特率不匹配

检查SET_LINE_CODING命令

发送数据丢失

缓冲区满

检查NAK响应,调整发送间隔

只能单向通信

端点配置错误

检查IN/OUT端点配置

USB分析仪看到的CDC通信
代码语言:javascript
复制
典型CDC通信分析:
[时间]      [方向]  [PID]    [内容]
00:00.001  主机→设备 SETUP   GET_DESCRIPTOR(设备)
00:00.002  设备→主机 DATA0   设备描述符
00:00.003  主机→设备 ACK     确认
00:00.010  主机→设备 SETUP   SET_CONFIGURATION(1)
00:00.011  设备→主机 ACK     确认
00:00.100  主机→设备 SETUP   SET_LINE_CODING
00:00.101  主机→设备 OUT     波特率115200数据
00:00.102  设备→主机 ACK     确认
00:00.200  设备→主机 IN      请求数据
00:00.201  设备→主机 DATA0   "Hello World"
00:00.202  主机→设备 ACK     确认

十四、CDC协议的未来发展

新特性与趋势
  1. 高速CDC:USB 3.0+支持,速度达5Gbps
  2. 多功能复合设备:CDC+大容量存储+HID集成
  3. 无线CDC:通过蓝牙或Wi-Fi模拟CDC
  4. WebUSB CDC:浏览器直接访问USB CDC设备
  5. 安全增强:加密通信,防窃听

十五、实用项目示例:DIY USB-CDC数据记录仪

硬件组成
代码语言:javascript
复制
┌─────────────┐  USB CDC  ┌─────────────┐
│ 传感器       │←---数据---→│ STM32F103   │
│ (温湿度/DHT11)│          │ (USB CDC设备)│
└─────────────┘           └──────┬──────┘
                                  │ USB线
                         ┌───────┴───────┐
                         │  电脑          │
                         │ 串口助手/Python│
                         └───────────────┘
固件关键代码
代码语言:javascript
复制
// 数据采集并发送
void DataLogger_Task(void) {
  float temperature, humidity;
  
  // 1. 读取传感器
  DHT11_Read(&temperature, &humidity);
  
  // 2. 格式化数据
  char buffer[64];
  sprintf(buffer, "Temp:%.1fC, Hum:%.1f%%\r\n", 
          temperature, humidity);
  
  // 3. 通过CDC发送
  CDC_Transmit_DATA((uint8_t*)buffer, strlen(buffer));
  
  // 4. 延时
  HAL_Delay(1000); // 每秒发送一次
}

总结:CDC的核心价值

CDC-ACM成功的关键在于它在USB的现代化优势串口的简单易用之间找到了完美平衡:

  1. 对用户透明:看起来、用起来都和传统串口一样
  2. 性能大幅提升:速度从Kbps提升到Mbps级别
  3. 即插即用:无需额外电源,自动安装驱动
  4. 标准化:所有操作系统都支持
  5. 灵活性:可软件配置波特率等参数

CDC本质上是一个翻译官

  • 对电脑说:“我是标准串口设备”
  • 对USB硬件说:“请以高速USB协议传输数据”
  • 在中间进行协议转换

这使得无数基于串口的传统设备(工业控制器、传感器、老式设备)能够平滑迁移到USB时代,而无需改变上位机软件。正是这种"承上启下"的设计,让CDC成为嵌入式开发中最重要、最常用的USB设备类之一。

下次使用Arduino、STM32或ESP32的USB功能时,你会知道,这简单的"串口"背后,是一套完整、精巧的USB CDC协议栈在工作!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • USB CDC串口通信详解:把USB变成“智能串口线”
    • 一、CDC是什么?——USB时代的串口革命
      • 传统串口 vs USB CDC串口
    • 二、CDC在USB体系中的位置
    • 三、CDC-ACM虚拟串口架构
      • CDC-ACM设备内部结构图
    • 四、CDC-ACM通信协议栈
    • 五、CDC-ACM描述符详解(设备的“身份证”)
      • 描述符集合结构
    • 六、CDC-ACM控制命令(串口参数设置)
      • 标准串口控制命令表
      • 关键命令详解:SET_LINE_CODING
    • 七、完整通信流程示例
      • 场景:STM32通过CDC虚拟串口发送"Hello"
    • 八、CDC-ACM数据端点工作机制
      • 数据流示意图
      • 数据包大小优化
    • 九、实际开发:嵌入式CDC实现
      • STM32 CDC固件示例(简化)
    • 十、CDC与其他通信方式对比
    • 十一、常见CDC设备实例
      • 1. CP2102/CH340 USB转串口芯片
      • 2. STM32内置USB CDC
      • 3. ESP32-S2/S3 USB CDC
    • 十二、CDC通信的性能优化技巧
      • 优化建议表
      • 高级特性:USB CDC双通道
    • 十三、调试与故障排查
      • 常见问题及解决
      • USB分析仪看到的CDC通信
    • 十四、CDC协议的未来发展
      • 新特性与趋势
    • 十五、实用项目示例:DIY USB-CDC数据记录仪
      • 硬件组成
      • 固件关键代码
    • 总结:CDC的核心价值
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档