ch32v307_camera/doc/设计文档/对接集成指南.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

318 lines
13 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.

# 对接集成指南
> 文档版本1.0 · 日期2026-03-15 · 适用对象ConfigServer 开发方
>
> 本文档描述如何对接 CH32V307 红外采集端,内容直接来源于固件代码,无需阅读源码即可完成对接开发。
---
## 1. 网络接入参数
### 1.1 固定参数
| 参数 | 值 |
|------|-----|
| MCU IP | `192.168.7.10` |
| MCU 子网掩码 | `255.255.255.0` |
| MCU 网关 | `192.168.7.1` |
| 以太网规格 | 1000M RGMII标准以太网帧 |
### 1.2 服务端监听要求
Server 端需在 **192.168.7.50** 上监听两个 TCP 端口MCU 主动连入):
| 端口 | 用途 | 连接方向 |
|------|------|---------|
| **5511** | 控制流(握手/配置/心跳) | MCU → Server |
| **5512** | 数据流(温度帧上报) | MCU → Server |
> 两个连接均为 MCU 主动发起Server 侧需以 TCP ServerListen模式等待。
---
## 2. 握手流程
MCU 上电并完成内部初始化后,按以下顺序建立连接:
```
1. MCU 建立控制流 TCP 连接Server 5511
2. MCU 发送 TYPE_HANDSHAKEClass=CLASS_SYSTEM=0x04
Value 结构Handshake_t46 字节):
├─ ProtocolVersion: uint16_t = 0x0200协议 v2.0
├─ DeviceUUID[16]: 6 字节 MAC 地址填入前 6 字节,其余填 0
├─ AuthToken[16]: 全零(当前版本不鉴权)
├─ HardwareVersion[8]: "CH32V307"(参考)
└─ FirmwareVersion[8]: 固件版本号
3. Server 回复握手响应(同类型或 TYPE_ACK_PAYLOAD
MCU 收到响应后标记控制流"就绪"
4. MCU 建立数据流 TCP 连接Server 5512
5. 系统就绪,开始接受配置并上报数据
```
**重要**握手完成前MCU 不会上报任何温度帧。如 Server 长时间未收到数据,请检查握手响应是否正确发送。
---
## 3. 配置下发
配置通过**控制流5511**发送,支持三种配置类型,可单独或组合发送。
### 3.1 Config2D — 2D 触发模式配置
**帧格式**FrameHeaderClass=0x01, Type=0x22+ TLV + Config2D_t
Config2D_t 全字段(按结构体内存顺序,均小端序):
| 字段 | 类型 | 偏移 | 说明 | 推荐初始值 |
|------|------|------|------|-----------|
| `Enabled` | uint8_t | 0 | 1=启用 2D 模式0=禁用 | 1 |
| `IsLive` | uint8_t | 1 | 保留,填 0 | 0 |
| `DeviceId` | uint16_t | 2 | 设备 ID | 0 |
| `Width` | uint16_t | 4 | 传感器宽度256 | 256 |
| `Height` | uint16_t | 6 | 传感器高度192 | 192 |
| `Fps` | uint8_t | 8 | 期望帧率参考值DVP 硬件控制) | 25 |
| `Exposure` | uint32_t | 9 | 曝光时间(传感器支持时有效) | 0 |
| `AutoExposure` | uint8_t | 13 | 自动曝光0/1 | 0 |
| `MaskEnabled` | uint8_t | 14 | 掩码使能 | 0 |
| `MaskThreshold` | int16_t | 15 | 掩码阈值0.1°C/LSB | 0 |
| `MaskWidth` | uint16_t | 17 | 掩码宽度 | 0 |
| `MaskHeight` | uint16_t | 19 | 掩码高度 | 0 |
| `Angle` | int16_t | 21 | 旋转角度(当前未使用) | 0 |
| `TargetWidth` | uint16_t | 23 | 输出 ROI 宽度(像素) | 64 |
| `TargetHeight` | uint16_t | 25 | 输出 ROI 高度(像素) | 64 |
| `TriggerMode` | uint8_t | 27 | **0=内部温度触发1=外部 GPIO 触发** | 1 |
| `TriggerGpioLine` | uint8_t | 28 | 外部触发 GPIO 编号参考MCU 固定 PA15 | 0 |
| `TriggerDelayMs` | uint16_t | 29 | 触发后延迟采集的时间ms | 0 |
| `TriggerBurstCount` | uint8_t | 31 | 每次触发连拍帧数 | 3 |
| `TriggerInternalIntervalMs` | uint16_t | 32 | 连拍帧间隔ms | 200 |
| `TriggerTemperatureThreshold` | int16_t | 34 | 内部触发温度阈值0.1°C/LSB`800` = 80.0°C | 800 |
| `TriggerDebounceIntervalMs` | uint16_t | 36 | 外部触发防抖时间ms | 50 |
| `TriggerCondition` | uint8_t | 38 | 内部触发判据:**0=ROI 均值1=ROI 最大值** | 1 |
| `TriggerRoiX` | uint16_t | 39 | 触发检测 ROI 左上角 X | 0 |
| `TriggerRoiY` | uint16_t | 41 | 触发检测 ROI 左上角 Y | 0 |
| `TriggerRoiW` | uint16_t | 43 | 触发检测 ROI 宽度0=全帧) | 256 |
| `TriggerRoiH` | uint16_t | 45 | 触发检测 ROI 高度0=全帧) | 192 |
| `NGioDelay` | uint16_t | 47 | NG 输出 GPIO 脉宽ms | 200 |
| `OutputGpioLine` | uint8_t | 49 | 输出 GPIO 编号(固定 PA8 | 0 |
| `AlarmGpioLine` | uint8_t | 50 | 告警 GPIO当前未使用 | 0 |
| `AlarmHoldMs` | uint16_t | 51 | 告警持续时间(当前未使用) | 0 |
| `StoreNgImagesOnly` | uint8_t | 53 | 仅存储 NG 图像(当前未使用) | 0 |
| `TrainingEnabled` | uint8_t | 54 | 训练模式(当前未使用) | 0 |
| `TrainingSampleThreshold` | uint16_t | 55 | 训练样本阈值(当前未使用) | 0 |
| `ProcessingTimeoutMs` | uint16_t | 57 | 处理超时ms当前未使用 | 0 |
| `MaxProcessingQueueSize` | uint8_t | 59 | 最大处理队列(当前未使用) | 0 |
| `Reserved` | uint8_t | 60 | 保留,填 0 | 0 |
### 3.2 Config1D — 1D 采集模式配置
**帧格式**FrameHeaderClass=0x01, Type=0x23+ TLV + Config1D_t
Config1D_t 全字段:
| 字段 | 类型 | 偏移 | 说明 | 推荐初始值 |
|------|------|------|------|-----------|
| `Enabled` | uint8_t | 0 | 1=启用 1D 模式0=禁用 | 0 |
| `RunMode` | uint8_t | 1 | **0=停止采集1=运行** | 1 |
| `TriggerType` | uint8_t | 2 | **1=内部连续热帧2=外部PA15 GPIO** | 1 |
| `BufferSize` | uint16_t | 3 | 采集缓冲区大小(样本数,最大 512 | 200 |
| `TriggerTempLimit` | int16_t | 5 | 触发温度阈值0.1°C/LSB | 500 |
| `StartPointsToRemove` | uint16_t | 7 | 保留 | 0 |
| `ReferenceLength` | uint16_t | 9 | 参考长度(保留) | 0 |
| `HighTimerLimit` | uint16_t | 11 | 外部触发防抖等待时间ms | 100 |
| `TimerCLimit` | uint16_t | 13 | 保留 | 0 |
| `NgCountLimit` | uint8_t | 15 | 触发后连续低温帧数达此值则停止采集 | 5 |
| `LSizeStart` | uint16_t | 16 | 发送时去掉头部样本数(切片) | 0 |
| `RSizeStart` | uint16_t | 18 | 发送时去掉尾部样本数(切片) | 0 |
| `NGioDelay` | uint16_t | 20 | NG 输出脉宽ms1D 使用) | 200 |
| `OutputGpioLine` | uint8_t | 22 | 输出 GPIO固定 PA8 | 0 |
| `AlarmGpioLine` | uint8_t | 23 | 告警 GPIO未使用 | 0 |
| `AlarmHoldMs` | uint16_t | 24 | 告警持续(未使用) | 0 |
> **2D 与 1D 互斥**`Config2D.Enabled=1` 时 MCU 进入 2D 模式;`Config1D.Enabled=1` 且 `Config2D.Enabled=0` 时进入 1D 模式。同时置 1 时 2D 优先。
---
## 4. 温度帧接收
温度帧通过**数据流5512**接收,帧类型为 `TYPE_TEMP_FRAME(0x10)`Class=`CLASS_DATA(0x02)`
### 4.1 2D 温度帧解析
Value 布局TemperatureFrameHeader_t + 像素数组):
```
[TemperatureFrameHeader_t] 18 字节
├─ FrameNumber: uint32_t LE — 帧序号(与 DVP 帧计数对应)
├─ Width: uint16_t LE — 输出 ROI 宽度TargetWidth 或有效宽度)
├─ Height: uint16_t LE — 输出 ROI 高度
├─ MinTemp: int16_t LE — ROI 内最低温度0.1°C/LSB
├─ MaxTemp: int16_t LE — ROI 内最高温度0.1°C/LSB
├─ AvgTemp: int16_t LE — ROI 内平均温度0.1°C/LSB
├─ RoiTemp: int16_t LE — TriggerRoi 区域特征温度0.1°C/LSB
├─ FrameType: uint8_t — 帧类型标识0x01=触发帧0x02=TEMP_REQ 帧)
├─ Status: uint8_t — 状态0=正常)
├─ Is2D: uint8_t — 1=2D 矩阵帧
└─ Reserved: uint8_t — 填 0
[像素数组] Width × Height × 2 字节
每个像素uint16_t 小端序
排列行优先row0 col0, row0 col1, ..., row0 colW-1, row1 col0, ...
单位0.1°C/LSB转为摄氏度 = 原始值 × 0.1
```
**Python 解析示例**
```python
import struct
def parse_2d_frame(data: bytes):
hdr_fmt = '<IHHhhhhhBBBB' # TemperatureFrameHeader_t
hdr_size = struct.calcsize(hdr_fmt)
frame_num, w, h, min_t, max_t, avg_t, roi_t, _, ft, st, is2d, _ = struct.unpack_from(hdr_fmt, data)
pixels_raw = struct.unpack_from(f'<{w*h}H', data, hdr_size)
pixels_celsius = [v * 0.1 for v in pixels_raw]
# pixels_celsius[row * w + col] = 第 row 行、第 col 列的温度°C
return {
'frame_num': frame_num, 'width': w, 'height': h,
'max_temp': max_t * 0.1, 'min_temp': min_t * 0.1,
'pixels': pixels_celsius
}
```
### 4.2 1D 温度帧解析
`Is2D=0` 时,像素数组替换为 1D 样本序列。
Value 布局(同 TemperatureFrameHeader_t但 Width=点数Height=1
```
[TemperatureFrameHeader_t] 18 字节
├─ Width: 实际有效样本点数 N
├─ Height: 1
└─ Is2D: 0
[样本数组] N × 4 字节
每个样本TempPoint1D_t
├─ TimeOffset: uint16_t LE — 相对采集开始的 ms 偏移
└─ Temperature: uint16_t LE — 对应时刻温度0.1°C/LSB
```
**Python 解析示例**
```python
def parse_1d_frame(data: bytes):
hdr_fmt = '<IHHhhhhhBBBB'
hdr_size = struct.calcsize(hdr_fmt)
frame_num, n, _, min_t, max_t, avg_t, _, _, ft, st, is2d, _ = struct.unpack_from(hdr_fmt, data)
points = []
for i in range(n):
t_off, temp = struct.unpack_from('<HH', data, hdr_size + i*4)
points.append({'time_ms': t_off, 'temp_c': temp * 0.1})
return {'frame_num': frame_num, 'points': points}
```
---
## 5. 检测结果下发与 NG 输出
### 5.1 下发检测结果
Server 在图像处理完成后,通过**控制流5511**发送 `TYPE_DETECTION_RESULT(0x40)`Class=CLASS_CONTROL=0x01
Value 结构DetectionResult_t8 字节):
| 字段 | 类型 | 说明 |
|------|------|------|
| `FrameNumber` | uint32_t LE | 对应触发该结果的帧号 |
| `Result` | uint8_t | **0=NG不合格1=OK合格** |
| `Reserved[3]` | uint8_t[3] | 填 0 |
### 5.2 MCU NG 动作
收到 `Result=0`NG
- `PA8` 输出高电平
- 持续 `Config2D.NGioDelay`(默认 200 ms后自动恢复低电平
- `NGioDelay` 可通过 Config2D 配置调整1D 模式使用 Config1D.NGioDelay
> 外部报警装置应接在 PA8高电平有效持续时间可配置。
---
## 6. TEMP_REQ 按需截图
Server 可随时通过控制流请求当前热场快照,无需等待触发。
**请求帧**TYPE_CONFIG_COMMON0x20Class=CLASS_CONTROL=0x01中包含 TEMP_REQ 字段,或通过专用命令触发(具体字段由 `TcpLogic` 内部解析),携带 `is2dRequest` 标志1=请求 2D 帧0=请求 1D 帧)。
**MCU 响应**
- 下一个业务循环取当前 FrameBuffer 的最新帧
- `is2d=1`:执行 `Preprocess_Execute`,返回 ROI 裁切后的 2D 温度矩阵FrameType=0x02
- `is2d=0`:返回中心行 **30 个等间距采样点**,时间偏移仿真 0~600 ms非真实时间序列
- 仅在对应模式(`Config2D.Enabled` / `Config1D.Enabled`)为 1 时响应,否则忽略
---
## 7. 错误码参考
| 错误码 | 值 | 触发场景 | 建议处理 |
|--------|-----|---------|---------|
| `ERR_CRC` | `0x1001` | 帧 CRC 校验失败 | 检查发送数据是否正确,重发 |
| `ERR_VERSION` | `0x1002` | 协议版本不匹配(非 0x20 | 检查 Version 字段 |
| `ERR_LENGTH` | `0x1003` | FrameHeader.Length 与实际帧长不符 | 检查帧构造逻辑 |
| `ERR_AUTH` | `0x2001` | AuthToken 不匹配 | 当前版本 AuthToken 全零,不应触发 |
| `ERR_BUSY` | `0x2002` | 设备忙,拒绝处理 | 等待 100 ms 后重试 |
| `ERR_DEV_ID_CONFLICT` | `0x2003` | DevID 与已注册设备冲突 | 检查 DevID 分配 |
| `ERR_PARAM` | `0x3001` | 配置字段值非法 | 检查配置结构体字段范围 |
---
## 8. 对接故障排查
### 8.1 MCU 上电后无连接
- 检查 MCU IP 是否为 `192.168.7.10`Server 是否在 `192.168.7.50`
- 确保 Server 在 5511 和 5512 端口上已 Listen
- 检查以太网连接MCU 使用 1000M RGMII需 1 Gbps 交换机或兼容网卡)
- 调试串口USART3921600会打印 `TCP Connected, socket X` 确认连接
### 8.2 握手成功但无数据帧
- 确认已通过控制流下发 `Config2D``Enabled=1`)或 `Config1D``Enabled=1`
- 查看调试串口是否打印 `TRIGGER frm=N`2D 模式)或 `1D: internal trigger start`1D 模式)
- 若无触发,检查 `TriggerTemperatureThreshold` 是否过高
### 8.3 数据帧偶发丢失
- 检查 Server 是否及时 ACKTCP 窗口是否足够
- 调试串口打印 `2D TX fail``1D SEND ... ret=-1` 表示 MCU 侧发送失败(队列满或连接异常)
### 8.4 温度值异常(偏高或偏低约 10 倍)
- 确认传感器已配置为 **TMP 模式**(非 Y16 模式)。参见 `Doc/Mini212G2预配置指南.md`
- TMP 模式输出值已是 0.1°C/LSB解析时乘以 0.1 即为摄氏度
### 8.5 NG 输出不动作
- 确认发送的 DetectionResult.Result = 0NG而非 1OK
- 检查 `Config2D.NGioDelay` 是否已配置0 时默认 200 ms
- 核查 PA8 GPIO 连接是否正确
---
## 9. 相关文档
| 文档 | 内容 |
|------|------|
| [系统总览.md](系统总览.md) | MCU 固件架构总览 |
| [QDX协议设计.md](QDX协议设计.md) | 帧结构详细说明(供深度对接参考) |
| [TCP通信模块设计.md](TCP通信模块设计.md) | MCU 侧连接管理实现细节 |
| [Mini212G2预配置指南.md](../Mini212G2预配置指南.md) | 传感器 TMP 模式配置 |