From e885c1b7eac6bed25bf83e4124b798755b99c6ea Mon Sep 17 00:00:00 2001 From: zhoujie <929834232@qq.com> Date: Sun, 15 Mar 2026 16:47:32 +0800 Subject: [PATCH] 106 --- README.md | 256 ++++++++++++ Todo.md | 4 + doc/TCPClient测试指南.md | 34 +- doc/下位机协议实现完备性分析.md | 14 +- doc/模式配置与功能说明.md | 20 +- openspec/config.yaml | 21 + 模式配置与功能说明.md | 669 -------------------------------- 7 files changed, 315 insertions(+), 703 deletions(-) create mode 100644 openspec/config.yaml delete mode 100644 模式配置与功能说明.md diff --git a/README.md b/README.md index e69de29..5557aed 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,256 @@ +# CH32V307 TCPClient — 红外热像采集端固件(MCU 端) + +> **MCU**: CH32V307WCU6 (RISC-V, 144 MHz) +> **协议版本**: QDX v2.0 / 采集端通信协议规范 v2.1.3 +> **固件版本**: v2.0 自主触发架构 +> **最近更新**: 2026-03 + +--- + +## 目录 + +1. [项目简介](#1-项目简介) +2. [硬件配置](#2-硬件配置) +3. [软件架构](#3-软件架构) +4. [目录结构](#4-目录结构) +5. [快速上手](#5-快速上手) +6. [编译期配置](#6-编译期配置) +7. [网络配置](#7-网络配置) +8. [运行时行为](#8-运行时行为) +9. [GPIO 引脚分配](#9-gpio-引脚分配) +10. [已知问题 / TODO](#10-已知问题--todo) +11. [参考文档](#11-参考文档) + +--- + +## 1. 项目简介 + +本项目是基于 **CH32V307WCU6** 的红外热像**采集端**(MCU 端)嵌入式固件,实现以下核心功能: + +- 驱动 **Mini212G2** 红外热像仪(256×192,Y16 原始温度格式)采集帧数据 +- 运行 **FreeRTOS** 实时操作系统,多任务并行处理 +- 通过 **WCHNET 1000M 以太网** 与**上位机**(ConfigServer,运行于 PC/服务器)进行 TCP 通信 +- 使用 **QDX TLV 二进制协议**(帧头 `0x55AA`,协议版本 v2.0)向上位机上报数据 +- 支持 **2D 触发连拍**(内部温度触发 / 外部 GPIO 触发)与 **1D 时序采集** +- 支持上位机运行时下发配置,MCU(采集端)**自主驱动**全部业务逻辑 + +--- + +## 2. 硬件配置 + +| 资源 | 规格 | +|------|------| +| MCU | CH32V307WCU6,RISC-V,144 MHz | +| FLASH | 128 KB | +| SRAM | 192 KB(Option Bytes [7:5]=110) | +| 传感器 | Mini212G2,256×192,Y16 原始温度 | +| 网络接口 | 1000M 以太网,RGMII(WCHNET) | +| 串口调试 | USART3,921600 baud(PB10 TX / PB11 RX) | +| 外部触发输入 | PA15 / EXTI15,上升沿 | +| NG 输出 | PA8,推挽,高有效,脉冲宽度可配 | +| DVP 接口 | 传感器图像数据采集(DMA 行搬运) | + +--- + +## 3. 软件架构 + +``` +┌──────────────────────────────────────────────────────┐ +│ FreeRTOS 任务层 │ +│ task_net_entry — WCHNET 轮询 / TCP 收发 │ +│ task_business_entry — 业务主循环(2D/1D 状态机) │ +│ task_test_pattern — 仅测试模式:模拟帧生成 │ +└─────────────────┬────────────────────────────────────┘ + │ +┌─────────────────▼────────────────────────────────────┐ +│ 中间件 / 协议层 │ +│ QDX 协议栈 — TLV 编解码、TCP 逻辑封装 │ +│ qdx_preprocess — 滑窗 ROI + 温度统计 + 降尺寸 │ +└─────────────────┬────────────────────────────────────┘ + │ +┌─────────────────▼────────────────────────────────────┐ +│ 驱动 / HAL 层 │ +│ eth_driver — WCHNET 以太网驱动 │ +│ dvp.c — DVP + DMA 行采集 │ +│ mini212g2.c — 传感器控制(当前通过 USB 预配置) │ +│ debug.c — USART1 调试输出 │ +└──────────────────────────────────────────────────────┘ +``` + +### RTOS 资源 + +| 组件 | 说明 | +|------|------| +| FreeRTOS v202112.00 | Heap_4,Heap 大小 16 KB | +| WCHNET | 万瑞 TCP/IP 协议栈,2 个 TCP socket | +| QDX 协议栈 | 自定义 TLV 二进制协议,双缓冲零拷贝 TX | +| 预处理模块 | 滑窗 ROI 搜索 + 最大/平均温度统计 + 自动降尺寸 | + +--- + +## 4. 目录结构 + +``` +Project_Ch32v307/ +├── User/ # 应用层入口 +│ ├── main.c # 初始化、FreeRTOS 任务创建、业务状态机 +│ ├── net_config.h # WCHNET socket / MAC 参数 +│ ├── FreeRTOSConfig.h +│ └── ch32v30x_conf.h +├── Middle/ +│ └── QDXnetworkStack/ # QDX TLV 协议栈(端口适配 + 预处理 + TCP 逻辑) +├── Debug/ +│ ├── dvp.c/h # DVP + DMA 传感器图像采集 +│ └── mini212g2.c/h # Mini212G2 传感器驱动 +├── NetLib/ # WCHNET 以太网驱动(多 PHY 版本) +├── FreeRTOS/ # FreeRTOS 内核 + portable + MemMang +├── Peripheral/ # CH32V30x 外设库 +├── Core/ # RISC-V 内核支持 +├── Startup/ # 启动汇编文件 +├── Ld/ # 链接脚本 +└── Doc/ # 协议规范、用户手册等文档 +``` + +--- + +## 5. 快速上手 + +### 5.1 工具链要求 + +- **IDE**: MounRiver Studio(推荐)或 GCC RISC-V 工具链 +- **调试器**: WCH-Link + +### 5.2 编译步骤 + +1. 用 MounRiver Studio 打开 `TCPClient1.wvproj` +2. 根据实际环境修改 `User/net_config.h` 中的 IP 地址(见[网络配置](#7-网络配置)) +3. 按需设置 `User/main.c` 顶部的 `TEST_PATTERN_MODE` 宏 +4. 编译并烧录到目标板 + +### 5.3 两种运行模式 + +| 项目 | 测试模式 (`TEST_PATTERN_MODE=1`) | 正常模式 (`TEST_PATTERN_MODE=0`) | +|------|------|------| +| 数据来源 | 软件生成模拟热图 (~10 FPS) | Mini212G2 传感器 DVP/DMA 采集 | +| 硬件依赖 | 仅需网口 | 需连接 Mini212G2 + DVP 线缆 | +| 默认配置 | 自动注入(2D Enabled=1,内部触发,80°C 阈值) | 等待服务器下发,默认不使能 | +| 适用场景 | 协议联调、网络测试 | 实际生产部署 | + +--- + +## 6. 编译期配置 + +所有宏定义位于 `User/main.c` 文件头部。 + +### 主模式开关 + +| 宏名 | 默认值 | 说明 | +|------|--------|------| +| `TEST_PATTERN_MODE` | `0` | **唯一编译开关**:`1`=测试模式,`0`=正常模式 | + +### 业务常量 + +| 宏名 | 默认值 | 说明 | +|------|--------|------| +| `DEFAULT_BURST_COUNT` | `3` | 服务器未配置时的默认连拍帧数 | +| `DEFAULT_BURST_INTERVAL_MS` | `200` | 默认连拍间隔(ms) | +| `MAX_TCP_PAYLOAD_SIZE` | `9216` | TCP 发送缓冲区大小(字节) | +| `NG_PULSE_MS` | `200` | NG 脉冲默认宽度(服务器可通过 `NGioDelay` 覆盖) | +| `MAX_1D_POINTS` | `512` | 1D 采集缓冲最大样本数 | + +### 传感器尺寸(`Debug/dvp.h`) + +| 宏名 | 值 | 说明 | +|------|-----|------| +| `SENSOR_WIDTH` | `256` | 传感器像素宽度 | +| `SENSOR_HEIGHT` | `192` | 传感器像素高度 | +| `BYTES_PER_LINE` | `512` | 每行字节数(256×2) | + +--- + +## 7. 网络配置 + +网络参数在 `User/net_config.h` 和 `User/main.c` 中配置: + +| 参数 | 说明 | +|------|------| +| 本机 IP | 静态 IP(在 `main.c` 初始化结构体中设置) | +| 控制通道 | TCP,主动连接上位机(ConfigServer)控制端口,接收命令与配置 | +| 数据通道 | TCP,主动连接上位机(ConfigServer)数据端口,上报帧数据 | +| TCP socket 数 | 2(`WCHNET_NUM_TCP=2`) | +| TCP MSS | 1460 字节 | +| KeepAlive | 开启,20 s 空闲 / 15 s 探测 / 9 次 | + +通信协议详见 [Doc/采集端通信协议规范.md](Doc/采集端通信协议规范.md)。 + +--- + +## 8. 运行时行为 + +系统行为完全由上位机(ConfigServer)运行时配置驱动,MCU 为采集端,主动连接上位机: + +``` +上位机下发 Config2D (Enabled=1) → MCU(采集端)自主执行 2D 触发 / 连拍 / 上报 +上位机下发 Config1D (Enabled=1) → MCU(采集端)自主执行 1D 时序采集 / 上报 +两者互斥:Config2D.Enabled 优先级高于 Config1D.Enabled +``` + +### 2D 触发状态机 + +``` +IDLE → 检测触发条件(内部温度阈值 or 外部 GPIO) + → 防抖(DebounceMs) + → 延迟(DelayMs) + → 连拍 N 帧(BurstCount × BurstIntervalMs) + → 每帧:预处理 → TCP 上报 → NG 输出(若 NG 条件满足) + → IDLE +``` + +### 1D 采集状态机 + +``` +IDLE → 触发(外部 GPIO 高电平计时 or 内部连续 3 帧超阈值) + → 防抖(HighTimerLimit) + → 逐帧采样温度点(中心行最大值) + → 阈值停止 + → 裁切 [LSizeStart, -RSizeStart] + → TCP 上报 + → IDLE +``` + +### TEMP_REQ 辅助通道 + +服务器可随时发送 `TEMP_REQ` 命令,MCU 立即采集当前帧并上报(`frameType=0x02`),不影响主状态机。 + +--- + +## 9. GPIO 引脚分配 + +| 引脚 | 方向 | 功能 | +|------|------|------| +| PA15 | 输入 | 外部触发(2D/1D,上升沿,EXTI15) | +| PA8 | 输出 | NG 信号(推挽,高有效,脉冲宽度可配) | +| PA2/PA3 | — | USART2(已被 DVP 占用,传感器通过 USB 预配置,**不可复用**) | +| USART1 | 输出 | 921600 baud 调试串口 | + +--- + +## 10. 已知问题 / TODO + +- [ ] 需与采集端联调具体业务逻辑 +- [ ] 上位机接收上报温度数据后出现卡死/异常,待排查 + +--- + +## 11. 参考文档 + +| 文档 | 说明 | +|------|------| +| [Doc/采集端通信协议规范.md](Doc/采集端通信协议规范.md) | QDX TLV 协议完整规范(v2.1.3) | +| [Doc/函数调用指南.md](Doc/函数调用指南.md) | 主要 API 调用说明 | +| [Doc/模式配置与功能说明.md](Doc/模式配置与功能说明.md) | 编译期/运行时配置详细说明 | +| [Doc/下位机协议实现完备性分析.md](Doc/下位机协议实现完备性分析.md) | 协议实现覆盖度分析 | +| [Doc/CH32二维运行结构概览.md](Doc/CH32二维运行结构概览.md) | 系统状态机全景图 | +| [Doc/TCPClient测试指南.md](Doc/TCPClient测试指南.md) | 测试模式使用说明 | +| [Doc/Mini212G2用户手册.md](Doc/Mini212G2系列用户手册.md) | 传感器硬件手册 | +| [Doc/Mini212G2串口通讯协议.md](Doc/Mini212G2串口通讯协议.md) | 传感器通信协议 | diff --git a/Todo.md b/Todo.md index 8f38507..5e060ba 100644 --- a/Todo.md +++ b/Todo.md @@ -1,3 +1,7 @@ ## 1.需要和采集端联调具体的逻辑功能 ## 2.采集的在接受上报的温度数据后会卡死异常 + 采集端与mcu正常通信时,发送2d数据上报后,采集端会卡死,过一段时间后能显示2d图像,但是采集端再发命令就发不出去了。 + + 点击采集端里面的重启功能之后又能重复上述步骤。 + diff --git a/doc/TCPClient测试指南.md b/doc/TCPClient测试指南.md index bb07820..337e1b2 100644 --- a/doc/TCPClient测试指南.md +++ b/doc/TCPClient测试指南.md @@ -10,16 +10,16 @@ | 红外传感器 | 256×192 DVP 接口热成像模组 | | 网络 | RJ45 网线,连接到与上位机同一局域网的交换机/路由器 | | NG 输出 | PA8 引脚可接 LED 或示波器观察脉冲 | -| 串口 | USART1 (115200 baud),连接 USB-TTL 调试串口 | +| 串口 | USART3 (921600 baud,PB10 TX / PB11 RX),连接 USB-TTL 调试串口 | ### 1.2 网络参数(代码默认值) | 参数 | 值 | 对应文件 | |------|-----|----------| -| MCU IP | `192.168.1.10` | `main.c` → `IPAddr` | -| 网关 | `192.168.1.1` | `main.c` → `GWIPAddr` | +| MCU IP | `192.168.7.10` | `main.c` → `IPAddr` | +| 网关 | `192.168.7.1` | `main.c` → `GWIPAddr` | | 子网掩码 | `255.255.255.0` | `main.c` → `IPMask` | -| 上位机 IP | `192.168.1.50` | `main.c` → `DESIP`,`qdx_tcp_logic.c` → `SERVER_IP` | +| 上位机 IP | `192.168.7.50` | `main.c` → `DESIP`,`qdx_tcp_logic.c` → `SERVER_IP` | | 控制流端口 | `5511` | `qdx_tcp_logic.c` → `CONTROL_PORT` | | 数据流端口 | `5512` | `qdx_tcp_logic.c` → `DATA_PORT` | @@ -27,7 +27,7 @@ ### 1.3 上位机软件 -将上位机 IP 设为 `192.168.1.50`,确保防火墙放行端口 5511 和 5512。 +将上位机 IP 设为 `192.168.7.50`,确保防火墙放行端口 5511 和 5512。 **方式 A — PC Demo 程序**(推荐先用此方式验证基本通信): @@ -72,7 +72,7 @@ api_demo.exe # 运行后作为 TCP 服务端监听 5511/5512 **目的**:确认 MCU 正常启动、FreeRTOS 调度器运行、心跳任务工作。 **操作**: -1. 连接串口终端(115200, 8N1) +1. 连接串口终端(921600, 8N1) 2. 上电或复位 **预期串口输出**: @@ -103,9 +103,9 @@ WCHNET_LibInit Success | 现象 | 可能原因 | 解决方案 | |------|----------|----------| -| 无任何输出 | 串口未连接/波特率错误 | 检查 USART1 TX 引脚连线,确认 115200 | +| 无任何输出 | 串口未连接/波特率错误 | 检查 USART3 TX 引脚 (PB10) 连线,确认 921600 | | 反复重启打印 `Flash/SRAM config changed` | Option Bytes 写入但未生效 | 先用 WCH-ISP 工具手动设置 Option Bytes | -| `err at line XXX of file "../FreeRTOS/tasks.c"` | Heap 不足 | 检查 `configTOTAL_HEAP_SIZE`(当前 12KB) | +| `err at line XXX of file "../FreeRTOS/tasks.c"` | Heap 不足 | 检查 `configTOTAL_HEAP_SIZE`(当前 16 KB) | | 卡死无心跳 | HardFault / startup 配置错 | 检查 mstatus=0x7800、CSR 0x804=0x1f | --- @@ -128,14 +128,14 @@ PHY Link Success | # | 检查点 | 通过条件 | |---|--------|----------| | 1 | PHY 链路 | 插入网线后出现 `PHY Link Success` | -| 2 | 上位机 ping | 上位机执行 `ping 192.168.1.10` 能通 | +| 2 | 上位机 ping | 上位机执行 `ping 192.168.7.10` 能通 | **故障排查**: | 现象 | 可能原因 | 解决方案 | |------|----------|----------| | 无 PHY Link Success | 网线/PHY 硬件问题 | 检查 RJ45 座子焊接、网线 | -| ping 不通 | IP 冲突或子网不同 | 确认上位机 IP 在 192.168.1.x 段 | +| ping 不通 | IP 冲突或子网不同 | 确认上位机 IP 在 192.168.7.x 段 | --- @@ -258,7 +258,7 @@ TCP Connected, socket 1 | 长时间运行 | 持续运行 24 小时 | 心跳持续、无 assert、无内存泄漏 | | 反复断线重连 | 每 30 秒拔插网线 | 每次重连后双通道恢复 | | 高频图像发送 | 传感器满帧率连续采集 | 无丢帧、无栈溢出 | -| 上位机先断后连 | MCU 先开机,30s 后再启动上位机 | MCU 自动重连成功 | +| 上位机先断后连 | MCU 先开机,30 s 后再启动上位机 | MCU 自动重连成功 | --- @@ -266,7 +266,7 @@ TCP Connected, socket 1 | 参数 | 当前值 | 文件 | |------|--------|------| -| `configTOTAL_HEAP_SIZE` | 12 KB | `FreeRTOSConfig.h` | +| `configTOTAL_HEAP_SIZE` | 16 KB | `FreeRTOSConfig.h` | | `configTICK_RATE_HZ` | 500 | `FreeRTOSConfig.h` | | `configMINIMAL_STACK_SIZE` | 256 words | `FreeRTOSConfig.h` | | task_wchnet 栈 | 512 words (2 KB) | `main.c` | @@ -283,18 +283,18 @@ TCP Connected, socket 1 ## 6. 常见问题 FAQ **Q: 心跳正常但 TCP 连不上?** -> 检查:① 上位机 IP 是否为 `192.168.1.50`;② 防火墙是否放行 5511/5512;③ `qdx_tcp_logic.c` 中 `SERVER_IP` 是否与 `main.c` 中 `DESIP` 一致。 +> 检查:① 上位机 IP 是否为 `192.168.7.50`;② 防火墙是否放行 5511/5512;③ `qdx_tcp_logic.c` 中 `SERVER_IP` 是否与 `main.c` 中 `DESIP` 一致。 **Q: 编译报 RAM overflow?** -> 检查 `.bss` 总量。FrameBuffer (96KB) + ETH buffers (~32KB) + ucHeap (12KB) + 应用缓冲区 (~47KB) ≈ 187KB。如果增大了某个缓冲区导致超 192KB,需要相应缩减其他部分。 +> 检查 `.bss` 总量。FrameBuffer (96KB) + ETH buffers (~32KB) + ucHeap (16KB) + 应用缓冲区 (~47KB) ≈ 191KB。如果增大了某个缓冲区导致超 192KB,需要相应缩减其他部分。 **Q: 运行时 assert (`err at line XXX`)?** -> 通常是 Heap 不足导致 `pvPortMalloc` 失败。确认 `configTOTAL_HEAP_SIZE` 为 12KB,任务栈未超预算。 +> 通常是 Heap 不足导致 `pvPortMalloc` 失败。确认 `configTOTAL_HEAP_SIZE` 为 16KB,任务栈未超预算。 **Q: 如何启用栈溢出检测进行调试?** > 在 `FreeRTOSConfig.h` 中设置 `configCHECK_FOR_STACK_OVERFLOW` 为 `2`,并实现 `vApplicationStackOverflowHook()` 函数打印任务名。**仅用于调试,发布时关闭**。 **Q: 如何调整上位机 IP?** > 同时修改两处(保持一致): -> 1. `main.c` 第 107 行:`DESIP[4] = {x, x, x, x};` -> 2. `qdx_tcp_logic.c` 第 58 行:`SERVER_IP = "x.x.x.x";` +> 1. `main.c` 中 `DESIP[4] = {x, x, x, x};` +> 2. `qdx_tcp_logic.c` 中 `SERVER_IP = "x.x.x.x";` diff --git a/doc/下位机协议实现完备性分析.md b/doc/下位机协议实现完备性分析.md index b454419..3effe02 100644 --- a/doc/下位机协议实现完备性分析.md +++ b/doc/下位机协议实现完备性分析.md @@ -1,6 +1,6 @@ # 下位机协议实现完备性分析 -> **分析日期**: 2026-03-14 +> **分析日期**: 2026-03-15 > **对照文档**: 采集端通信协议规范 v2.1.3 (2026-02-07) > **分析对象**: prj/TCPClient 工程全部源码 @@ -56,12 +56,12 @@ | 6 | CRC16 校验 | ✅ 已实现 | 收发双向 CRC16-MODBUS 校验 | | 7 | 自动重连 | ✅ 已实现 | 检测断线后 3s 重连双通道 | | 8 | 阈值蒙版输出 | ⚠️ 部分 | 滑窗搜索时低温 → 90 替换,但规范要求**输出数据**中低于 MaskThreshold → 替换为 0 | -| 9 | 触发延迟 (DelayMs) | ❌ 未实现 | 字段已解析但触发后无延迟等待逻辑 | -| 10 | 外部 GPIO 触发 | ❌ 未实现 | 无 EXTI 中断配置、消抖(DebounceIntervalMs)、触发逻辑 | +| 9 | 触发延迟 (DelayMs) | ✅ 已实现 | `burst_delay_pending` + `burst_delay_until_ms` 状态机实现,消抖后延迟再连拍 | +| 10 | 外部 GPIO 触发 | ✅ 已实现 | PA15/EXTI15 上升沿 EXTI 中断,`EXTI15_10_IRQHandler` + `burst_debounce_pending` 消抖 + `TriggerDelayMs` 延迟 | | 11 | Alarm GPIO | ❌ 未实现 | AlarmGpioLine/AlarmHoldMs 字段已解析但无 GPIO 驱动 | -| 12 | 1D 数据采集处理 | ❌ 未实现 | Config1D 可接收但无 1D 环形缓冲区/切片/触发逻辑 | +| 12 | 1D 数据采集处理 | ✅ 已实现 | `S1D_IDLE / S1D_DEBOUNCE / S1D_COLLECTING` 完整状态机,内/外部触发、预环形缓冲、切片、发送 | | 13 | Training 模式 | ❌ 未实现 | 字段可解析但无训练采样功能 | -| 14 | 消抖 (DebounceIntervalMs) | ❌ 未实现 | 依赖外部触发,一并缺失 | +| 14 | 消抖 (DebounceIntervalMs) | ✅ 已实现 | 2D 外部触发消抖与 1D `HighTimerLimit` 均已实现 | --- @@ -71,8 +71,8 @@ |------|:---------:|:-------:|:---------:| | 接收(控制通道) | 7 | 1 | 3 | | 发送(数据通道) | 4 | 0 | 5 | -| 处理逻辑 | 7 | 1 | 6 | -| **合计** | **18** | **2** | **14** | +| 处理逻辑 | 10 | 1 | 3 | +| **合计** | **21** | **2** | **11** | --- diff --git a/doc/模式配置与功能说明.md b/doc/模式配置与功能说明.md index 052a9dd..13eddea 100644 --- a/doc/模式配置与功能说明.md +++ b/doc/模式配置与功能说明.md @@ -36,7 +36,7 @@ | FLASH | 128KB | | SRAM | 192KB (Option Bytes [7:5]=110) | | 传感器 | Mini212G2 (256×192, Y16 原始温度) | -| 网络 | 10M 以太网 (WCHNET) | +| 网络 | 1000M 以太网 RGMII (WCHNET) | | 串口波特率 | 921600 | ### 软件组件 @@ -66,7 +66,7 @@ | **自主触发** | ✅ 立即工作(无需服务器) | ✅ 需服务器下发 Enabled=1 后激活 | | **TEMP_REQ** | ✅ 可用(需对应模式 Enabled=1) | ✅ 可用 | | **NG GPIO** | ✅ PA8 始终初始化 | ✅ PA8 始终初始化 | -| **外部触发 GPIO** | ✅ PA0/EXTI0 始终初始化 | ✅ PA0/EXTI0 始终初始化 | +| **外部触发 GPIO** | ✅ PA15/EXTI15 始终初始化 | ✅ PA15/EXTI15 始终初始化 | --- @@ -78,7 +78,7 @@ | 宏名 | 当前值 | 说明 | |------|--------|------| -| `TEST_PATTERN_MODE` | **1** | **唯一编译开关**:1=测试模式,0=正常模式 | +| `TEST_PATTERN_MODE` | **0** | **唯一编译开关**:1=测试模式,0=正常模式 | ### 3.2 业务常量 @@ -86,7 +86,7 @@ |------|-----|------| | `DEFAULT_BURST_COUNT` | 3 | 服务器未配置时的默认连拍帧数 | | `DEFAULT_BURST_INTERVAL_MS` | 200 | 服务器未配置时的默认连拍间隔 (ms) | -| `MAX_TCP_PAYLOAD_SIZE` | 10240 | TCP 发送缓冲区大小 (字节) | +| `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 空间采样点数 | @@ -545,15 +545,15 @@ task_business_entry (优先级 5) ### 11.3 缓冲区容量约束 ``` -MAX_TCP_PAYLOAD_SIZE = 10240 字节 +MAX_TCP_PAYLOAD_SIZE = 9216 字节 HeadOffset = 64 字节(协议头预留) -可用像素空间 = 10240 - 64 = 10176 字节 -最大像素数 = 10176 / 2 = 5088 像素 +可用像素空间 = 9216 - 64 = 9152 字节 +最大像素数 = 9152 / 2 = 4576 像素 推荐安全目标尺寸: 64 × 64 = 4096 像素 = 8192 字节 ✓ - 71 × 71 = 5041 像素 = 10082 字节 ✓ - 72 × 72 = 5184 像素 = 10368 字节 ✗ (触发降尺寸) + 67 × 67 = 4489 像素 = 8978 字节 ✓ + 68 × 68 = 4624 像素 = 9248 字节 ✗ (触发降尺寸) ``` ### 11.4 自动降尺寸保护 @@ -561,7 +561,7 @@ HeadOffset = 64 字节(协议头预留) TargetWidth × TargetHeight × 2 超过可用缓冲区时,自动等比减半: ``` -示例:服务器设 185×70 → 185×70×2=25900 > 10176 → 减半 → 93×35 +示例:服务器设 185×70 → 185×70×2=25900 > 9152 → 减半 → 93×35 日志:PP: target clamped 185x70 -> 93x35 (buf=10176) ``` diff --git a/openspec/config.yaml b/openspec/config.yaml new file mode 100644 index 0000000..2dc9010 --- /dev/null +++ b/openspec/config.yaml @@ -0,0 +1,21 @@ +schema: spec-driven + +# Project context (optional) +# This is shown to AI when creating artifacts. +# Add your tech stack, conventions, style guides, domain knowledge, etc. +# Example: +context: | + 使用中文 +# Tech stack: TypeScript, React, Node.js +# We use conventional commits +# Domain: e-commerce platform + +# Per-artifact rules (optional) +# Add custom rules for specific artifacts. +# Example: +# rules: +# proposal: +# - Keep proposals under 500 words +# - Always include a "Non-goals" section +# tasks: +# - Break tasks into chunks of max 2 hours diff --git a/模式配置与功能说明.md b/模式配置与功能说明.md deleted file mode 100644 index 052a9dd..0000000 --- a/模式配置与功能说明.md +++ /dev/null @@ -1,669 +0,0 @@ -# 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 原始温度) | -| 网络 | 10M 以太网 (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** | ✅ PA0/EXTI0 始终初始化 | ✅ PA0/EXTI0 始终初始化 | - ---- - -## 3. 编译期常量总表 - -所有宏定义位于 `prj/TCPClient/User/main.c` 文件头部。 - -### 3.1 主模式开关 - -| 宏名 | 当前值 | 说明 | -|------|--------|------| -| `TEST_PATTERN_MODE` | **1** | **唯一编译开关**:1=测试模式,0=正常模式 | - -### 3.2 业务常量 - -| 宏名 | 值 | 说明 | -|------|-----|------| -| `DEFAULT_BURST_COUNT` | 3 | 服务器未配置时的默认连拍帧数 | -| `DEFAULT_BURST_INTERVAL_MS` | 200 | 服务器未配置时的默认连拍间隔 (ms) | -| `MAX_TCP_PAYLOAD_SIZE` | 10240 | 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 = 10240 字节 -HeadOffset = 64 字节(协议头预留) -可用像素空间 = 10240 - 64 = 10176 字节 -最大像素数 = 10176 / 2 = 5088 像素 - -推荐安全目标尺寸: - 64 × 64 = 4096 像素 = 8192 字节 ✓ - 71 × 71 = 5041 像素 = 10082 字节 ✓ - 72 × 72 = 5184 像素 = 10368 字节 ✗ (触发降尺寸) -``` - -### 11.4 自动降尺寸保护 - -TargetWidth × TargetHeight × 2 超过可用缓冲区时,自动等比减半: - -``` -示例:服务器设 185×70 → 185×70×2=25900 > 10176 → 减半 → 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 管线运行。