ch32v307_camera/doc/设计文档/QDX协议设计.md
zhoujie b69717b964 📝 docs(design): 新增系统设计文档集
 feat(system-overview): 创建系统总览文档
- 描述项目背景与硬件平台配置
- 提供 FreeRTOS 任务拓扑表(任务优先级、栈大小、职责)
- 详细说明系统启动序列和初始化依赖关系
- 绘制 2D/1D 状态机完整流程图
- 解释 TEMP_REQ 辅助通道工作机制
- 说明任务间同步机制(Frame_Ready_Flag、双缓冲 TX)

 feat(dvp-module-design): 创建 DVP 模块设计文档
- 提供 DVP 硬件连接引脚映射表
- 描述 DVP 时序配置(信号极性、工作模式)
- 解释 DMA ping-pong 行缓冲机制和切换逻辑
- 说明 DVP IRQ 帧组装流程(STR_FRM/ROW_DONE)
- 定义 FrameBuffer 数据格式和像素访问方式
- 说明 TMP 模式温度换算公式和字节序要求

 feat(qdx-protocol-design): 创建 QDX 协议设计文档
- 描述完整 TLV 帧结构(FrameHeader + TLV + CRC)
- 列出所有 Class/Type 映射表和用途说明
- 解释零拷贝 TX 缓冲区架构(HeadOffset 机制)
- 说明分片机制和最大载荷限制
- 定义 Flags 字段各位含义和使用场景

 feat(tcp-module-design): 创建 TCP 通信模块设计文档
- 描述双流连接架构(控制流 5511 / 数据流 5512)
- 说明握手流程和连接建立时序
- 解释心跳机制和 TCP Keepalive 配置
- 描述配置下发与缓存机制
- 说明数据发送队列和背压处理策略
- 解释 WCHNET 网络栈驱动任务工作机制

 feat(integration-guide): 创建对接集成指南
- 提供网络接入参数表(IP、端口、协议)
- 详细说明握手流程和配置下发格式
- 提供 2D/1D 温度帧解析方法和示例代码
- 说明检测结果上报和 NG 响应机制
- 解释 TEMP_REQ 按需截图工作方式
- 列出错误码表和对接故障排查步骤
2026-03-15 19:17:41 +08:00

203 lines
7.2 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.

