Files
arcs/tools/audio/usb_cdc_protocol.md
2026-08-13 16:50:52 +08:00

314 lines
7.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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字段的长度<br>**命令/响应/MD5帧**: ≤64字节<br>|
| Data | N 字节 | 实际数据内容长度由Length字段指定 |
| Check | 1 字节 | 校验和对整个帧除Check字段外进行XOR校验<br>**音频帧固定填充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: **无** (音频帧不包含校验字节)
### 示例3MD5数据
**设备发送:**
```
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 | 初始版本,定义基本协议格式和命令 |
## 联系方式
如有问题或建议,请联系开发团队。