# 对接集成指南 > 文档版本: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 Server(Listen)模式等待。 --- ## 2. 握手流程 MCU 上电并完成内部初始化后,按以下顺序建立连接: ``` 1. MCU 建立控制流 TCP 连接(Server 5511) │ ↓ 2. MCU 发送 TYPE_HANDSHAKE(Class=CLASS_SYSTEM=0x04) Value 结构(Handshake_t,46 字节): ├─ 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 触发模式配置 **帧格式**:FrameHeader(Class=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 采集模式配置 **帧格式**:FrameHeader(Class=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 输出脉宽(ms,1D 使用) | 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 = ' 外部报警装置应接在 PA8,高电平有效,持续时间可配置。 --- ## 6. TEMP_REQ 按需截图 Server 可随时通过控制流请求当前热场快照,无需等待触发。 **请求帧**:TYPE_CONFIG_COMMON(0x20,Class=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 交换机或兼容网卡) - 调试串口(USART3,921600)会打印 `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 是否及时 ACK,TCP 窗口是否足够 - 调试串口打印 `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 = 0(NG),而非 1(OK) - 检查 `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 模式配置 |