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

7.2 KiB
Raw Permalink Blame History

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 字节)

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 字节)

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 结构

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 双缓冲设计

/* 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 双缓冲 TX 策略、任务调度
TCP通信模块设计.md TcpLogic_BuildAndSendTemperatureFrame 调用链
对接集成指南.md 外部接入方协议帧构造示例