# USB CDC 串口通信协议规范 ## 概述 本协议定义了上位机(PC)与设备之间通过USB CDC进行音频数据传输和命令控制的通信格式。协议采用二进制帧格式,支持命令、音频数据和MD5校验等功能。 ## 协议版本 - 版本号:1.0 - 更新日期:2026-01-07 ## 帧格式 ### 基本帧结构 ``` +--------+--------+--------+--------+--------+--------+ | Magic | Type | Length | Data | Check | | 2 Bytes| 1 Byte | 4 Bytes | N Bytes| 1 Byte | +--------+--------+--------+--------+--------+--------+ ``` **注意:** 音频数据帧(Type=0x03)的Check字段固定填充为0x00,不进行实际校验计算,保持协议格式一致性。 ### 字段说明 | 字段 | 长度 | 说明 | |------|------|------| | Magic | 2 字节 | 魔数,固定为 `0xAA55`(大端序),用于帧同步 | | Type | 1 字节 | 数据类型,见下表 | | Length | 4 字节 | 数据长度(小端序),仅指Data字段的长度
**命令/响应/MD5帧**: ≤64字节
| | Data | N 字节 | 实际数据内容,长度由Length字段指定 | | Check | 1 字节 | 校验和,对整个帧(除Check字段外)进行XOR校验
**音频帧固定填充0x00** | **数据长度限制说明:** - 命令请求/响应/MD5帧的Data字段最大64字节 - 这种区分设计可节省非音频帧的内存占用 ### 数据类型(Type) | 类型值 | 名称 | 方向 | 说明 | |--------|------|------|------| | 0x01 | CMD_REQUEST | PC → 设备 | 命令请求 | | 0x02 | CMD_RESPONSE | 设备 → PC | 命令响应 | | 0x03 | AUDIO_DATA | 设备 → PC | 音频数据 | | 0x04 | MD5_DATA | 设备 → PC | MD5校验值 | ## 命令定义 ### 命令码 | 命令码 | 名称 | 说明 | |--------|------|------| | 0x01 | CMD_START_RECORD | 开始录音 | | 0x02 | CMD_STOP_RECORD | 停止录音 | | 0x03 | CMD_QUERY_STATUS | 查询状态 | ### 命令请求格式(CMD_REQUEST) **Data字段格式:** ``` +--------+--------+ | CmdID | Params | | 1 Byte | N Bytes| +--------+--------+ ``` - **CmdID**: 命令码 - **Params**: 命令参数(可选,长度根据具体命令而定) ### 命令响应格式(CMD_RESPONSE) **Data字段格式:** ``` +--------+--------+--------+ | CmdID | Status | Data | | 1 Byte | 1 Byte | N Bytes| +--------+--------+--------+ ``` - **CmdID**: 对应的命令码 - **Status**: 状态码(0x00=成功,0x01=失败,0x02=忙碌,0x03=不支持) - **Data**: 响应数据(可选) ### 状态码定义 | 状态码 | 名称 | 说明 | |--------|------|------| | 0x00 | STATUS_OK | 命令执行成功 | | 0x01 | STATUS_ERROR | 命令执行失败 | | 0x02 | STATUS_BUSY | 设备忙碌 | | 0x03 | STATUS_UNSUPPORTED | 不支持的命令 | ## 数据格式 ### 音频数据(AUDIO_DATA) **Data字段格式:** ``` +--------+--------+ | SeqNum | PCM | | 4 Bytes| N Bytes| +--------+--------+ ``` - **SeqNum**: 序列号(小端序),用于检测丢包,从0开始递增 - **PCM**: 原始PCM音频数据 **注意:** 音频数据帧保留Check校验字节,但固定填充为0x00,不进行实际校验计算。这样保持协议格式一致性,数据完整性由最终的MD5校验保证。 ### MD5数据(MD5_DATA) **Data字段格式:** ``` +--------+ | MD5 | |16 Bytes| +--------+ ``` - **MD5**: 音频数据的MD5哈希值(128位) ## 通信流程 ### 开始录音流程 ``` PC 设备 | | |---- CMD_START_RECORD ---->| | | 开始录音 |<--- CMD_RESPONSE(OK) -----| | | |<--- AUDIO_DATA(SeqNum=0)--| |<--- AUDIO_DATA(SeqNum=1)--| |<--- AUDIO_DATA(SeqNum=2)--| | ... | ``` ### 停止录音流程 ``` PC 设备 | | |---- CMD_STOP_RECORD ----->| | | 停止录音 |<--- AUDIO_DATA(last) -----| |<--- MD5_DATA -------------| |<--- CMD_RESPONSE(OK) -----| | | ``` ### 查询状态流程 ``` PC 设备 | | |---- CMD_QUERY_STATUS ---->| | | |<--- CMD_RESPONSE ---------| | (Status + Data) | | | ``` **查询状态响应Data格式:** ``` +--------+--------+--------+--------+ | State | TotalBytes | SeqNum | | 1 Byte | 4 Bytes | 4 Bytes| +--------+--------+--------+--------+ ``` - **State**: 当前状态(0x00=空闲,0x01=正在录音) - **TotalBytes**: 已传输的总字节数(小端序) - **SeqNum**: 当前序列号(小端序) ## 校验算法 ### XOR校验 对除Check字段外的所有字节进行XOR运算: ```c uint8_t calculate_checksum(uint8_t *data, uint32_t len) { uint8_t checksum = 0; for (uint32_t i = 0; i < len; i++) { checksum ^= data[i]; } return checksum; } ``` ### MD5校验 使用标准MD5算法对所有音频数据进行校验: 1. 设备端:对发送的所有PCM数据进行MD5计算 2. 停止录音后,设备发送MD5_DATA帧 3. PC端:对接收的所有PCM数据进行MD5计算并与设备端发送的MD5对比 ## 示例 ### 示例1:开始录音命令 **PC发送:** ``` AA 55 01 01 00 00 00 01 FA ``` 解析: - Magic: `AA 55` - Type: `01` (CMD_REQUEST) - Length: `01 00 00 00` (1字节,小端序) - Data: `01` (CMD_START_RECORD) - Check: `FA` (XOR校验) **设备响应:** ``` AA 55 02 02 00 00 00 01 00 F8 ``` 解析: - Magic: `AA 55` - Type: `02` (CMD_RESPONSE) - Length: `02 00 00 00` (2字节) - Data: `01 00` (CmdID=0x01, Status=0x00成功) - Check: `F8` ### 示例2:音频数据 **设备发送:** ``` AA 55 03 08 00 00 00 00 00 00 00 XX XX XX XX ``` 解析: - Magic: `AA 55` - Type: `03` (AUDIO_DATA) - Length: `08 00 00 00` (8字节) - Data: `00 00 00 00 XX XX XX XX` (SeqNum=0, PCM数据4字节) - Check: **无** (音频帧不包含校验字节) ### 示例3:MD5数据 **设备发送:** ``` AA 55 04 10 00 00 00 [16字节MD5] XX ``` 解析: - Magic: `AA 55` - Type: `04` (MD5_DATA) - Length: `10 00 00 00` (16字节) - Data: 16字节MD5值 - Check: `XX` ## 错误处理 ### 帧错误 1. **魔数错误**:丢弃当前字节,继续搜索魔数 2. **校验错误**:丢弃整个帧,请求重传(可选) 3. **长度异常**:丢弃整个帧 ### 超时处理 - **命令超时**:PC端发送命令后,2秒内未收到响应视为超时 - **数据超时**:录音过程中,5秒内未收到数据视为断连 ### 序列号检查 - PC端应检查音频数据的SeqNum是否连续 - 如果发现跳号,说明有数据丢失 ## 实现注意事项 ### 设备端(C语言) 1. **内存管理**:使用环形缓冲区管理数据帧 2. **多线程**:命令处理和数据发送应分开不同任务 3. **优先级**:命令处理优先级应高于音频数据发送 4. **MD5计算**:使用增量方式计算MD5,避免一次性读取所有数据 ### PC端(Python) 1. **异步接收**:使用独立线程接收数据 2. **帧解析**:实现状态机进行帧解析,处理粘包/拆包 3. **超时机制**:实现命令超时和数据超时检测 4. **MD5对比**:实时计算接收数据的MD5,录音结束后对比 ## 扩展性 协议预留了扩展空间: 1. **命令扩展**:可以添加新的命令码(0x04-0xFF) 2. **数据类型扩展**:可以添加新的数据类型(0x05-0xFF) 3. **参数扩展**:每个命令的Params字段可以自定义格式 ## 参考实现 - 设备端实现:[src/middleware/usb/app_usb_cdc.c](../src/middleware/usb/app_usb_cdc.c) - PC端实现:[tools/audio/serial_capture.py](../tools/audio/serial_capture.py) - 协议库:[src/middleware/usb/cdc_protocol.c](../src/middleware/usb/cdc_protocol.c) ## 版本历史 | 版本 | 日期 | 说明 | |------|------|------| | 1.0 | 2026-01-07 | 初始版本,定义基本协议格式和命令 | ## 联系方式 如有问题或建议,请联系开发团队。