c
__USB_ALIGN_BEGIN static uint8_t usb_dev_cdc_cfgdesc[USB_CDC_CONFIG_DESC_SIZ] = {
0x09,
USB_CFG_DESCRIPTOR_TYPE,
USB_CDC_CONFIG_DESC_SIZ,
0x00,
0x02,
0x01,
0x00,
0xC0,
0x32,
0x08,
0x0B,
0x00,
0x02,
0x02,
0x02,
0x01,
0x04,
0x09,
USB_INTERFACE_DESCRIPTOR_TYPE,
0x00,
0x00,
0x01,
0x02,
0x02,
0x01,
0x00,
0x05,
0x24,
0x00,
0x10,
0x01,
0x05,
0x24,
0x01,
0x00,
0x01,
0x04,
0x24,
0x02,
0x02,
0x05,
0x24,
0x06,
0x00,
0x01,
0x07,
USB_ENDPOINT_DESCRIPTOR_TYPE,
CDC_CMD_EP,
0x03,
LOBYTE(CDC_CMD_PACKET_SIZE),
HIBYTE(CDC_CMD_PACKET_SIZE),
0xFF,
0x09,
USB_INTERFACE_DESCRIPTOR_TYPE,
0x01,
0x00,
0x02,
0x0A,
0x00,
0x00,
0x00,
0x07,
USB_ENDPOINT_DESCRIPTOR_TYPE,
CDC_OUT_EP,
0x02,
LOBYTE(MAX_CDC_PACKET_SIZE),
HIBYTE(MAX_CDC_PACKET_SIZE),
0x00,
0x07,
USB_ENDPOINT_DESCRIPTOR_TYPE,
CDC_IN_EP,
0x02,
LOBYTE(MAX_CDC_PACKET_SIZE),
HIBYTE(MAX_CDC_PACKET_SIZE),
0x00
} ;
F460 USB CDC(Communication Device Class)设备的完整配置描述符(Configuration Descriptor),它定义了该 USB 设备在 CDC 模式下的整体结构,包括接口、端点和 CDC 类特定的功能描述符。
我们将逐段解析这个描述符数组 usb_dev_cdc_cfgdesc,并解释每个字段的含义。
📌 总体结构说明
CDC 设备通常包含 两个接口:
- 通信类接口(Control Interface):用于发送/接收控制命令(如 AT 指令),使用一个中断端点(IN)。
- 数据类接口(Data Interface):用于批量传输数据(如串口数据),使用两个批量端点(IN + OUT)。
此外,CDC 还需要若干 类特定描述符(Class-Specific Descriptors),如:
- Header Functional Descriptor
- Call Management Functional Descriptor
- ACM (Abstract Control Model) Functional Descriptor
- Union Functional Descriptor
这些都嵌套在第一个接口描述符之后、端点描述符之前。
🔍 逐段解析(按字节顺序)
✅ 1. 配置描述符(Configuration Descriptor)
c
0x09, // bLength = 9 字节
USB_CFG_DESCRIPTOR_TYPE, // bDescriptorType = 0x02 (配置描述符)
USB_CDC_CONFIG_DESC_SIZ, // wTotalLength = 整个配置描述符总长度(低字节)
0x00, // wTotalLength 高字节(假设为 0x0067 = 103 字节)
0x02, // bNumInterfaces = 2 个接口
0x01, // bConfigurationValue = 1(激活此配置时用)
0x00, // iConfiguration = 0(无配置字符串)
0xC0, // bmAttributes = 1100 0000
// D7=1(必须为1),D6=1(自供电),D5=0(不支持远程唤醒)
0x32 // MaxPower = 100 mA(0x32 * 2mA = 100mA)
💡 注意:
wTotalLength必须等于整个配置描述符(包括所有接口、端点、CDC 功能描述符)的总字节数。这里高字节是0x00,低字节来自宏USB_CDC_CONFIG_DESC_SIZ,应为0x67(103)左右。
✅ 2. IAD 描述符(Interface Association Descriptor)
⚠️ 虽然类型是
0x0B,但这是 IAD,用于告诉主机"接下来的多个接口属于同一个功能"。
c
0x08, // bLength = 8
0x0B, // bDescriptorType = IAD (0x0B)
0x00, // bFirstInterface = 0(从接口 0 开始关联)
0x02, // bInterfaceCount = 2(关联 2 个接口:0 和 1)
0x02, // bFunctionClass = CDC Communication Class (0x02)
0x02, // bFunctionSubClass = Abstract Control Model (ACM)
0x01, // bFunctionProtocol = AT Commands (V.250 etc.)
0x04 // iFunction = 4(配置字符串索引,对应你之前定义的 CONFIG_STR_IDX=4)
✅ IAD 是 USB 2.0 后推荐的方式,让复合设备(如 CDC+MSC)能被正确识别为一个逻辑设备。
✅ 3. 接口 0:通信类接口(Control Interface)
c
0x09, // bLength = 9
USB_INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType = 0x04(接口描述符)
0x00, // bInterfaceNumber = 0
0x00, // bAlternateSetting = 0
0x01, // bNumEndpoints = 1(只有命令端点)
0x02, // bInterfaceClass = CDC Communication (0x02)
0x02, // bInterfaceSubClass = ACM (0x02)
0x01, // bInterfaceProtocol = AT Commands (0x01)
0x00 // iInterface = 0(无接口字符串)
✅ 4. CDC 类特定描述符(嵌套在接口 0 中)
a) Header Functional Descriptor
c
0x05, // bLength = 5
0x24, // bDescriptorType = CS_INTERFACE (0x24)
0x00, // bDescriptorSubtype = Header (0x00)
0x10, 0x01 // bcdCDC = 0x0110 = USB CDC v1.10
b) Call Management Functional Descriptor
c
0x05, // bLength = 5
0x24, // CS_INTERFACE
0x01, // Subtype = Call Management (0x01)
0x00, // bmCapabilities = 0x00 → 不处理呼叫管理,由 Data Interface 处理
0x01 // bDataInterface = 1(数据接口编号)
c) ACM Functional Descriptor
c
0x04, // bLength = 4
0x24, // CS_INTERFACE
0x02, // Subtype = Abstract Control Management (0x02)
0x02 // bmCapabilities = 0x02 → 支持 Set_Line_Coding 等请求
d) Union Functional Descriptor
c
0x05, // bLength = 5
0x24, // CS_INTERFACE
0x06, // Subtype = Union (0x06)
0x00, // bMasterInterface = 0(控制接口)
0x01 // bSlaveInterface0 = 1(数据接口)
✅ 这些 CDC 功能描述符告诉主机:"这是一个 ACM CDC 设备,控制接口 0 管理数据接口 1"。
✅ 5. 端点:命令端点(Interrupt IN)
c
0x07, // bLength = 7
USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType = 0x05
CDC_CMD_EP, // bEndpointAddress = 如 0x83(IN 端点 3)
0x03, // bmAttributes = Interrupt(0x03)
LOBYTE(CDC_CMD_PACKET_SIZE), // wMaxPacketSize(低字节)
HIBYTE(CDC_CMD_PACKET_SIZE), // wMaxPacketSize(高字节,通常为 0)
0xFF // bInterval = 255 ms(中断端点轮询间隔)
⚠️ 注意:CDC 命令端点通常是 Interrupt IN,用于通知主机状态变化(如 DSR 变化),但在简单实现中可能不用。
✅ 6. 接口 1:数据类接口(Data Interface)
c
0x09, // bLength = 9
USB_INTERFACE_DESCRIPTOR_TYPE, // 接口描述符
0x01, // bInterfaceNumber = 1
0x00, // bAlternateSetting = 0
0x02, // bNumEndpoints = 2(IN + OUT)
0x0A, // bInterfaceClass = CDC Data (0x0A)
0x00, // bInterfaceSubClass = 0
0x00, // bInterfaceProtocol = 0
0x00 // iInterface = 0
💡 数据接口类为
0x0A(CDC Data),不是0x02!
✅ 7. 端点:数据 OUT(主机 → 设备)
c
0x07, // bLength = 7
USB_ENDPOINT_DESCRIPTOR_TYPE, // 端点描述符
CDC_OUT_EP, // 如 0x02(OUT 端点 2)
0x02, // bmAttributes = Bulk(0x02)
LOBYTE(MAX_CDC_PACKET_SIZE), // wMaxPacketSize(如 64)
HIBYTE(MAX_CDC_PACKET_SIZE), // 高字节(通常 0)
0x00 // bInterval = 0(Bulk 端点忽略此字段)
✅ 8. 端点:数据 IN(设备 → 主机)
c
0x07, // bLength = 7
USB_ENDPOINT_DESCRIPTOR_TYPE,
CDC_IN_EP, // 如 0x82(IN 端点 2)
0x02, // Bulk
LOBYTE(MAX_CDC_PACKET_SIZE),
HIBYTE(MAX_CDC_PACKET_SIZE),
0x00
🧾 总结:整体结构图
[Configuration Descriptor]
└── [IAD] ------ 关联接口 0 和 1
└── [Interface 0: CDC Control]
├── Header FD
├── Call Mgmt FD
├── ACM FD
├── Union FD
└── [Endpoint: Interrupt IN] ← 命令/通知
└── [Interface 1: CDC Data]
├── [Endpoint: Bulk OUT] ← 主机发数据
└── [Endpoint: Bulk IN] ← 设备发数据
🔧 常见宏值参考(需在代码中定义)
c
#define CDC_CMD_EP 0x83 // IN 端点 3
#define CDC_OUT_EP 0x02 // OUT 端点 2
#define CDC_IN_EP 0x82 // IN 端点 2
#define CDC_CMD_PACKET_SIZE 0x10 // 16 字节(命令端点)
#define MAX_CDC_PACKET_SIZE 0x40 // 64 字节(数据端点,全速 USB 最大)
#define USB_CDC_CONFIG_DESC_SIZ 0x67 // 总长度 = 103 字节
✅ 你可以用
sizeof(usb_dev_cdc_cfgdesc)验证总长度是否匹配USB_CDC_CONFIG_DESC_SIZ。
💡 提示
- Windows / Linux 会根据 IAD + CDC 描述符自动加载
cdc_acm或usbser驱动。 - 如果没有 IAD,某些旧系统可能无法正确识别双接口 CDC 设备。
- 确保
wTotalLength正确,否则枚举会失败!