# QDX 协议设计文档
> 文档版本1.0 · 日期2026-03-15 · 状态:已发布
---
## 1. 模块概述
QDXnetworkStack 是本固件使用的应用层通信协议栈,基于 TLVType-Length-Value帧格式运行在 TCP/IP 之上。协议设计重点:
- **零拷贝 TX**预留帧头空间HeadOffset像素数据直接写入发送缓冲区帧头在发送前原地写入
- **双流架构**控制流5511与数据流5512职责分离
- **平台无关**:所有结构体 `#pragma pack(push, 1)`1 字节对齐,可在任意平台解析
源文件:`Middle/QDXnetworkStack/`
---
## 2. 帧结构
### 2.1 完整帧布局
```
┌─────────────────────────────────────────────────────────┐
│ FrameHeader16 字节) │
│ TLV Header3 字节) │
│ ValueN 字节) │
│ CRC162 字节Modbus CRC16覆盖 FrameHeader+TLV+Value
└─────────────────────────────────────────────────────────┘
```
总帧长 = 16 + 3 + N + 2 = **N + 21** 字节
### 2.2 FrameHeader16 字节)
```c
typedef struct {
uint16_t Magic; /* [0-1] 0x55AA — 帧同步魔数 */
uint8_t Version; /* [2] 0x20 — 协议版本 v2.0 */
uint16_t Length; /* [3-4] 整帧字节数(含 Header不含 CRC */
uint16_t Sequence; /* [5-6] 单调递增帧序号LE */
uint32_t Timestamp; /* [7-10] Unix 时间戳或 ms 计数LE */
uint8_t Source; /* [11] 0x01=MCU0x02=Server */
uint16_t DevID; /* [12-13]设备 IDLE */
uint8_t Class; /* [14] 消息类别 */
uint8_t Flags; /* [15] 控制标志位 */
} FrameHeader_t; /* 共 16 字节1 字节对齐 */
```
### 2.3 TLV Header3 字节)
```c
typedef struct {
uint8_t Type; /* [0] 帧类型 */
uint16_t Length; /* [1-2] Value 区域字节数LE */
} TLV_t;
```
---
## 3. Class 与 Type 映射表
### 3.1 消息类别Class
| 常量 | 值 | 说明 |
|------|----|------|
| `CLASS_CONTROL` | `0x01` | 配置 / 控制命令(服务器 → MCU |
| `CLASS_DATA` | `0x02` | 实时数据上报MCU → 服务器) |
| `CLASS_RESPONSE` | `0x03` | ACK / NACK / 错误响应 |
| `CLASS_SYSTEM` | `0x04` | 握手 / 心跳 / 系统同步 |
### 3.2 帧类型Type
| 常量 | 值 | 方向 | 说明 |
|------|----|------|------|
| `TYPE_HANDSHAKE` | `0x01` | 双向 | 握手Class=SYSTEM |
| `TYPE_HEARTBEAT` | `0x02` | 双向 | 心跳保活Class=SYSTEM |
| `TYPE_SYNC_TIME` | `0x03` | Server→MCU | 时间同步 |
| `TYPE_DEVID_ASSIGN` | `0x05` | Server→MCU | 设备 ID 分配 |
| `TYPE_TEMP_FRAME` | `0x10` | MCU→Server | 温度帧2D/1DClass=DATA |
| `TYPE_RAW_FRAME` | `0x11` | MCU→Server | 原始帧(预留) |
| `TYPE_CONFIG_COMMON` | `0x20` | Server→MCU | 公共配置 |
| `TYPE_CONFIG_2D` | `0x22` | Server→MCU | 2D 模式配置 |
| `TYPE_CONFIG_1D` | `0x23` | Server→MCU | 1D 模式配置 |
| `TYPE_ACK_PAYLOAD` | `0x30` | 双向 | ACK 响应体 |
| `TYPE_DETECTION_RESULT` | `0x40` | Server→MCU | 检测结果(含 NG 判定) |
### 3.3 Flags 字段位定义
| 位掩码 | 常量 | 说明 |
|--------|------|------|
| `0x03` | `FLAG_PRIORITY_MASK` | 优先级 0-30=最低) |
| `0x04` | `FLAG_COMPRESSED` | 压缩标志(当前固件未使用) |
| `0x08` | `FLAG_ENCRYPTED` | 加密标志(当前固件未使用) |
| `0x10` | `FLAG_ACK_REQ` | 要求接收方回复 ACK |
| `0x20` | `FLAG_LAST_FRAGMENT` | 分片末片标志 |
---
## 4. 零拷贝 TX 架构
### 4.1 TcpTxBuffer_t 结构
```c
typedef struct {
uint8_t *pBuffer; /* 分配的内存起点 */
uint32_t TotalCapacity; /* 总容量 = 9216 字节 */
uint32_t HeadOffset; /* 预留帧头空间 = 64 字节 */
uint32_t ValidPayloadLen;/* 当前有效 Value 数据长度 */
} TcpTxBuffer_t;
```
### 4.2 缓冲区内存布局
```
pBuffer
├──[0 ... 63]────────────────── HeadOffset64 字节预留区)
│ ← 发送前:写入 FrameHeader(16B) + TLV_Header(3B) = 19 字节
│ 从 HeadOffset - 19 = 偏移 45 处开始写入(帧头向前填充)
├──[64 ... 64+ValidPayloadLen-1]── Value 数据Preprocess 写入)
│ ← 图像像素 / 1D 样本 / 其他 payload
└──[64+ValidPayloadLen ... 9215] ── 未使用空间
+ [尾部 2 字节] CRC16追加在 Value 之后)
```
### 4.3 有效载荷容量计算
```
最大可用 Value 大小
= TotalCapacity(9216) - HeadOffset(64) - CRC(2) - TLV_Header(3) - FrameHeader(16)
= 9131 字节
对于 2D 温度帧(每像素 2 字节):
最多传输 9131 / 2 = 4565 个像素(约 67×67 ROI
```
### 4.4 双缓冲设计
```c
/* main.c 中声明 */
uint8_t g_TxNetBuffer_A_Mem[9216];
uint8_t g_TxNetBuffer_B_Mem[9216];
TcpTxBuffer_t g_TxNetBuffer_A = { .pBuffer = g_TxNetBuffer_A_Mem, .TotalCapacity = 9216, .HeadOffset = 64 };
TcpTxBuffer_t g_TxNetBuffer_B = { .pBuffer = g_TxNetBuffer_B_Mem, .TotalCapacity = 9216, .HeadOffset = 64 };
```
切换逻辑:`use_buffer_A` 标志在每次调用发送函数时取反,保证本帧发送入队后下一帧可立即填写另一个缓冲区。
---
## 5. 分片机制
### 5.1 分片限制
| 参数 | 值 | 说明 |
|------|-----|------|
| `MAX_FRAGMENT_PAYLOAD` | 1400 字节 | 受 TCP MSS=1460 制约1460 - HEADER=1400 |
| TX 缓冲区容量 | 9216 字节 | 单次发送通常不超过此限制,无需分片 |
### 5.2 分片标志
末片帧的 `Flags` 字段 `FLAG_LAST_FRAGMENT0x20` 置位,接收端以此判断分片结束。中间片段该位为 0。
> **当前固件实践**:绝大多数 2D 温度帧(最大 9131 字节)直接作为单个 TCP send 调用发送。WCHNET 底层在必要时分拆为多个 TCP 段,但协议层不显式分片。
---
## 6. Sequence 字段规则
- `Sequence` 字段为 `uint16_t`,每发送一帧单调递增
- 溢出后自然回滚65535 → 0
- 接收端 **不强制要求连续**,但可通过 Sequence 检测丢包(非连续 = 有帧丢失)
- 不同流(控制流 / 数据流)的 Sequence 互相独立计数
---
## 7. 错误码
| 常量 | 值 | 触发场景 |
|------|----|---------|
| `ERR_NONE` | `0x0000` | 无错误 |
| `ERR_CRC` | `0x1001` | CRC 校验失败 |
| `ERR_VERSION` | `0x1002` | 协议版本不匹配 |
| `ERR_LENGTH` | `0x1003` | 帧长度字段与实际不符 |
| `ERR_AUTH` | `0x2001` | 认证失败AuthToken 不匹配) |
| `ERR_BUSY` | `0x2002` | 设备忙,拒绝处理 |
| `ERR_DEV_ID_CONFLICT` | `0x2003` | DevID 冲突 |
| `ERR_PARAM` | `0x3001` | 参数非法(配置值越界等) |
---
## 8. 相关文档
| 文档 | 内容 |
|------|------|
| [系统总览.md](系统总览.md) | 双缓冲 TX 策略、任务调度 |
| [TCP通信模块设计.md](TCP通信模块设计.md) | `TcpLogic_BuildAndSendTemperatureFrame` 调用链 |
| [对接集成指南.md](对接集成指南.md) | 外部接入方协议帧构造示例 |