# CH32V307 TCPClient 模式配置与功能说明 > **版本**: v2.0 — 自主触发架构 > **更新日期**: 2026-03 > **适用代码**: main.c 自主触发架构(已移除所有 `TEST_ENABLE_*` 编译开关) ## 目录 1. [系统架构概述](#1-系统架构概述) 2. [运行模式说明](#2-运行模式说明) 3. [编译期常量总表](#3-编译期常量总表) 4. [自主触发架构详解](#4-自主触发架构详解) 5. [2D 触发状态机](#5-2d-触发状态机) 6. [1D 采集状态机](#6-1d-采集状态机) 7. [TEMP_REQ 辅助通道](#7-temp_req-辅助通道) 8. [测试模式详解](#8-测试模式详解) 9. [正常模式详解](#9-正常模式详解) 10. [网络与服务器配置](#10-网络与服务器配置) 11. [配置下发流程](#11-配置下发流程) 12. [RTOS 任务架构](#12-rtos-任务架构) 13. [GPIO 引脚分配](#13-gpio-引脚分配) 14. [功能完整性对照表](#14-功能完整性对照表) 15. [已知注意事项](#15-已知注意事项) --- ## 1. 系统架构概述 本系统基于 CH32V307WCU6 (RISC-V) 微控制器,运行 FreeRTOS 实时操作系统,通过 WCHNET TCP/IP 协议栈与上位机通信。系统行为完全由运行时服务器配置驱动——服务器下发 Config2D/Config1D 并设置 `Enabled=1` 后,MCU 自主执行触发检测和数据采集上报。 ### 硬件资源 | 资源 | 配置 | |------|------| | MCU | CH32V307WCU6 (RISC-V, 144MHz) | | FLASH | 128KB | | SRAM | 192KB (Option Bytes [7:5]=110) | | 传感器 | Mini212G2 (256×192, Y16 原始温度) | | 网络 | 1000M 以太网 RGMII (WCHNET) | | 串口波特率 | 921600 | ### 软件组件 | 组件 | 说明 | |------|------| | FreeRTOS v202112.00 | 实时操作系统,Heap=16KB | | WCHNET | 万瑞 TCP/IP 协议栈 | | QDX 协议栈 | 自定义 TLV 二进制通信协议 (0x55AA, v2.0) | | 预处理模块 | 滑窗 ROI 搜索 + 温度统计 + 自动降尺寸 | --- ## 2. 运行模式说明 系统仅保留一个编译期宏开关 `TEST_PATTERN_MODE`,控制数据来源。所有业务功能(触发、采集、NG 输出、心跳)在两种模式下均始终启用,行为由服务器运行时配置驱动。 ### 两种模式对比 | 对比项 | 测试模式 (`TEST_PATTERN_MODE=1`) | 正常模式 (`TEST_PATTERN_MODE=0`) | |--------|------|------| | **数据来源** | 软件生成模拟热图 (~10 FPS) | Mini212G2 传感器 DVP/DMA 采集 | | **硬件依赖** | 仅需网口,无需传感器 | 需连接 Mini212G2 + DVP 线缆 | | **初始化** | 跳过 `DVP_Init()` | 执行 DVP 初始化 | | **帧生成** | `task_test_pattern_entry` 任务周期填充 | DVP 行中断逐行 DMA 搬运 | | **默认配置** | 自动注入测试配置(2D Enabled=1, 内部触发, 80°C) | 等待服务器下发,默认不使能 | | **自主触发** | ✅ 立即工作(无需服务器) | ✅ 需服务器下发 Enabled=1 后激活 | | **TEMP_REQ** | ✅ 可用(需对应模式 Enabled=1) | ✅ 可用 | | **NG GPIO** | ✅ PA8 始终初始化 | ✅ PA8 始终初始化 | | **外部触发 GPIO** | ✅ PA15/EXTI15 始终初始化 | ✅ PA15/EXTI15 始终初始化 | --- ## 3. 编译期常量总表 所有宏定义位于 `prj/TCPClient/User/main.c` 文件头部。 ### 3.1 主模式开关 | 宏名 | 当前值 | 说明 | |------|--------|------| | `TEST_PATTERN_MODE` | **0** | **唯一编译开关**:1=测试模式,0=正常模式 | ### 3.2 业务常量 | 宏名 | 值 | 说明 | |------|-----|------| | `DEFAULT_BURST_COUNT` | 3 | 服务器未配置时的默认连拍帧数 | | `DEFAULT_BURST_INTERVAL_MS` | 200 | 服务器未配置时的默认连拍间隔 (ms) | | `MAX_TCP_PAYLOAD_SIZE` | 9216 | TCP 发送缓冲区大小 (字节) | | `KEEPALIVE_ENABLE` | 1 | TCP KeepAlive(20s 空闲 / 15s 探测 / 9 次) | | `TEST_FPS_DELAY_MS` | 100 | 测试模式帧生成间隔 (~10 FPS) | | `SNAPSHOT_1D_POINTS` | 30 | TEMP_REQ 1D 空间采样点数 | | `MAX_1D_POINTS` | 512 | 1D 采集缓冲最大样本数 | | `NG_PULSE_MS` | 200 | NG 脉冲默认宽度(服务器可通过 NGioDelay 覆盖) | ### 3.3 GPIO 引脚宏 | 宏名 | 值 | 说明 | |------|-----|------| | `EXT_TRIG_GPIO_PORT` | GPIOA | 外部触发输入端口 | | `EXT_TRIG_GPIO_PIN` | GPIO_Pin_15 | PA15 | | `EXT_TRIG_EXTI_LINE` | EXTI_Line15 | 外部中断线 | | `NG_GPIO_PORT` | GPIOA | NG 输出端口 | | `NG_GPIO_PIN` | GPIO_Pin_8 | PA8 | ### 3.4 传感器相关宏 (dvp.h) | 宏名 | 值 | 说明 | |------|-----|------| | `SENSOR_WIDTH` | 256 | 传感器像素宽度 | | `SENSOR_HEIGHT` | 192 | 传感器像素高度 | | `BYTES_PER_LINE` | 512 | 每行字节数 (256×2) | ### 3.5 传感器通信宏 (mini212g2.h) > 当前模组已通过 USB 预配置,MCU UART 配置功能已用 `#if 0` 关闭。 > **USART2 (PA2/PA3) 引脚已被占用,不可用于传感器通信。** | 宏名 | 当前值 | 说明 | |------|--------|------| | `SENSOR_UART_ENABLE` | **0 (已禁用)** | 传感器通过 USB 预配置 | --- ## 4. 自主触发架构详解 ### 4.1 核心设计原则 系统的所有业务行为由运行时服务器配置驱动,不再使用编译期功能开关: ``` 服务器下发 Config2D (Enabled=1) → MCU 自主执行 2D 触发/连拍/上报 服务器下发 Config1D (Enabled=1) → MCU 自主执行 1D 采集/上报 两者互斥:Config2D.Enabled 优先级高于 Config1D.Enabled ``` ### 4.2 主循环逻辑流程 ``` task_business_entry (优先级 5, 2ms 轮询) │ ├── [1] NG 脉冲超时检查 → 到期则拉低 PA8 │ ├── [2] DVP_Task() (仅正常模式) │ ├── 行 DMA 完成 → 复制到 FrameBuffer │ └── 最后一行 → Frame_Ready_Flag=1 │ ├── [3] TEMP_REQ 辅助通道(服务器按需截图) │ ├── 前提:对应模式 Enabled=1 │ ├── is2D=1 → Preprocess_Execute() → TCP 发送 (frameType=0x02) │ └── is2D=0 → send_1d_snapshot() → 30 点空间采样 │ └── [4] 自主触发主管线 │ 前提:Frame_Ready_Flag=1 && TcpLogic_GetLatestConfig OK │ ├── Config2D.Enabled=1 → handle_2d_trigger() │ (2D 触发状态机:消抖 → 延迟 → 连拍) │ └── Config1D.Enabled=1 → handle_1d_trigger() (1D 采集状态机:IDLE → DEBOUNCE → COLLECTING) ``` ### 4.3 回调注册 | 回调 | 注册函数 | 触发时机 | 处理 | |------|---------|---------|------| | `OnConfigUpdate` | `TcpLogic_RegisterConfigCallback` | 服务器下发配置 | → `Preprocess_Settings_Change()` | | `OnDetectionResult` | `TcpLogic_RegisterDetectionCallback` | 服务器返回检测结果 (resultStatus=0 为 NG) | → PA8 NG 脉冲 | | `OnTempFrameRequest` | `TcpLogic_RegisterTempFrameRequestCallback` | 服务器请求截图 | → 设置 `g_temp_req_pending` | --- ## 5. 2D 触发状态机 ### 5.1 状态机流程 ``` ┌─────────────┐ │ IDLE │ │ 等待触发 │ └──────┬──────┘ │ ┌────────────┼────────────┐ │ TriggerMode=0 │ TriggerMode=1 │ (内部触发) │ (外部触发) ▼ ▼ Preprocess_CheckInternalTrigger2D() PA15/EXTI15 上升沿 │ (TriggerRoi 区域 Max/Avg > Threshold) │ │ │ ┌──────────────┐ │ │ DEBOUNCE │ │ │ DebounceMs │ │ └──────┬───────┘ │ │ └─────────┬───────────────┘ ▼ ┌──────────────┐ │ DELAY │ │ DelayMs │ └──────┬───────┘ ▼ ┌──────────────┐ │ BURST │──┐ │ 发送第1帧 │ │ 剩余 BurstCount-1 帧 └──────────────┘ │ 间隔 InternalIntervalMs ▲ │ └──────────┘ │ ▼ Burst 完成 → 回到 IDLE ``` ### 5.2 关键 Config2D 字段 | 字段 | 类型 | 2D 触发中的作用 | |------|------|----------------| | `Enabled` | u8 | 1=启用 2D 管线 | | `TriggerMode` | u8 | 0=内部(温度), 1=外部(GPIO) | | `TriggerDebounceIntervalMs` | u16 | 外部触发消抖等待 (ms) | | `TriggerDelayMs` | u16 | 触发确认后延迟采集 (ms) | | `TriggerBurstCount` | u8 | 连拍帧数 | | `TriggerInternalIntervalMs` | u16 | 连拍帧间隔 (ms) | | `TriggerCondition` | u8 | 内部触发判定:0=平均温度, 1=最大温度 | | `TriggerTemperatureThreshold` | i16 | 内部触发温度阈值 (0.1°C/LSB) | | `TriggerRoiX/Y/W/H` | u16×4 | 内部触发检测区域 | | `TargetWidth` / `TargetHeight` | u16 | 预处理输出尺寸 | | `NGioDelay` | u16 | NG 脉冲宽度 (ms) | ### 5.3 2D 帧发送路径 ``` handle_2d_trigger() → start_2d_burst() → do_2d_capture_send() → Preprocess_Execute(raw, tx_buf, &meta) // 滑窗 ROI 搜索 → TcpLogic_BuildAndSendTemperatureFrame(tx_buf, &meta, 0x01, 1) // frameType=TRIGGER, is2D=1 ``` --- ## 6. 1D 采集状态机 ### 6.1 状态机流程 ``` ┌─────────────┐ │ S1D_IDLE │ (RunMode 必须=1) │ 等待触发 │ └──────┬──────┘ │ ┌────────────┼────────────┐ │ TriggerType=1 │ TriggerType=2 │ (内部触发) │ (外部触发) ▼ ▼ 前置环形缓冲(3样本) PA15/EXTI15 上升沿 连续3个 ≥ TriggerTempLimit │ │ ▼ │ ┌───────────────┐ │ │ S1D_DEBOUNCE │ │ │ HighTimerLimit │ │ └──────┬────────┘ │ │ └─────────┬───────────────┘ ▼ ┌────────────────┐ │ S1D_COLLECTING │ │ 逐帧采集温度点 │ │ (中心行最大值) │ └───────┬────────┘ │ ┌────────┼────────┐ │ 停止条件1 │ 停止条件2 │ BufferSize 满 │ 已触发 + NgCountLimit 连续冷点 │ │ └────────┬────────┘ ▼ 切片 [LSizeStart, -RSizeStart] │ ▼ send_1d_collection() → TCP 发送 │ ▼ 回到 S1D_IDLE ``` ### 6.2 1D 温度采样方式 每个 DVP 帧产生一个温度样本:取中心行所有像素的最大温度值(`get_1d_sample()`)。 ### 6.3 内部触发预环形缓冲 内部触发模式维护长度为 3 的环形缓冲: - 每帧写入一个样本到环形缓冲 - 当 3 个样本全部 ≥ `TriggerTempLimit` → 进入 COLLECTING 状态 - 环形缓冲内容(最旧在前)写入采集数组前 3 位 - 从第 4 位起继续采集 ### 6.4 关键 Config1D 字段 | 字段 | 类型 | 1D 采集中的作用 | |------|------|----------------| | `Enabled` | u8 | 1=启用 1D 管线 | | `RunMode` | u8 | 0=STOP, 1=RUN, 2=NOP, 3=DEBUG | | `TriggerType` | u8 | 1=内部(温度), 2=外部(GPIO) | | `BufferSize` | u16 | 单次采集最大样本数(停止条件) | | `TriggerTempLimit` | i16 | 触发/采集温度阈值 (0.1°C/LSB) | | `HighTimerLimit` | u16 | 外部触发消抖时间 (ms) | | `NgCountLimit` | u8 | 连续冷点数→停止采集 | | `LSizeStart` | u16 | 切片左起始偏移 | | `RSizeStart` | u16 | 切片右侧移除点数 | ### 6.5 1D 数据打包格式 每个样本点 4 字节 (Little-Endian): | 偏移 | 类型 | 说明 | |------|------|------| | 0-1 | u16 LE | TimeOffset (距采集开始的毫秒偏移) | | 2-3 | u16 LE | Temperature (0.1°C/LSB) | --- ## 7. TEMP_REQ 辅助通道 TEMP_REQ 是服务器主动请求的按需截图通道,与自主触发管线独立工作: - **2D 截图**:`Preprocess_Execute()` → 滑窗搜索 → 发送 `frameType=0x02`(MASKED) - **1D 截图**:`send_1d_snapshot()` → 从中心行等间距采样 30 点 → 发送 前提:对应模式 `Enabled=1`,否则请求被忽略并打印 `TEMP_REQ ignored`。 --- ## 8. 测试模式详解 ### 8.1 启用方式 ```c #define TEST_PATTERN_MODE 1 ``` 编译烧录即可,**无需连接任何传感器硬件**,仅需以太网连接。 ### 8.2 测试图案 系统自动循环生成 4 种测试图案(256×192 Y16 格式): | 图案 | 持续帧数 | 温度范围 | 是否触发 | 用途 | |------|---------|---------|---------|------| | **对角渐变** | 20 帧 | 25.0°C → 45.0°C | 否 | 基线测试 | | **中心热点** | 5 帧 | 背景 28~32°C, 中心 90.0°C | 是 (>80°C) | 触发测试 | | **均匀温场** | 10 帧 | 35.0°C | 否 | 无触发验证 | | **棋盘格** | 5 帧 | 28.0°C / 85.0°C 交替 | 是 (>80°C) | ROI 搜索测试 | 总周期:40 帧 ≈ 4 秒循环一次。 ### 8.3 自动注入测试配置 测试模式启动时通过 `TcpLogic_InjectTestConfig()` 注入以下配置(走标准缓存+回调路径): ``` Config2D: Enabled = 1 # 自动启用 2D 管线 TriggerMode = 0 # 内部触发(温度检测) TargetWidth = 64 # 预处理输出 64×64 TargetHeight = 64 TriggerRoiX/Y = 0, 0 # 全幅扫描 TriggerRoiW/H = 256, 192 TriggerCondition = 1 # 最大温度 TriggerTemperatureThreshold = 800 # 80.0°C TriggerBurstCount = 3 # 3 帧连拍 TriggerInternalIntervalMs = 200 NGioDelay = 200 ``` > **注入路径**:`TcpLogic_InjectTestConfig()` → 内部缓存 + `has_valid_config=1` → 触发 `OnConfigUpdate` 回调 → `Preprocess_Settings_Change()`。与服务器下发配置走完全相同的路径。 ### 8.4 启动串口输出示例 ``` TCPClient SystemClk:144000000 TEST_PATTERN=1 UserByte: c0 === TEST PATTERN MODE === No sensor/DVP hardware needed net version:1c WCHNET_LibInit Success Test config injected: En=1 TrigMode=Internal thresh=800 Tgt=64x64 burst=3 [HB] 0 tick=1010 TEST_MODE frm=9 2D internal trigger TRIGGER frm=21 2D SEND frm=21 64x64 ret=0 Burst start: 3 frames, interval=200 ms ``` --- ## 9. 正常模式详解 ### 9.1 启用方式 ```c #define TEST_PATTERN_MODE 0 ``` 需要: 1. Mini212G2 传感器正确连接 DVP 接口 2. 传感器已通过 USB 预配置为 CMOS/DVP Y16 输出 ### 9.2 硬件连接 #### DVP 引脚定义 | 功能 | GPIO | 说明 | |------|------|------| | DATA[0] | PA4 | 数据线 bit0 | | DATA[1] | PA5 | 数据线 bit1 | | DATA[2] | PA6 | 数据线 bit2 | | DATA[3] | PA9 | 数据线 bit3 | | DATA[4] | PA10 | 数据线 bit4 | | DATA[5] | PB3 | 数据线 bit5 | | DATA[6] | PB8 | 数据线 bit6 | | DATA[7] | PB9 | 数据线 bit7 | | HSYNC | PC8 | 行同步 | | VSYNC | PC9 | 场同步(高有效) | | PCLK | PC11 | 像素时钟(上升沿采样) | #### 传感器 UART(仅 USART3 可用) > ⚠ USART2 (PA2/PA3) 引脚已被占用,不可用于传感器通信。 | 配置 | USART3 | |------|--------| | TX | PB10 | | RX | PB11 | | 波特率 | 115200 | > 注意:启用 USART3 传感器通信会占用 printf 调试端口,需通过 JTAG 调试。 ### 9.3 正常模式数据流 ``` DVP 硬件中断 (DVP_IRQHandler) ├── STR_FRM 中断 → 帧开始,line_idx=0 └── ROW_DONE 中断 → 行完成,DMA 乒乓切换 │ 设置 Line_Ready_Flag=1 ▼ task_business_entry (优先级 5) │ DVP_Task() │ ├── 复制 DMA 行缓冲 → FrameBuffer[line_idx] │ └── 最后一行 → Frame_Ready_Flag=1 ▼ ├── [TEMP_REQ] 服务器按需截图 │ └── [自主触发] Config2D.Enabled → 2D 状态机 Config1D.Enabled → 1D 状态机 ``` ### 9.4 正常模式注意事项 - **无默认配置**:正常模式不注入测试配置,`Preprocess_Init()` 仅设置 `TargetWidth=1, TargetHeight=1`。必须等服务器下发 Config2D/Config1D 后才能工作。 - **传感器初始化**:模组已通过 USB 预配置,`mini212g2.h` 中 UART 配置已关闭。 - **帧率取决于传感器**:Mini212G2 在 DVP 模式下的帧率由传感器内部配置决定。 --- ## 10. 网络与服务器配置 ### 10.1 MCU 网络参数 定义位置:`main.c` | 参数 | 值 | 说明 | |------|-----|------| | IP 地址 | 192.168.7.10 | MCU 静态 IP | | 网关 | 192.168.7.1 | 默认网关 | | 子网掩码 | 255.255.255.0 | C 类子网 | | MAC 地址 | 由芯片自动获取 | 硬件 MAC | ### 10.2 服务器连接参数 定义位置:`qdx_tcp_logic.c` | 参数 | 值 | 说明 | |------|-----|------| | `SERVER_IP` | "192.168.7.50" | 服务器 IP | | `CONTROL_PORT` | 5511 | 控制通道端口 | | `DATA_PORT` | 5512 | 数据通道端口 | ### 10.3 TCP KeepAlive ```c #define KEEPALIVE_ENABLE 1 // main.c // 探测配置: 20s 空闲后每 15s 探测一次,最多 9 次 ``` ### 10.4 TCP 内部参数 | 参数 | 值 | 说明 | |------|-----|------| | `HEARTBEAT_INTERVAL_MS` | 2000 | 心跳发送间隔 | | `SERVER_TIMEOUT_MS` | 6000 | 服务器超时断连 | | `RECONNECT_DELAY_MS` | 3000 | 断连后重连等待 | | `MAX_FRAGMENT_PAYLOAD` | 1400 | 分片最大载荷 | --- ## 11. 配置下发流程 ### 11.1 TLV 消息类型 | TLV Type | 名称 | 方向 | 说明 | |----------|------|------|------| | 0x01 | TYPE_HANDSHAKE | ↔ | 握手(UUID、版本) | | 0x02 | TYPE_HEARTBEAT | ↔ | 心跳(上行/下行) | | 0x05 | TYPE_DEVID_ASSIGN | ← | 设备 ID 分配(触发重连) | | 0x10 | TYPE_TEMP_FRAME | ← | 请求温度帧(TEMP_REQ) | | 0x20 | TYPE_CONFIG_COMMON | ← | 通用配置 | | 0x22 | TYPE_CONFIG_2D | ← | 2D 配置 | | 0x23 | TYPE_CONFIG_1D | ← | 1D 配置 | | 0x30 | TYPE_ACK_PAYLOAD | ← | ACK 响应 | | 0x40 | TYPE_DETECTION_RESULT | ← | 检测结果(OK/NG) | ### 11.2 Config2D 关键字段 | 字段 | 偏移 | 类型 | 说明 | |------|------|------|------| | Enabled | 0 | u8 | **使能开关** | | Width | 4 | u16 LE | 设备分辨率宽度(仅标记) | | Height | 6 | u16 LE | 设备分辨率高度(仅标记) | | **TargetWidth** | **23** | **u16 LE** | **预处理输出宽度** | | **TargetHeight** | **25** | **u16 LE** | **预处理输出高度** | | TriggerMode | 21 | u8 | 0=内部, 1=外部 | | TriggerCondition | 37 | u8 | 0=平均, 1=最大 | | TriggerTemperatureThreshold | 28 | i16 LE | 触发阈值 (0.1°C/LSB) | | TriggerBurstCount | 30 | u8 | 连拍帧数 | | TriggerInternalIntervalMs | 31 | u16 LE | 连拍间隔 (ms) | | TriggerDebounceIntervalMs | 35 | u16 LE | 外部触发消抖 (ms) | | TriggerDelayMs | 23 | u16 LE | 触发后延迟 (ms) | | TriggerRoiX/Y/W/H | 33-40 | u16 LE ×4 | 内部触发检测 ROI | | NGioDelay | 41 | u16 LE | NG 脉冲宽度 (ms) | > **重要**:`Width/Height` 与 `TargetWidth/TargetHeight` 是两组不同的字段!前者仅做标识,后者直接控制帧大小。 ### 11.3 缓冲区容量约束 ``` MAX_TCP_PAYLOAD_SIZE = 9216 字节 HeadOffset = 64 字节(协议头预留) 可用像素空间 = 9216 - 64 = 9152 字节 最大像素数 = 9152 / 2 = 4576 像素 推荐安全目标尺寸: 64 × 64 = 4096 像素 = 8192 字节 ✓ 67 × 67 = 4489 像素 = 8978 字节 ✓ 68 × 68 = 4624 像素 = 9248 字节 ✗ (触发降尺寸) ``` ### 11.4 自动降尺寸保护 TargetWidth × TargetHeight × 2 超过可用缓冲区时,自动等比减半: ``` 示例:服务器设 185×70 → 185×70×2=25900 > 9152 → 减半 → 93×35 日志:PP: target clamped 185x70 -> 93x35 (buf=10176) ``` ### 11.5 配置传递链 ``` 服务器 TCP 下发 TLV → qdx_tcp_logic.c: parse_and_dispatch_tlv() → 反序列化 → cached_cfg{2d,1d,common} → OnConfigUpdate() 回调 → Preprocess_Settings_Change() 互斥锁更新 → 下次帧处理使用新配置 ``` --- ## 12. RTOS 任务架构 | 任务名 | 优先级 | 栈 (words) | 条件 | 功能 | |--------|--------|-----------|------|------| | `wchnet` | 6 (最高) | 512 | 始终创建 | WCHNET 协议栈轮询 (5ms) | | `business` | 5 | 512 | 始终创建 | DVP + 触发状态机 + 发送 | | `testpat` | 4 | 256 | `TEST_PATTERN_MODE=1` | 测试图案生成 (~10 FPS) | | `hb` | 3 (最低) | 256 | 始终创建 | 心跳调试打印 (2s) | | TcpLogic 内部 | - | - | 始终创建 | 管理线程 (连接/心跳/重连) | --- ## 13. GPIO 引脚分配 | GPIO | 功能 | 方向 | 配置 | 说明 | |------|------|------|------|------| | PA15 | 外部触发输入 | 输入 | 下拉 + EXTI15 上升沿 | 2D/1D 共用(互斥) | | PA8 | NG 输出 | 推挽输出 | 低速 2MHz | 检测 NG 时脉冲拉高 | | PA4-PA6, PA9-PA10, PB3, PB8-PB9 | DVP 数据线 | 输入 | 浮空 | 仅正常模式使用 | | PC8, PC9, PC11 | DVP HSYNC/VSYNC/PCLK | 输入 | - | 仅正常模式使用 | | PA2, PA3 | **已占用** | - | - | USART2,不可用 | --- ## 14. 功能完整性对照表 ### 协议规范 vs MCU 实现 | 协议功能 | 实现状态 | 备注 | |---------|---------|------| | 握手 (Handshake) | ✅ | UUID + HW/FW 版本 | | 心跳 (Heartbeat) | ✅ | 2s 间隔,6s 超时断连 | | 设备 ID 分配 (DevID Assign) | ✅ | 触发自动重连 | | Config Common/2D/1D 下发 | ✅ | 解析+缓存+回调 | | ACK 响应 | ✅ | 发送+接收 | | TEMP_REQ 截图 | ✅ | 2D 预处理 / 1D 空间采样 | | Detection Result | ✅ | NG → PA8 脉冲 | | 2D 外部触发 | ✅ | GPIO → 消抖 → 延迟 → 连拍 | | 2D 内部触发 | ✅ | ROI Max/Avg → 延迟 → 连拍 | | 1D 外部触发 | ✅ | GPIO → 消抖 → 采集 → 切片 | | 1D 内部触发 | ✅ | 3 样本预环形 → 采集 → 切片 | | 温度矩阵分片发送 | ✅ | 每片 ≤1400 字节 | | TCP KeepAlive | ✅ | 20s/15s/9次 | | CRC16-MODBUS 校验 | ✅ | 每帧校验 | | IsLive 实时流 | ❌ | MCU 资源不足,触发场景不需要 | | Training 训练模式 | ❌ | 服务器端完成 | | SyncTime 时间同步 | ❌ | 协议已定义 (0x03),未解析 | | StatusEvent 状态上报 | ❌ | 服务器通过心跳判断在线 | | Alarm GPIO | ❌ | 结构体有字段,硬件未接线 | | 1D StartPointsToRemove / ReferenceLength / TimerCLimit | ❌ | 已解析到结构体,业务逻辑未使用 | --- ## 15. 已知注意事项 ### 15.1 温度单位 系统统一使用 **0.1°C/LSB**: - 温度值 350 = 35.0°C - 温度值 900 = 90.0°C - `TEMP_RAW(deg_c) = (uint16_t)(deg_c * 10)` ### 15.2 Config2D 字段区分 - **Width / Height**:设备分辨率标识(如 256×192),不影响 MCU 预处理 - **TargetWidth / TargetHeight**:预处理实际输出尺寸,**必须正确设置** ### 15.3 正常模式默认目标尺寸 `TargetWidth=1, TargetHeight=1`(最小默认),必须等服务器下发 Config2D 后才能正常输出。 ### 15.4 IP 与端口硬编码 网络参数为编译期常量,更改需修改源码并重新编译: - MCU IP:`main.c` → `IPAddr[]` - 服务器 IP:`qdx_tcp_logic.c` → `SERVER_IP` - 端口号:`qdx_tcp_logic.c` → `CONTROL_PORT` / `DATA_PORT` ### 15.5 printf 限制 使用 newlib-nano,仅支持 `%d, %x, %s` 格式。所有 `uint32_t` 必须 `(int)` 强转后打印,否则 HardFault。不支持 `%u, %lu, %f`。 ### 15.6 双缓冲发送 系统使用 A/B 交替 `TcpTxBuffer_t`,避免发送过程中缓冲区被覆盖。`use_buffer_A` 标志在每次发送后翻转。 ### 15.7 2D/1D 互斥 主循环中 `Config2D.Enabled` 优先级高于 `Config1D.Enabled`。若两者同时 Enabled=1,仅 2D 管线运行。