# CH32V307 TCPClient 模式配置与功能说明

## 目录

1. [系统架构概述](#1-系统架构概述)
2. [运行模式说明](#2-运行模式说明)
3. [宏开关配置总表](#3-宏开关配置总表)
4. [测试模式详解](#4-测试模式详解)
5. [正常模式详解](#5-正常模式详解)
6. [网络与服务器配置](#6-网络与服务器配置)
7. [配置下发流程](#7-配置下发流程)
8. [RTOS 任务架构](#8-rtos-任务架构)
9. [切换模式操作指南](#9-切换模式操作指南)
10. [常见配置场景](#10-常见配置场景)
11. [已知注意事项](#11-已知注意事项)

---

## 1. 系统架构概述

本系统基于 CH32V307WCU6 (RISC-V) 微控制器，运行 FreeRTOS 实时操作系统，通过 WCHNET TCP/IP 协议栈与上位机通信。系统支持两种运行模式：**测试模式**（软件生成模拟热成像数据）和**正常模式**（通过 DVP 接口采集 Mini212G2 红外传感器真实数据）。

### 硬件资源

| 资源 | 配置 |
|------|------|
| 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 二进制通信协议 |
| 预处理模块 | 滑窗 ROI 搜索 + 温度统计 |

---

## 2. 运行模式说明

### 两种模式对比

| 对比项 | 测试模式 (`TEST_PATTERN_MODE=1`) | 正常模式 (`TEST_PATTERN_MODE=0`) |
|--------|------|------|
| **数据来源** | 软件生成模拟热图 (~10 FPS) | Mini212G2 传感器 DVP/DMA 采集 |
| **硬件依赖** | 仅需网口，无需传感器 | 需连接 Mini212G2 + DVP 线缆 |
| **初始化** | 跳过 `Mini212G2_Init()` 和 `DVP_Init()` | 执行传感器初始化 + DVP 配置 |
| **帧生成** | `task_test_pattern_entry` 任务周期填充 | DVP 行中断逐行 DMA 搬运 |
| **心跳显示** | `[HB] N tick=X TEST_MODE frm=Y` | `[HB] N tick=X dvp_frm=Y row_irq=Z` |
| **默认配置** | 自动加载测试配置（64×64, 80°C 阈值） | 等待服务器下发，默认 1×1 |
| **适用场景** | 软件调试、协议验证、无硬件开发 | 生产环境、实际传感器采集 |

---

## 3. 宏开关配置总表

所有宏定义位于 `prj/TCPClient/User/main.c` 文件头部。

### 3.1 主模式开关

| 宏名 | 文件位置 | 当前值 | 说明 |
|------|---------|--------|------|
| `TEST_PATTERN_MODE` | main.c:18 | **1** | **主开关**：1=测试模式，0=正常模式 |

### 3.2 功能子开关

| 宏名 | 当前值 | 控制功能 | 依赖条件 |
|------|--------|---------|---------|
| `TEST_ENABLE_HEARTBEAT` | **1** | 周期心跳调试打印（2秒间隔） | 无 |
| `TEST_ENABLE_TRIGGER` | **0** | 内部触发 + 连拍上传 | 需配合阈值配置 |
| `TEST_ENABLE_NG_GPIO` | **0** | PA8 NG GPIO 脉冲输出 | 需硬件连接 |
| `TEST_ENABLE_TEMP_REQ` | **1** | 服务器按需帧请求响应 | 需服务器发送请求 |
| `TEST_ENABLE_TCP_SEND` | **1** | TCP 数据通道发送 | 需网络连接 |

### 3.3 其他编译期常量

| 宏名 | 值 | 说明 |
|------|-----|------|
| `KEEPALIVE_ENABLE` | 1 | TCP KeepAlive 保持（20s 探测） |
| `DEFAULT_BURST_COUNT` | 3 | 默认连拍帧数 |
| `DEFAULT_BURST_INTERVAL_MS` | 200 | 默认连拍帧间隔 (ms) |
| `MAX_TCP_PAYLOAD_SIZE` | 10240 | TCP 发送缓冲区大小 (字节) |
| `TEST_FPS_DELAY_MS` | 100 | 测试模式帧间隔 (~10 FPS) |
| `TEST_1D_POINTS` | 30 | 1D 模式采样点数 |

### 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_USE_USART3` | 0 | 启用后必须为 1（USART2 不可用） |
| `SENSOR_UART_ENABLE` | **0 (已禁用)** | MCU UART 配置已禁用，传感器通过 USB 预配置 |
| `SENSOR_UART_BAUD` | 115200 | 传感器 UART 波特率（未使用） |

---

## 4. 测试模式详解

### 4.1 启用方式

```c
#define TEST_PATTERN_MODE    1
```

编译烧录即可，**无需连接任何传感器硬件**，仅需以太网连接。

### 4.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 秒循环一次。

### 4.3 默认配置参数

测试模式启动时自动加载以下配置（无需服务器下发即可工作）：

```
TargetWidth  = 64        # 预处理输出宽度
TargetHeight = 64        # 预处理输出高度
TriggerRoiX  = 0         # 触发检测区域起点 X
TriggerRoiY  = 0         # 触发检测区域起点 Y
TriggerRoiW  = 256       # 触发检测区域宽度（全幅）
TriggerRoiH  = 192       # 触发检测区域高度（全幅）
TriggerCondition = 1     # 触发条件：1=最大温度
TriggerTemperatureThreshold = 800   # 80.0°C (0.1°C/LSB)
TriggerBurstCount = 3    # 连拍帧数
TriggerInternalIntervalMs = 200  # 连拍间隔 (ms)
NGioDelay = 200          # NG 脉冲宽度 (ms)
```

> **注意**：如果服务器连接后下发了 Config2D，将覆盖上述默认配置。

### 4.4 测试模式数据流

```
task_test_pattern_entry (优先级 4, 100ms 周期)
    │ 生成 256×192 Y16 测试图案
    │ 写入 FrameBuffer[]
    │ 设置 Frame_Ready_Flag=1
    ▼
task_business_entry (优先级 5)
    ├── 检查 g_temp_req_pending (服务器请求)
    │   ├── is2D=1 → Preprocess_Execute() → 滑窗搜索 → 发送 2D 帧
    │   └── is2D=0 → send_1d_frame_from_raw() → 采样中心行 → 发送 1D 帧
    │
    └── 检查 Frame_Ready_Flag (仅 TRIGGER 启用时)
        └── Preprocess_CheckInternalTrigger2D()
            └── 触发 → 连拍发送
```

### 4.5 启动串口输出示例

```
TCPClient Test
SystemClk:144000000
=== Feature Switches ===
  PATTERN=1  TRIGGER=0  NG_GPIO=0  TEMP_REQ=1  TCP_SEND=1  HB=1
UserByte: c0
=== TEST PATTERN MODE === No sensor/DVP hardware needed
net version:1c
WCHNET_LibInit Success
Test default config loaded: trigger thresh=800 ROI=full burst=3
[HB] 0  tick=1010  TEST_MODE  frm=9
[HB] 1  tick=3010  TEST_MODE  frm=29
```

---

## 5. 正常模式详解

### 5.1 启用方式

```c
#define TEST_PATTERN_MODE    0
```

需要：
1. Mini212G2 传感器正确连接 DVP 接口
2. 传感器已通过 USB 或 UART 预配置为 CMOS/DVP Y16 输出

### 5.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 调试。

### 5.3 传感器配置选项

修改 `mini212g2.h`：

```c
// 当前状态：MCU UART 配置已禁用（#if 0）
// 模组已通过 USB 预配置，无需 MCU 配置

// 如需重新启用 MCU UART 配置，将 mini212g2.h 中的 #if 0 改为 #if 1
// 仅可使用 USART3 (PB10/PB11)，USART2 引脚已被占用
// ⚠ 启用后 printf 串口不可用，需通过 JTAG 调试
```

### 5.4 正常模式数据流

```
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
    ▼
    ├── 检查 g_temp_req_pending (服务器请求)
    │   ├── is2D=1 → Preprocess_Execute() → 发送
    │   └── is2D=0 → 1D 采样 → 发送
    │
    └── 检查 Frame_Ready_Flag (TRIGGER 启用时)
        └── Preprocess_CheckInternalTrigger2D()
```

### 5.5 正常模式注意事项

- **无默认预处理参数**：正常模式不加载测试默认配置，`Preprocess_Init()` 仅设置 `TargetWidth=1, TargetHeight=1`。必须等服务器下发 Config2D 后才能获取正确的目标尺寸。
- **传感器初始化检查**：可通过 JTAG 查看 `sensor_init_ok` / `sensor_init_fail` 变量确认初始化结果。
- **帧率取决于传感器**：Mini212G2 在 DVP 模式下的帧率由传感器内部配置决定，不通过软件控制。

### 5.6 启动串口输出示例（预期）

```
TCPClient Test
SystemClk:144000000
=== Feature Switches ===
  PATTERN=0  TRIGGER=0  NG_GPIO=0  TEMP_REQ=1  TCP_SEND=1  HB=1
UserByte: c0
[DVP] Init done CR0=0x2C CR1=0x04 ROW=1 COL=512
[DVP] DMA_BUF0=0x200XXXXX DMA_BUF1=0x200XXXXX
net version:1c
WCHNET_LibInit Success
[HB] 0  tick=1010  dvp_frm=0  row_irq=0
```

---

## 6. 网络与服务器配置

### 6.1 MCU 网络参数

定义位置：`main.c`

| 参数 | 值 | 说明 |
|------|-----|------|
| IP 地址 | 192.168.7.10 | MCU 静态 IP |
| 网关 | 192.168.7.1 | 默认网关 |
| 子网掩码 | 255.255.255.0 | C 类子网 |
| MAC 地址 | 由芯片自动获取 | 硬件 MAC |

### 6.2 服务器连接参数

定义位置：`qdx_tcp_logic.c`

| 参数 | 值 | 说明 |
|------|-----|------|
| `SERVER_IP` | "192.168.7.50" | 服务器 IP |
| `CONTROL_PORT` | 5511 | 控制通道端口 |
| `DATA_PORT` | 5512 | 数据通道端口 |

> **修改方法**：直接编辑 `qdx_tcp_logic.c` 中的常量值，重新编译。

### 6.3 TCP KeepAlive

```c
#define KEEPALIVE_ENABLE    1   // main.c
// 探测配置: 20s 空闲后每 15s 探测一次，最多 9 次
```

---

## 7. 配置下发流程

### 7.1 TLV 配置类型

| TLV Type | 名称 | 说明 |
|----------|------|------|
| 0x20 | TYPE_CONFIG_COMMON | 通用配置（模式、严格标记等） |
| 0x22 | TYPE_CONFIG_2D | 2D 配置（目标尺寸、触发、连拍等） |
| 0x23 | TYPE_CONFIG_1D | 1D 配置 |

### 7.2 Config2D 关键字段

| 字段 | 偏移 | 类型 | 说明 |
|------|------|------|------|
| Width | 4 | u16 LE | 设备/传感器分辨率宽度（仅标记，不影响预处理） |
| Height | 6 | u16 LE | 设备/传感器分辨率高度（仅标记，不影响预处理） |
| **TargetWidth** | **23** | **u16 LE** | **预处理输出宽度（直接控制帧大小）** |
| **TargetHeight** | **25** | **u16 LE** | **预处理输出高度（直接控制帧大小）** |
| Fps | 8 | u16 LE | 帧率 |
| TriggerCondition | 27 | u8 | 0=平均, 1=最大 |
| TriggerTemperatureThreshold | 28 | u16 LE | 触发温度阈值 (0.1°C/LSB) |
| TriggerBurstCount | 30 | u8 | 连拍帧数 |
| TriggerInternalIntervalMs | 31 | u16 LE | 连拍帧间隔 (ms) |
| TriggerRoiX/Y/W/H | 33-40 | u16 LE ×4 | 触发检测 ROI 区域 |

> **重要**：Width/Height 与 TargetWidth/TargetHeight 是两组不同的字段！
> - `Width/Height`：设备分辨率标记（偏移 4-7），**不影响预处理**
> - `TargetWidth/TargetHeight`：预处理实际输出尺寸（偏移 23-26），**直接决定帧数据大小**

### 7.3 缓冲区容量约束

```
MAX_TCP_PAYLOAD_SIZE = 10240 字节
HeadOffset           = 64 字节（协议头预留）
可用像素空间         = 10240 - 64 = 10176 字节
最大像素数           = 10176 / 2 = 5088 像素

推荐安全目标尺寸:
  64 × 64 = 4096 像素 = 8192 字节  ✓ (< 10176)
  71 × 71 = 5041 像素 = 10082 字节 ✓ (< 10176)
  72 × 72 = 5184 像素 = 10368 字节 ✗ (> 10176，会触发降尺寸)
```

### 7.4 自动降尺寸保护

当服务器下发的 TargetWidth × TargetHeight × 2 超过可用缓冲区时，MCU 会自动等比减半目标尺寸直到适合：

```
示例：服务器设 TargetWidth=185, TargetHeight=70
  185 × 70 × 2 = 25,900 > 10,176  → 减半
  93 × 35 × 2 = 6,510 < 10,176    → 使用 93×35
日志输出：PP: target clamped 185x70 -> 93x35 (buf=10176)
```

### 7.5 配置传递链

```
服务器 TCP 下发 TLV
    → qdx_tcp_logic.c: parse_and_dispatch_tlv()
    → 反序列化 → cached_cfg2d / cached_cfg1d / cached_common
    → OnConfigUpdate() 回调
    → Preprocess_Settings_Change() 互斥锁更新
    → 下次 Preprocess_Execute() 使用新配置
```

---

## 8. RTOS 任务架构

| 任务名 | 优先级 | 栈 (words) | 条件 | 功能 |
|--------|--------|-----------|------|------|
| `wchnet` | 6 (最高) | 512 | 始终创建 | WCHNET 协议栈轮询 |
| `business` | 5 | 512 | `TEST_ENABLE_TCP_SEND=1` | DVP/预处理/发送主循环 |
| `testpat` | 4 | 256 | `TEST_PATTERN_MODE=1` | 测试图案生成 |
| `hb` | 3 (最低) | 256 | `TEST_ENABLE_HEARTBEAT=1` | 心跳调试打印 |
| TcpLogic 内部 | - | - | 始终创建 | 管理线程 (连接/心跳) |

> 测试模式创建 4 个任务，正常模式创建 3 个（无 testpat）。

---

## 9. 切换模式操作指南

### 9.1 从测试模式 → 正常模式

1. **修改宏**：打开 `prj/TCPClient/User/main.c`，将：
   ```c
   #define TEST_PATTERN_MODE    1
   ```
   改为：
   ```c
   #define TEST_PATTERN_MODE    0
   ```

2. **检查传感器配置**：当前模组已通过 USB 预配置，`mini212g2.h` 中 UART 配置已用 `#if 0` 关闭，无需修改。如需重新启用，将 `#if 0` 改为 `#if 1`。

3. **检查功能开关**：根据需要启用/禁用各子功能：
   ```c
   #define TEST_ENABLE_TRIGGER      1   // 启用内部触发
   #define TEST_ENABLE_NG_GPIO      1   // 启用 NG 输出（需接 PA8）
   ```

4. **编译烧录**：使用 MRS IDE 编译并烧录。

### 9.2 从正常模式 → 测试模式

1. **修改宏**：`TEST_PATTERN_MODE` 改为 `1`
2. **无需断开传感器**：测试模式跳过所有硬件初始化，传感器接线不影响
3. **编译烧录**

### 9.3 功能开关独立配置

各功能子开关在两种模式下均可独立启用/禁用，无互相依赖：

| 开关组合 | 行为 |
|---------|------|
| PATTERN=1, TRIGGER=1 | 测试模式 + 内部触发连拍（测试热点图案会触发） |
| PATTERN=1, TRIGGER=0, TEMP_REQ=1 | 测试模式 + 服务器按需请求（当前配置） |
| PATTERN=0, TRIGGER=1, TEMP_REQ=1 | 正常模式 + 自动触发 + 服务器请求（完整功能） |
| PATTERN=0, TRIGGER=0, TEMP_REQ=1 | 正常模式 + 仅服务器请求（最简运行） |
| TCP_SEND=0 | 禁用 business 任务，系统仅运行网络协议但不处理/发送帧 |

---

## 10. 常见配置场景

### 场景 A：纯软件协议调试（无硬件）

```c
#define TEST_PATTERN_MODE        1
#define TEST_ENABLE_HEARTBEAT    1
#define TEST_ENABLE_TRIGGER      0
#define TEST_ENABLE_NG_GPIO      0
#define TEST_ENABLE_TEMP_REQ     1
#define TEST_ENABLE_TCP_SEND     1
```

**适用**：验证 TLV 协议、握手流程、Config 下发、帧分片发送等。

### 场景 B：测试内部触发 + 连拍

```c
#define TEST_PATTERN_MODE        1
#define TEST_ENABLE_TRIGGER      1   // ← 打开
#define TEST_ENABLE_NG_GPIO      0
#define TEST_ENABLE_TEMP_REQ     1
#define TEST_ENABLE_TCP_SEND     1
```

**适用**：验证 80°C 触发阈值、3 帧连拍、连拍间隔。热点和棋盘格图案会触发。

### 场景 C：正常模式完整功能

```c
#define TEST_PATTERN_MODE        0
#define TEST_ENABLE_TRIGGER      1
#define TEST_ENABLE_NG_GPIO      1   // ← PA8 接报警
#define TEST_ENABLE_TEMP_REQ     1
#define TEST_ENABLE_TCP_SEND     1
```

**适用**：生产运行，传感器实时采集 + 自动触发 + NG 报警 + 服务器请求。

### 场景 D：正常模式最小功能验证

```c
#define TEST_PATTERN_MODE        0
#define TEST_ENABLE_TRIGGER      0
#define TEST_ENABLE_NG_GPIO      0
#define TEST_ENABLE_TEMP_REQ     1   // 仅响应服务器请求
#define TEST_ENABLE_TCP_SEND     1
```

**适用**：验证传感器数据采集 + 网络发送，无自动触发逻辑干扰。

### 场景 E：网络连接诊断

```c
#define TEST_PATTERN_MODE        1
#define TEST_ENABLE_HEARTBEAT    1
#define TEST_ENABLE_TRIGGER      0
#define TEST_ENABLE_NG_GPIO      0
#define TEST_ENABLE_TEMP_REQ     0   // 关闭帧请求
#define TEST_ENABLE_TCP_SEND     0   // 关闭 business 任务
```

**适用**：仅测试 TCP 连接/断开/重连，不涉及数据帧处理。心跳打印确认系统活跃。

---

## 11. 已知注意事项

### 11.1 温度单位

系统统一使用 **0.1°C/LSB**：
- 温度值 350 = 35.0°C
- 温度值 900 = 90.0°C
- `TEMP_RAW(deg_c) = (uint16_t)(deg_c * 10)`

### 11.2 TriggerTemperatureThreshold 值

温度阈值使用 0.1°C/LSB 单位，与系统所有温度值一致。当前测试默认 `TriggerTemperatureThreshold = 800`（80.0°C），测试热点图案 90.0°C（值 900）可正常触发。

### 11.3 服务器 Config2D 字段区分

- **Width / Height**（偏移 4-7）：设备分辨率标识（如 256×192），不影响 MCU 预处理
- **TargetWidth / TargetHeight**（偏移 23-26）：预处理输出目标尺寸，**必须正确设置**

如果服务器只设了 Width/Height=64×64 而未设 TargetWidth/TargetHeight，MCU 仍会使用超大目标尺寸（或上次缓存值），导致 `PP fail ret=-3` 或触发自动降尺寸。

### 11.4 正常模式默认目标尺寸

正常模式启动时 `TargetWidth=1, TargetHeight=1`（最小默认），必须等服务器下发 Config2D 后才会更新为正确值。测试模式自动加载 64×64。

### 11.5 IP 与端口硬编码

当前网络参数（IP、端口）为编译期常量，更改需修改源码并重新编译：
- MCU IP：`main.c` → `IPAddr[]`
- 服务器 IP：`qdx_tcp_logic.c` → `SERVER_IP`
- 端口号：`qdx_tcp_logic.c` → `CONTROL_PORT` / `DATA_PORT`

### 11.6 printf 限制

使用 newlib-nano，仅支持 `%d, %x, %s` 格式。所有 `uint32_t` 变量必须强制转换 `(int)` 后打印，否则可能 HardFault。不支持 `%u, %lu, %f`。
