Files
STM32F4-Base/docs/产品需求/产品需求设计文档.md
T
wandering1 842d711ed6 refactor(编号): 测试验证层级去号——CI job / 门禁输出 / 命令行旗标换语义名 + ASCII 段名
用户裁定「我不想看到编号」。测试验证层级这一族的整族清退分三道并行:本笔是**代码与 CI 道**
(CI 步骤与门禁输出面),代码注释面另走、文档面由文档道走。

口径(旧 → 语义名 → ASCII 段名,段名只进日志/旗标/job id/文件名):
  L0 静态门禁 static | L0a 钩子解释器预检 preflight | L0b 提交信息门禁 commitmsg
  L0c 体积门禁 size | L0.5 主机侧纯逻辑单测 host-unit | L0.5c 覆盖率 coverage

- scripts/ci_local.py 43 站点:段标题与 [SUMMARY] 标签改 ASCII 段名(static: /
  host-unit:),函数 run_l0/run_l05 → run_static_gates/run_host_unit_tests,
  收尾「已跑:」列表用段名。旗标改 --static-only / --host-unit-only,**旧旗标
  --l0-only / --l05-only 保留为 argparse 别名**(肌肉记忆与既有脚本片段不断档,
  实测 --help 两名列出)。
- .gitea/workflows/ci.yml 42 站点:job id l0-gates → static-gates、
  l05-host-unit-tests → host-unit-tests;步骤名与 step-summary 标题改语义名;
  日志名 l0-pre-commit.log → static-pre-commit.log、l05-<模块>.log →
  host-unit-<模块>.log;::error::/::notice:: 文案同步。yaml.safe_load 核过
  两个 job id 与步骤名。
  host-unit-tests;步骤名与 step-summary 标题改语义名;日志名 l0-pre-commit.log →
  static-pre-commit.log、l05-<模块>.log → host-unit-<模块>.log;::error::/::notice::
  文案同步。yaml.safe_load 核过两个 job id 与步骤名。
- 门禁脚本 18 站点:check_registration(登记簿理由串 7)、check_test_coverage 5、
  README 8、check_generated_fresh 2、ram_baseline 2、check_size_gate 1、
  ci_find_python.ps1 2、ci_runner_bootstrap.ps1 2、.pre-commit-config.yaml 2、
  requirements.txt 1(保持纯 ASCII)。
- skills 7 站点:task-worktree(含 [SUMMARY] 样例两行)、mem-budget、ui-verify、
  task_worktree.py 的实跑标签。
- AGENTS.md 3 站点:CI 段「只跑静态门禁 + 主机侧纯逻辑单测」、自查命令段、
  「2026-10-11 静态门禁全灭」事件名。
- 归档:编号治理历史.md 新增 §10 换算表 + **撞族警示**(同形 L0/L1/L2/L3 还属 UI 设计
  令牌层 / UI 菜单层级 / 采集链 / 链路时延段 / CubeMX 三层 / 硬件位号与 FTP 应答字面量
  等六个族,其中 6 处在字符串字面量里,改了就是改行为——故全程只按行内置换、先判族)。
- docs/产品需求 §7.4 测试分层表:去号 + 顺带修掉上一批**错族替换疤**(该表 L1/L2 行曾被
  采集链层名「语义取数与有效性 / 全周傅氏相量」「保护判据」顶替,现按内容改写为板端测试
  套件 / 主机侧回归两行)。同文档 §1.5 G5 判据行同步。

门禁:ci_local --help 两面旗标并列;py_compile 7 个 .py 全过;yaml 解析通过;
check_ids_new --worktree rc=0;git diff --check 干净;17 个改动文件 FFFD=0、无 CR、
BOM 与原文件一致(含 requirements.txt 纯 ASCII)。本族无机器识别面(单字母+数字是
新增行门禁的自述盲区),口径来自自建逐行扫描器,复扫本族形态归零。
- 交接说明:文档道 teammate 在改 CI 指南时中断,剩余 9 处双写疤与 29 处 CI 标识
  (job id / 日志名 / 汇总行字面量)由 Lead 接手改完,逐处仍走断言式行内置换。
2026-10-28 17:46:52 +08:00

216 KiB
Raw Blame History

STM32F4-Base 产品需求设计文档

文档定位:本项目面向产品的需求基线——把散落在架构、子系统、测试、问题记录各文档中的 "产品做什么 / 做到什么程度 / 依据是什么"收敛成一份可评审、可追溯的需求说明,供甲方、产品、 开发、测试与评审者建立统一认知。 范围:硬件规格、系统架构、功能需求(FR)、接口规范、非功能需求(NFR)、UI 规格、平台约束、 待实现项与路线图、验收判据。 事实来源:本文所有数值与结论均取自仓库内受管事实源(代码、.ioc、.map、网表分析报告与 各模块设计文档),凡与其它文档冲突处,以本文标注的权威来源为准。 版本:v1.9 日期:2026-10-28 状态:现状基线(含已实现项 + 待实现项) 阅读前提:建议先读 docs/README.md(文档索引)与 docs/架构设计/项目架构总览.md(全景架构)。 范围口径:1:1 复刻——本产品是参考产品 CLS100(Scatter_P_HV03.01_SV01.01,OMAP-L138 ARM+DSP 双核 + VxWorks 配电保护测控装置)的逐模块复刻。产品范围 = 参考源码的能力全集, 差异只允许来自物理不可移植项(§2.4.1)。§2.5 以参考工程源码的常量表与模块文件为唯一清单, 给出 20 项能力对照与复刻进度;§9 的缺口一律表述为"复刻进度"而非"不做", 其中 §9.4~§9.13 是逐项明细(每个定值 / 每个点 / 每个模块 / 每条链路的报文差在哪、怎么算做完)。 产品定义的技术细化见 docs/算法/继电保护功能复现规划.md。


1. 文档说明

1.1 目的与范围

本文回答三个问题:

  1. 产品是什么——一块工业级嵌入式 DTU 平台固件,做什么、面向谁、部署在哪;
  2. 产品要做到什么程度——每一项功能/接口/性能/可靠性的可验收要求;
  3. 产品当前做到哪一步——已实现、已验收、待实现的明确边界。

不含:具体代码实现细节(见各模块设计文档)、测试用例步骤(见 docs/测试说明/)、 未闭环事项的逐条跟踪(见 docs/任务规划/README.md)。

1.2 术语与缩写

术语 全称 / 含义
DTU Data Transfer Unit,数据传输单元;本产品的设备角色
MCU STM32F407ZGTx(Cortex-M4,LQFP144)
FTL Flash Translation Layer,闪存转换层(本项目用 dhara 实现)
BBT Bad Block Table,NAND 坏块表(持久化在保留块池)
FatFs 通用 FAT 文件系统模块(Lib/FatFs)
BSD Socket API 本项目在 CH395F 之上封装的 net_socket 接口(socket/bind/listen/accept/recv/send/close)
RemoDispBus 远程显示总线协议(MCU 无屏,UI 以 1bpp 帧经 TCP 推流到远端客户端)
cfg_file 通用配置引擎(INI 段键表,MCU/模拟器双端共享核心)
sys_clock 系统墙钟时间服务(RTC 基准 + tick 推进)
sys_log 定长 64B 记录引擎(运行/自检日志)
IWDG Independent Watchdog,独立看门狗(LSI 时钟源)
就绪屏障 用 CMSIS-RTOS2 Event Flags 表达"子系统就绪"的启动顺序机制
双端 MCU(Keil/ARMCC)与 PC 模拟器(CMake/MSVC)共用同一份 UI/配置源码
@build / @test 仓库约定的构建 / 自动化测试命令别名
语义取数与有效性 / 标定折算 / 全周傅氏相量 / 测频与遥测快照 / 保护判据 采集链路分层:语义取数与有效性(语义取数与有效性)→ 标定折算(标定折算)→ 全周傅氏相量(全周傅氏相量)→ 测频与遥测快照(测频与遥测快照)→ 保护判据(保护判据)
全周傅氏 单频 DFT 取基波相量,窗长 = 整周波(20 点);幅值即基波有效值
相量 {fRe, fIm, fAm, fAmSQ},实部 / 虚部 / 幅值 / 有效值
双区交换 相量(及遥测快照)计算区 / 使用区索引单字节翻转,读者无锁取整份快照
等周波采样 软件测频 + 调采样周期,使窗长恒等于实际周波(严格 20 点/周波)
标定 k / b 通道折算系数(µV/码,Q16 定点)与零点(码值);工程量 = (code + b) × k
QDS IEC 60870-5-104 的品质描述符字节(OV / NT / IV 等位)
SOE Sequence of Event,带时标的事件顺序记录(本产品落 /log/soe.log)
CP56Time2a 104 的 7 字节时标格式(毫秒 / 分 / 时 / 日 / 月 / 年 + 时标标志位)
点表 / IOA 104 上送对象表与信息体地址;本产品点表口径见 §6.8
固有 / 运行 / 保护定值 三类参数:只读身份信息、可整定的运行参数、可整定的保护定值(§5.13)
软压板 软件投退开关(全局软压板 = 保护总投入,可经 104 遥控投退)
遥测死区 遥测变化上送门槛;本产品按"连续 2 个新测量点越限才确认"
CLS100 参考产品(配电保护测控装置,ARM + DSP 双核 / VxWorks),仅作能力对照,非本产品代次

1.3 读者与相关文档

角色 建议读法
甲方 / 产品 §2 产品概述 → §5 功能需求 → §9 待实现项与路线图 → §10 验收判据
开发 全文;深入时按 §11 指向各模块设计文档
测试 / 验证 §5、§6、§7、§10 + docs/测试说明/
评审 §2、§7、§8、§9

2. 产品概述

2.1 产品定位

STM32F4-Base 是一块工业级嵌入式 DTU 平台固件,基于 STM32F407ZGTx,集成 以太网通信、SPI NAND 存储、ADC 采集、RS-485 通信与 FTP 文件服务,并自带 远程显示(UI 推流)、墙钟对时、看门狗自恢复、运行/自检记录等工业现场能力。

它的产品目标是 1:1 复刻参考产品 CLS100(配电保护测控装置)——按参考工程源码的 常量表与模块文件逐项对齐点表、定值、保护元件与规约栈(§2.4、§2.5)。在此过程中沉淀出的 分层底座(采集链 语义取数与有效性~出口与记录、配置引擎、就绪屏障、双端测试)同时是可复用的平台能力。

产品现状一句话:平台能力(网络 / 存储 / 时间 / UI / 日志 / 看门狗 / FTP / 配置) 已实现并台架验收;采集主线(语义取数与有效性采集 → 标定折算 → 全周傅氏相量 → 测频与遥测快照 → 保护判据 → 出口与记录 SOE → IEC 60870-5-104 上送)软件链路已全线贯通并台架闭环;与参考产品的差距 集中在三处:① 保护判据处于未标定闭锁态(等标准源两点标定)、② 点表规模远小于参考 (定值 40 vs 249 项、遥测 9 vs 31 点、开入开出 0 vs 138/31 点)、③ 独立子系统未立项 (故障录波、电度、多规约、SNTP)。即:"数"与"判据"已可信到引脚电压口径, 缺的是标定、点表铺开与一次设备接口(明细见 §2.5.2、§9)。

2.2 产品形态与部署

flowchart LR
    subgraph DEV["开发机(Windows)"]
        K[Keil MDK-ARM v5<br/>编译/烧录]
        SIM[LVGL PC 模拟器<br/>CMake + SDL2]
        PY[Python .venv<br/>脚本/测试]
    end
    subgraph TGT["目标板(DTU 硬件)"]
        M[STM32F407ZGTx @168MHz]
        P[CH395F / GD5F2GQ5UE / TPAFE5160 / SD2506 / RS-485 / LED×6]
    end
    subgraph RMT["远端客户端(PC/浏览器)"]
        C[DTU-RemoteLCD 或任意 TCP 客户端]
    end
    DEV -- "USB:ST-Link 下载器" --> TGT
    DEV -- "USB 串口 USART1 @115200 调试日志" --> TGT
    TGT -- "以太网 CH395F<br/>FTP:21 / 对时:8888 / 远程显示:7003" --> RMT
环境 角色 必需性
① 开发机 编译/烧录、UI 模拟器、脚本工具链 开发/测试必需
② 目标板 运行固件的 DTU 硬件 上机必需
③ 远端客户端 远程看图/按键、对时推送、FTP 文件操作 现场使用必需

关键产品特征:MCU 端无物理屏幕——UI 画面以 160×160 单色位图(1bpp)经 TCP 推送到远端 客户端渲染,按键亦由远端下发(见 §5.6、§8)。

2.3 设计目标与原则

# 目标 落地手段
G1 可靠:现场死机可自恢复、掉电不丢配置、错误可追溯 IWDG + 任务心跳位图、原子写 + 迁移、错误码通道四要素
G2 可维护:分层解耦、单一事实源、双端复用、门禁强制 六层架构、就绪屏障、生成器(菜单/字体/任务表)、pre-commit 钩子族
G3 可移植:UI/配置源码 MCU 与 PC 模拟器共用 平台后端抽象(*_mcu.c / *_sim.c),核心零平台依赖
G4 可扩展:新子系统/新配置段/新页面按模板接入 事件位扩展、段注册三步、页面插件描述符、App/protocol/ 预留
G5 可验收:每项能力有明确判据与自动化门禁 @build / @test / 静态门禁 / 主机侧纯逻辑单测 / 台架验证

设计原则(贯穿全项目):

  1. 上层只依赖相邻下层(单向);禁止反向依赖(例外经登记)。
  2. 状态位常驻、命令位消费——Event Flags 就绪位必须 osFlagsNoClear。
  3. 能推导的就不存——持久化"不可推导"的状态(导航历史、配置、日志),其余现算。
  4. 单写者——配置文件属主 = defaultTask;syslog 唯一写者 = defaultTask;控制台唯一发送者 = defaultTask。
  5. 一切写入 = 临时文件 + rename(原子替换),半截窗口结构消除。
  6. 测量不可信就不判据——未标定(VALID 未置位)或采样故障时保护停走,品质位如实上送, 绝不用"看起来对"的数去动作(§5.12、§5.15)。
  7. 点表优先于实现——本期做不了的 104 点照常入表并置 IV;缺行比置 IV 更糟, 主站将无法区分"没做"与"接线错"(§6.8)。

2.4 产品范围(1:1 复刻口径)

产品范围 = 参考产品 CLS100 的可移植能力全集。 本产品不是"在参考产品里挑一部分做", 而是按参考工程源码逐模块复刻:凡参考源码中存在的点表、定值单元、保护元件、记录类型、 规约栈,都属本产品目标范围;差异只允许来自物理不可移植项(§2.4.1)。

范围按复刻完成度分三档,判定口径见 §2.5.1:

档 含义 处置
✅ 已对齐 参考源码能力在本产品上已实现,且有台架/单测证据 进 §10 验收判据
🔶 部分对齐 骨架、口径、地址编排已对齐,覆盖范围小于参考(通道数 / 元件数 / 点数) 差额逐条进 §9
⬜ 未开始 参考源码存在、本产品无对应实现 逐条进 §9,不等于"不做"

当前分布(20 项能力,明细见 §2.5.2):✅ 2 项(采样节拍、自检类型)、🔶 10 项、 ⬜ 7 项、— 1 项(双核分工,不可移植)。

2.4.1 不可移植项(唯一允许落在范围外的部分)

# 不可移植项 参考实现 本产品 归因
X1 双核 ARM + DSP 分工 OMAP-L138(ARM 跑通信/HMI,DSP 跑保护) 单核 Cortex-M4F 按任务划分承担 芯片形态
X2 实时操作系统与工具链 VxWorks 5.x + CCS FreeRTOS V10.3.1 + Keil ARMCC 平台形态
X3 一次设备接口 KO / KI 板卡(出口、开入、硬压板) V0.1 无该硬件(§4.6 H3) 硬件缺失
X4 独立计量通道 专用计量芯片(电度) 无(跨转换器无同刻,§4.6 H1) 硬件缺失

X1~X4 是范围外项的全部。 除此以外不存在"参考有、我们决定不做"的能力—

2.5 1:1 复刻基线(参考源码能力清单)

判定口径:本节所有"参考能力"的数字,**一律从参考工程源 (实测已发现"89 个元件模块"实为 45 个、定值"约 260 项"实为 249 项两处偏差)。

2.5.1 复刻基线三要素

  1. 点表即契约:参考源码用常量表(g_t*Tab[])定义点表、定值、事件、压板。 这些表就是"要复刻什么"的唯一清单——表有几行,目标就有几个点。
  2. 地址即接口:104 的 IOA 由 Rly_IEC104.h 的基址宏划分段,段基址必须逐字对齐(§2.5.3)。
  3. 模块即元件:RelayUnit/ 下一个 .c 对应一个保护元件,元件数 = 文件数(§2.5.5)。

2.5.2 能力清单与复刻进度(源码实测)

# 能力 参考源码出处 参考数量 本产品现状 状态
1 定值项 APP/EquipCfg/Const_Set.c g_tSetModelTab 249 项 40 项(PS_ID_COUNT) 🔶
2 定值单元 APP/EquipCfg/Const_Set.h EN_SET_CELL_* 23 个有项(枚举 28) 5 组(短路/接地/过负荷/电压/频率) 🔶
3 104 定值映射 Comm/Pub/Const_CommSetPara.c g_tCommSetParaTab 107 项,0x8820~0x8891 40 项(0x8820~0x8890 局部) 🔶
4 遥测 YC APP/EquipCfg/Const_Ana.c g_tYcIndexTab 31 点 9 点(0x4011~0x4018 + 0x401D) 🔶
5 遥测模型 同上 g_tAnaModelTab 35 行 0 ⬜
6 电度 YM 同上 g_tYmIndexTab 8 种 0 ⬜
7 开入 KI APP/EquipCfg/Const_IO.c g_tInputModelTab 138 点 0(无硬件,X3) ⬜
8 开出 KO 同上 g_tOutputModelTab 31 点 0(无硬件,X3) ⬜
9 动作事件 APP/EquipCfg/Const_Rec.c g_tActRecTab 33 条(421~453) 7 类记录(App/log/sys_log.h) 🔶
10 录波测量通道 同上 g_tMeasureModelTab 65 通道 0 ⬜
11 软压板 APP/EquipCfg/Const_Soft.c g_tSoftTab 9 面(表容量 32) 1 面(PS_GLOBAL_EN) 🔶
12 保护元件 RelayUnit/*.c 45 个模块 9 个实例 🔶
13 记录队列 RecUnit/RecFile.c + GlobalDef/Const_Sys.h 13 类(128/256 条) 8 通道(7 文本 + SOE) 🔶
14 自检类型 GlobalUnit/SelfChk.c 3 类型 + 2 闭锁 3 类 ✅
15 故障录波 APP/EquipCfg/Const_Wave.h 3 类型 / 6 段 / RAM 16 个 0 ⬜
16 采样节拍 APP/EquipCfg/Const_VisEquip.h 20 点/周波(50 Hz) 20 点/周波(1000 Hz) ✅
17 上行规约 Comm/Pub/、Comm/Mon/ 12 种 1 种(104) 🔶
18 加密算法 Comm/Ecc/ SM2 / SM3 / ECDSA 0 ⬜
19 双核分工 CLS100_Arm/、CLS100_Dsp/ ARM + DSP 单核(X1) —
20 远端屏与按键链路 HMI/RemoeDisp/RemoDispBus.c、HMI/Dsp/Key.c、HMI/Dsp/Disp_Pub.c;屏板侧 DTU-LCD 串口屏板通道(显存 3200 B + 状态灯 4 B 位掩码下行 / 键号上行)+ TCP 7003 镜像 7003 四命令已通;串口屏板通道整条缺失(协议已按屏板源码定版,见 §5.16.2);INIT 应答 8 B(参考 29 B,其中 13 B 颜色信息不对齐)、无断点续传、无链路监视、缺 F1/F2 🔶

读法:🔶 / ⬜ 行全部是待办,逐条对应 §9.1;— 只出现在 X1~X4 不可移植项上。 本表是范围判定的唯一出处,§9 不再重复解释"为什么缺"。

2.5.3 104 地址空间(段基址逐字对齐)

段 基址 范围 容量 本产品使用
遥信 YX 0x0001 0x0001~0x1000 4096 定义 131,有效 6(YX1518/23/31)
保护 BH 0x1001 0x1001~0x4000 12288 0
遥测 YC 0x4001 0x4001~0x5000 4096 0x4011~0x4018、0x401D
参数 PM 0x5001 0x5001~0x6000 4096 0
遥控 YK 0x6001 0x6001~0x6200 512 0x600A(信号复归)、0x600B(全局压板)
设定 YS 0x6201 0x6201~0x6400 512 0
电能 YM 0x6401 0x6401~0x6600 512 0
步位置 STEP 0x6601 0x6601~0x6700 256 0

⚠ 段基址是 0x4001 / 0x6001,不是 0x4000 / 0x6000。参考源码 Comm/Pub/Rly_IEC104.h 的 CONST_104_BASEADDR_YC / _YK 明确 1 起编 (注释即写 4001-5000H、6001-6200H)。本仓 v1.1 及更早文档按 4000H+ / 6000H+ 描述 属笔误,以本表为准;§5.15、§6.8 已同步更正。

2.5.4 定值单元(23 个有项单元,合计 249 项)

单元 语义 项数 本产品
EN_SET_CELL_WatchDog 看门狗功能 63 ⬜
EN_SET_CELL_SYS3 系统参数 45 🔶
EN_SET_CELL_VolTimeRecv 电压时间型自愈 17 ⬜
EN_SET_CELL_AutoReCls 重合闸 16 ⬜
EN_SET_CELL_SYN 同期元件(FTU 型) 13 ⬜
EN_SET_CELL_OverCurI0 接地告警 13 🔶
EN_SET_CELL_VolPro 电压保护 13 🔶
EN_SET_CELL_WAVESTART 录波启动 12 ⬜
EN_SET_CELL_MeaLimit 遥测越限 10 ⬜
EN_SET_CELL_OverCurSpeed 过流加速 8 ⬜
EN_SET_CELL_SYS1 PT 参数 6 🔶
EN_SET_CELL_SYS2 CT 参数 4 🔶
EN_SET_CELL_Auto_FG 自动分闸 4 ⬜
EN_SET_CELL_Auto_HH 自动合闸 4 ⬜
EN_SET_CELL_InRush 励磁涌流闭锁 3 ⬜
EN_SET_CELL_OverCur 短路告警 3 🔶
EN_SET_CELL_VolQuaRate 电压合格率 3 ⬜
EN_SET_CELL_FZDDL 非遮断电流闭锁 3 ⬜
EN_SET_CELL_BHKO 保护出口展宽 2 ⬜
EN_SET_CELL_MeaRecord 遥测记录 2 ⬜
EN_SET_CELL_PowerSet 功率电压设置 2 ⬜
EN_SET_CELL_PTBreak PT 断线告警 2 ⬜
EN_SET_CELL_AutoCtrl 自动控制(活化/复归) 1 ⬜

枚举中另有 4 个单元在参考源码表内无项(EN_SET_CELL_YB_TY 功能软压板、OnceCch 一次重合闸、TwiceCch 二次重合闸、OverLoad 过负荷保护)——已被条件编译或注释掉, 因此 249 项分布在 23 个单元而非枚举的 28 个。另有 3 个单元(SYN / OverCurSpeed / VolTimeRecv)受 CN_DEV_TYPE_FTU 宏控制,属 FTU 型专属。

104 定值地址编排:107 项占 0x8820~0x8891 连续段中的 107 个地址,8 个空洞 (0x8822、0x8823、0x883E、0x883F、0x8842、0x8851、0x8852、0x8853) 对应参考源码中被注释掉的 4 条映射(ULTV_PARA_2、ULTV_Phase 等)。

2.5.5 保护元件(45 个模块 → 覆盖 8 个模块 / 9 个实例)

按功能归类(RelayUnit/ 文件名去 PRS_ 前缀):

类别 元件模块 个数 本产品
过流类 OverCurrent、OverCurrent_I0、OverCurrent_SpeedUp、OverCurrentI0_SpeedUp、FZDOverCur、OverCurWarn、OverCurWarn_I0、OverLoad 8 🔶 过流 Ⅰ/Ⅱ/Ⅲ + 过负荷(4)
电压类 OverVol、OverVol_U0、LackVol、LineHaveVol、HaveVolCls、NoVolTrip、PTBreak、CTBreak 8 🔶 过压 / 欠压 / 零序过压(3)
频率类 OverFr、LackFr 2 ✅ 过频 / 低频(2)
重合闸 AutoReCls、AutoReCls_JD、OnceCch、TwiceCch、ConnectBrkCls 5 ⬜
方向 / 功率 DirCell、PowDirJudge、PowerSet、YcOverLimit 4 ⬜
涌流 / 故障 InRushCur、FaultIsola、FaultRecov、BusEarthAlm、SgzAlarm 5 ⬜
自动控制 AutoCtrlTrip、ManualTrip、MusterRecov、ExvRec、ExvRecGW 5 ⬜
记录类 SOERecord、CORecord、FrzRecord、YcMeaRecord、YcMeaLimitRec、YcVolQuaRate 6 🔶 SOE 落盘(1,非判据元件)
录波 / 采样 WaveQdCell、RlyCommSam 2 ⬜

判据结构对齐(以 PRS_OverCurrent.c 为样板,三段过流共用一个核):

M_GRly_OverRelay(&bRelay, fAmp, fSetStart, fSetRet)     越限 + 返回系数滞回
  ∧ bFyOpen ∧ bDirOpenX ∧ bNOVOpen                      复压 / 方向 / 低压闭锁
GRly_TimeRelay(&bRelay, &tTimer, dwSetDelay, CN_T10MS)  定时限(10 ms 基准)
tTimer_KeepKI                                           电流保持(返回后仍延时保持)
tTimer_NoUI                                             无压无流判据(CN_T20MS / CN_T200MS)

本产品 prot_elm.c 的"越限 + 返回系数滞回 + 定时限"三元核与上述结构同构; 差异在于本产品用每元件独立实例表替代参考的全局定时器数组——这是单核移植的必要调整, 不改变判据语义。逐元件复刻计划见 docs/算法/继电保护功能复现规划.md。

2.5.6 上行规约全集(12 种 → 已复刻 1 种;加密算法另计)

方向 规约 参考源码 本产品
主站侧(对上) IEC 60870-5-101 Comm/Pub/Rly_IEC101.c、Rly_IEC101_B.c ⬜
IEC 60870-5-102(电度) Comm/Pub/Rly_IEC102.c ⬜
IEC 60870-5-103 Comm/Pub/RLY_IEC103.c、RLY_IEC103-tcp.c、Rly_IEC103T.c ⬜
IEC 60870-5-104 Comm/Pub/Rly_IEC104.c ✅
ModBus Comm/Pub/Rly_ModBus.c ⬜
CDT Comm/Pub/Rly_Cdt.c ⬜
国标电度 Whm_GB Comm/Pub/Whm_GB.c ⬜
IEC 61850(MMS / GOOSE / SV) Comm/Pub/struct61850.h、GlobalUnit/SttnLvlGoose.c ⬜
CAN Comm/Pub/Rly_Can.h ⬜
子站侧(对下) IEC 101(含 ABB / 西门子 / 无优先级变体) Comm/Mon/Rtu_IEC101*.c ⬜
IEC 104(含调试 / RIS 变体) Comm/Mon/Rtu_IEC104.c、Rtu_Dbg104.c、Rtu_RIS104.c ⬜
BALA101 / ModBus Comm/Mon/Rtu_BALA101*.c、Rtu_ModBus.c ⬜
加密 SM2 / SM3 / ECDSA Comm/Ecc/ ⬜

排期判断:104 已对齐;对下 ModBus RTU 与 101 是"配网终端"的必要项(接一次开关 / FTU), 与 RS-485 簇同批解冻;61850 依赖以太网多播与 MMS 栈,单核 M4 资源上需单独评估,属最末批。

2.5.7 差异归因与结论

归因 涉及条目 解除方式
外部资源(标准源、端子变比) 定值标定、保护判据解卡 两点标定(§9.2 第 4 步)
硬件缺失(X3 / X4) 开入 138、开出 31、电度 8、同期、三相通道 V0.2 硬件
立项未排 录波、多规约、SNTP、定值铺开 按 §9.2 顺序
算力 / 形态(X1 / X2) 双核分工、VxWorks 不解除。屏板链路已从范围外项移入范围内待做(规格 §5.16,执行规划 docs/任务规划/屏板链路.md):主机侧链路与参考 1:1 同构,不属"替代方案"

结论:本产品与参考产品的差距全部是"进度"而非"范围"——没有一项是"参考有而我们不做"。 已对齐的是软件骨架(采样节拍、相量算法、定值模型、104 上行、SOE 落盘、自检闭锁); 未对齐的是点表规模(249 / 31 / 138 / 31 / 33 / 65 vs 40 / 9 / 0 / 0 / 7 / 0) 与独立子系统(录波、电度、多规约)。因此 §9 统一表述为"复刻进度",不再出现"不做"。


3. 系统总体架构

3.1 六层分层架构

STM32F4-Base 项目分层架构

上图由 tools/arch_diagram/gen_arch_svg.py 生成(手绘 SVG,零连线交叉);改架构后编辑脚本顶部 ROWS 数据重跑即可,源数据与下表一致。

分层原则:上层只依赖相邻下层(单向);① 业务层为顶层(仅 net_cfg,被 UI 与基础服务共用), ② UI 层与 ③ 基础服务层同级并列。

层 目录 职责 关键模块
① 业务层 Drivers/BSP/NETCFG/ 顶层共享配置(被 UI 与基础服务共用) net_cfg
② UI 层 Drivers/BSP/UI/ LVGL 界面(与 PC 模拟器共用源码) ui_port ui_menu ui_menu_view ui_menu_tab ui_content_page ui_page_* ui_net_sink ui_font_cn_12 ui_deco
③ 基础服务层 App/、Drivers/BSP/NET/lftpd/ 应用侧服务、采集算法与协议编排 app_main sys_events app_cfg task/* algo/*(语义取数与有效性~保护判据)protocol/iec104/* log/soe_store lftpd time_sync
④ 中间件层 Drivers/BSP/NET/、Lib/、App/util/ 通用库 / 协议栈 net_socket net_select FatFs nand_ftl(dhara) LVGL sys_clock
⑤ 驱动层 Drivers/BSP/{CH395F,GD5F2GQ5UE,TPAFE5160,SD2506,RS485}/ 芯片寄存器 / 时序 / 中断 ch395f gd5f2gq5ue tpafe5160 sd2506 rs485
⑥ 内核 / HAL Middlewares/、Drivers/STM32F4xx_HAL_Driver/、Drivers/CMSIS/ 任务调度、外设 HAL、启动 FreeRTOS V10.3.1 · STM32 HAL · CMSIS
⑦ 硬件 — STM32F407ZGTx @168MHz SPI1 / SPI2 / I2C1 / UART4 / USART1 / DMA / GPIO / TIM7

3.2 运行时任务模型

九个 FreeRTOS 任务(Src/freertos.c 创建,任务体在 App/task/、App/sync/):

任务 栈(words / B) 优先级 职责
defaultTask 1280 / 5120 Normal FatFS 挂载(无卷 f_mkfs)→ 卷健康探针/自愈 → net_cfg_load + 定值/运行参数/通讯参数装载(配置引擎属主)→ 置 STORAGE_READY → 日志落盘(唯一写者)+ 2 s 配置轮询 + 各模块脏位落盘(prot_set / run_par / comm)+ SOE 排空 + LED 闪烁 + 栈水位观测 + 看门狗唯一喂狗者
netTask 960 / 3840 Normal 等存储 → net_stack_bring_up() → 置 NET_READY → net_poll 轮询 + CH395F 操作串行化(消息队列执行者)
ftpTask 1024 / 4096 Normal 等网络且存储(WaitAll)→ lftpd_start("/", 21) → 单客户端会话循环
testTask 2048 / 8192 BelowNormal 测试套件入口(test/board/test_config.h 选择)。产品构建不创建(未选套件时立即 vTaskDelete 回收其 8 KB CCM 栈)
uiTask 4096 / 16384 BelowNormal 等网络 → ui_port_init/ui_menu_init/ui_standby_init(空闲 60 s 切待机屏)/ui_net_sink → 10 ms 刷新 + 数据注入
timeSyncTask 640 / 2560 Normal 等网络 → TCP :8888 收 PC 推送时间 → 写 RTC
adcTask 640 / 2560 AboveNormal 采集主线唯一消费者:每拍 adc_input_poll()(TPAFE 快照 + ADC1 DMA 帧)→ adc_health 有效性 → phasor_run() 相量 → freq_run() 测频 → 每 200 ms meas_tick() 发布遥测快照
iec104Task 640 / 2560 Normal 等网络 → TCP :2404 监听 → 104 链路状态机(总召/变位/周期/遥控/定值/对时)+ 断链重听 + 网络代次自愈
protectTask 512 / 2048 Normal 20 ms 判据节拍:采样故障闭锁判定 → 定值校验和巡检 → prot_elm_run() 元件判据 → 动作边沿投递 SOE(不做 NAND I/O)

idle(128 words)/ timer(256 words)由 FreeRTOS 内核创建。所有任务栈从 56 KB heap_4 堆 (CCM)分配;CCM 水位 87.9%(<92% 门禁)。 任务表与 Src/freertos.c 的 osThreadAttr_t 一致,由 scripts/gen_task_table.py 生成并门禁校验; 栈配置与实测余量见 §7.3,改栈前后必须重跑 scripts/stack_report.py。

⚠ 节拍同源:TIM3 更新事件(1 kHz)同时触发 TPAFE CONVST 与(经 TRGO)ADC1 一轮 9 通道扫描, 并在 ISR 内唤醒 adcTask——采集节拍与任务唤醒不允许各自计时。 ⚠ ADC1 必须在挂 DMA 的瞬间处于关闭态:app_main_init() 步骤 4b-pre 的 adc1_disable() 不可删、不可后移, 否则 DMA 乒乓缓冲整体旋转 2 格(表象与"映射表写错"一致)。证据见 docs/子系统设计/ADC采样节拍设计说明.md §4.5。

3.3 就绪屏障(Event Flags)

就绪屏障(Event Flags)

用 CMSIS-RTOS2 Event Flags(sys_evtHandle)表达"子系统就绪",取代魔法延时与全局标志轮询。 生产者与消费者互不知晓,只经事件组解耦;新增子系统只需定义新 bit + 各自 wait/set。

位 名称 类型 语义
bit0 SYS_EVT_NET_READY 状态位 netTask:net_init + PHY 稳定完成
bit1 SYS_EVT_STORAGE_READY 状态位 defaultTask:FTL/FatFS 挂载 + 配置就绪
bit2 SYS_EVT_FTP_READY 状态位 ftpTask:lftpd_start 完成
bit3 SYS_EVT_TIMESYNC_READY 状态位 timeSyncTask:首次时间同步完成
bit4 SYS_EVT_NET_RECONFIG 命令位 UI:请求立即应用新网口配置
bit5 SYS_EVT_CFG_SAVE 命令位 UI:网口配置保存请求(defaultTask 消费并写盘)
bit6 SYS_EVT_CONSOLE_TX 命令位 控制台单写者:生产者入环形缓冲后置位
bit7 SYS_EVT_PROT_SET_SAVE 命令位 保护定值落盘请求:104 检测到定值脏后置位,defaultTask 原子写 /prot_set.bin
bit8 SYS_EVT_RUN_PAR_SAVE 命令位 运行参数段落盘请求:104 写运行参数后置位,defaultTask 整档外科保存

⚠️ 铁律:状态位(bit03)表达持久状态,任何消费者都不许消费——必须 osFlagsWaitAny|osFlagsNoClear。命令位(bit48)表达"请做一件事",必须恰好被消费一次(消费型等待)。 历史事故:就绪位被先到的等待者消费,导致 ftpTask 的 WaitAll(bit0|bit1) 永不成立、21 端口从未监听(静默)。

3.4 启动时序

sequenceDiagram
    autonumber
    participant M as main
    participant A as app_main_init
    participant K as osKernelStart
    participant D as defaultTask
    participant N as netTask
    participant S as adcTask / protectTask
    participant F as ftpTask
    participant U as uiTask
    participant I as iec104Task / timeSyncTask

    M->>M: HAL_Init + CubeMX 外设初始化<br/>(SPI1/SPI2/I2C1/UART4/USART1/DMA/GPIO/TIM3/TIM7)
    M->>A: app_main_init()
    Note over A: 时间子系统优先,使后续日志带时间戳
    A->>A: sd2506_init() → sys_clock_init()(墙钟基准)
    A->>A: rs485_init() → gd5f2gq5ue_init()(BBT 扫描)
    A->>A: tpafe5160_init() → adc_input_init()(语义映射自检)
    A->>A: 配置段注册(adc_cal / run_par / prot_set / comm)→ 定值/元件初始化
    A->>A: adc1_disable() → ADC1 挂 DMA(4b-pre,顺序不可变)→ 启动 TIM3 1 kHz 节拍
    A-->>M: "App init OK"
    M->>K: osKernelStart()
    K->>D: 调度
    D->>D: f_mount(无卷则 f_mkfs FAT32)→ 卷探针/自愈 → 配置装载<br/>→ 定值整表原子装载(损坏则保出厂默认 + 自检留痕)
    D-->>N: set SYS_EVT_STORAGE_READY
    S->>S: adcTask:等 TIM3 节拍 → 采集 → 相量/测频 → 200 ms 遥测快照
    S->>S: protectTask:20 ms 判据(未标定/采样故障则停走)
    N->>N: wait STORAGE_READY(Any|NoClear)→ net_init(ip,mask,gw,mac)<br/>→ PHY 强制 100M 全双工 → 等链路 ≤3s
    N-->>F: set SYS_EVT_NET_READY
    F->>F: wait NET_READY|STORAGE_READY(All|NoClear)→ lftpd_start("/", 21)
    U->>U: wait NET_READY(Any|NoClear)→ ui_port_init → ui_menu_init → ui_net_sink_start(7003)
    I->>I: wait NET_READY(Any|NoClear)→ TCP listen :2404 / :8888

顺序铁律:① 配置段注册必须先于 cfg_file_load(否则 FTP 上传的段不生效); ② adc1_disable() 必须在挂 DMA 之前;③ osKernelStart 之前禁调任何内核 API(含 osDelay / 队列)。

3.5 线程间通信

机制 对象 用途
Event Flags sys_evtHandle 启动就绪屏障 + 命令位(§3.3)
Message Queue netMsgQueue(深度 8,net_msg_t) 所有 CH395F 操作经队列串行化到 netTask 执行,保证 SPI 单线程访问
双区 + 序号(无锁) phasor 相量区、meas 遥测快照 写侧填满计算区后单字节翻转活跃索引;读者先取索引再整份拷贝,seq 判"是否换帧"
SPSC 环(无锁) soe_store(深度 8) protectTask 只投递动作边沿,defaultTask 排空落盘——保护路径零 NAND I/O
脏位 + 事件位 prot_set / run_par / comm 写入方置脏;104 侧 peek 后投递事件位,配置属主(defaultTask)落盘,失败保留脏位下轮重试
单字请求标志 prot_elm_request_reset() 跨上下文复归请求(104 遥控 YK11 在 iec104Task 落请求,protectTask 下一拍消费)

4. 硬件规格

4.1 主控与内存

项 值 说明
MCU STM32F407ZGTx Cortex-M4(FPU),LQFP144
主频 168 MHz HSE 8 MHz → PLL M=4 / N=168 / P=2
Flash 1 MB(0x08000000) 片内
SRAM 192 KB(128 KB 主 SRAM1+SRAM2 + 64 KB CCM) 链接器映射 128 KB 主 SRAM;CCM 用于 FreeRTOS 堆(任务栈)
RTOS FreeRTOS V10.3.1(CMSIS-RTOS2) HAL 时基 TIM7,tick = 1 ms;NVIC 4 位抢占,外设中断优先级 ≥5
工具链 Keil MDK-ARM v5(ARMCC v5) 工程锁 uAC6=0,不支持 armclang
CubeMX 6.17.0 + STM32Cube FW_F4 V1.28.3 与 .ioc 记录一致,再生成须用此组合

4.2 外设与引脚分配

权威来源:V0.1 网表分析报告 + Inc/main.h(代码已迁移至 V0.1)。下表为 V0.1 硬件的引脚。

外设 接口 引脚 说明
CH395F 以太网 SPI2 PB12 CS / PB13 SCK / PB14 SDO / PB15 SDI 10/100M 以太网控制器;PHY 强制 100M 全双工;SPI 分频系数必须为 8(PCB 设计约束)
GD5F2GQ5UE NAND SPI1 PE0 CS / PB3 SCK / PB4 MISO / PB5 MOSI / PB8 WP / PE1 HOLD 256 MB SPI NAND(2 Gbit)
TPAFE5160 ADC 并行 16 位 PG0~PG15 数据 / PC6 FRSTDATA / PC7 BUSY(EXTI) / PC8 RD / PC9 CONVST / PA8 OS2 / PA11 OS1 / PA12 OS0 高精度多通道 ADC
SD2506 RTC I2C1 PB6 SCL / PB7 SDA 提供墙钟基准与日志时间戳
USART1(调试串口 / U5 直连 TTL) UART PA9 TX / PA10 RX 115200 8N1;现为 printf 日志 + @test 采集通道。端口重排后改作屏板链路(700 kbaud,§5.16.2);PA10 双向均已接线
UART4(RS-485) UART PC10 TX / PC11 RX / PA15 DE 半双工通信(V0.1 轮换后 RS485#4 = UART4,docs/硬件平台/V0.1_网表详细分析报告.md §4.2)
USART2(RS-232 #3) UART PD5 TX / PD6 RX 经 U10 隔离 → U13 TPT3232E → CN1;端口重排后为日志口
UART5(RS-232 #1) UART PC12 TX / PD2 RX 经 U9 隔离 → U13 → CN1;备选日志口
状态 LED ×6 GPIO PC5 / PB0 / PB1 / PB2 / PF11 / PF12 低电平点亮
SWD — PA13 SWDIO / PA14 SWCLK V0.1 已修复 V0.0 的 SWCLK 引脚缺陷
调试口 — CN2(XH-3A,1=SWDIO/2=SWCLK/3=GND) V0.1 由 H2 排针改为 XH 端子

⚠️ V0.0 / V0.1 差异:V0.1 相比 V0.0 做了接口裁剪(删 8080 LCD 与 8 键)+ U17 大面积引脚重排 + ADC 前端通道置换(17 路中 13 路变化)+ 调试口改型。固件 BSP 与 ADC 通道映射表必须按 V0.1 重映射; 详见 docs/硬件平台/V0.1_网表详细分析报告.md。

4.3 存储器件

器件 容量 组织 软件栈
GD5F2GQ5UE 2 Gbit(256 MB) 2048 块 × 64 页 × 2048 B FatFS(FAT32)→ dhara FTL(磨损均衡 / 坏块管理 / GC)→ NAND 驱动
SD2506 — I2C1 RTC(时间/温度/电池诊断)
  • BBT 持久化:坏块表存于保留块池(顶部 4 块),不交给 dhara 管理。
  • 单写者纪律:defaultTask 拥有存储;netTask 只读 RAM 配置副本,不触卷。
  • FatFs 约束:FF_USE_LFN=0(严格 8.3 文件名);FF_FS_REENTRANT=1 + ffsystem.c 互斥钩子(超时 1 s);FF_FS_NORTC=0(get_fattime 直引用墙钟)。

4.4 硬件版本与兼容性

版本 状态 说明
V0.0 历史 含 8080 LCD、8 按键;存在 2 处设计缺陷(SWCLK 引脚错误致 SWD 不通、ADC17 落在非 ADC 引脚)
V0.1 当前 架构与 V0.0 一致;裁剪 LCD/按键、U17 引脚重排、修复上述 2 处缺陷;固件已迁移
V0.2 规划关注 新增关注项:VCAP 电容值未标注、PC13/14/15 子板 LED 3 mA 限流、SPI1 无法双落点

4.5 平台约束

约束 内容
CubeMX 生成文件 Inc/、Src/ 中带 USER CODE BEGIN/END 标记;自定义代码只能写标记区内
生成区外的定制 仅限 Src/iwdg.c 延后启动、4 个 Fault Handler 实体(scripts/check_cubemx_survival.py 审计兜底)
osKernelStart 前 禁止任何 FreeRTOS / CMSIS-RTOS API 调用
BOM / 编码 部分源文件带 BOM(Drivers/BSP/UI/*、App/task/ui_task.c、App/cfg/cfg_file.c、Lib/lv_conf.h),被工具改写丢 BOM 会导致 ARMCC 按 CP936 解码、中文字面量编译失败
SDIO V0.1 主板 SDIO 固定引脚组被 TPAFE/UART 全部占用 → 无 SDIO 能力(当前设计不受影响,FatFs 卷在 SPI NAND 上)
新源文件 必须双端注册(Keil .uvprojx + simulator/CMakeLists.txt),否则不参与编译

4.6 V0.1 硬件能力边界(对产品的硬约束)

下列五条是硬件事实,不是软件缺陷;§5 的功能范围与 §9 的"等条件"项均由它们推导:

# 约束 具体内容 产品影响 解除条件
H1 双转换器无共同采样触发 8 路电气量分属 TPAFE5160(16 位、8 通道同步、±5 V 双极性)与 STM32 ADC1(12 位、顺序扫描、0~3.3 V 单极性)两片;两片无共同触发,STM32 侧 9 通道一轮约 67 µs 跨转换器的相位 / 功率 / 功率因数 / 对称分量 / 三相同时刻判据一律不成立 → 方向元件、PT/CT 断线、三相过流、零序过流延后 V0.2 硬件:8 路电气量全部接 TPAFE(与备用路对调串联电阻,料号不变,走线级改动);固件只改映射表内容
H2 STM32 侧无中点偏置 单极性 0~3.3 V,交流量负半周削顶 UB/UC/IB/IC/IN 无有效值/相量,只能读码值监视;104 对应点恒置 IV V0.2 补偏置
H3 无出口继电器与开入回路 无跳闸/告警出口、无硬压板与开入遥信 保护动作只体现为遥信 + 日志 + SOE;104 遥控 YK1~4/13/14 否定确认 开入开出独立立项 + 硬件
H4 无本地屏与按键 160×160 单色屏仅存在于远端客户端 UI 以 TCP :7003 推流 + 远端按键回注(§8) 产品形态即如此,不解除
H5 无 SDIO SDIO 固定引脚组被 TPAFE/UART 占用 FatFs 卷只能落 SPI NAND(当前设计不受影响) 不解除

量纲口径(由 H1/H2 派生):在端子/子板变比确认与两点标定完成前,遥测与保护读数的单位是 ADC 引脚电压(eng=0),不是二次值;此时 ADC_CAL_F_VALID 未置位, 保护判据整体停走(§5.12)。这是刻意设计,不是"保护不动作"的缺陷。


5. 功能需求

每项功能给出:需求描述 → 实现要点 → 验收判据。状态标注:✅ 已实现并验收 / ⚠️ 已实现待专项 / ⬜ 待实现。

5.1 网络通信子系统(FR-NET)✅

FR-NET-1 以太网组网

  • 需求:上电后按配置的 IP/掩码/网关/MAC 完成以太网初始化,PHY 强制 100M 全双工,等链路稳定后置就绪位。
  • 实现:netTask 等 STORAGE_READY → 读 RAM 配置副本 → net_init(ip,mask,gw,mac) → 等链路 ≤3 s → 置 NET_READY。
  • ���据:串口出现 Network Init / net init: OK / PHY: 100M FULL;PC 能 ping 通设备 IP。

FR-NET-2 网络抽象层(BSD Socket API)

  • 需求:为上层提供 socket/bind/listen/accept/recv/send/close 与 select/poll 多路复用;所有 CH395F 操作串行化。
  • 实现:net_socket.c(BSD API)→ netMsgQueue(深度 8)→ netTask 串行执行;net_select.c 提供 I/O 多路复用。
  • 判据:三个 TCP 服务(FTP / 对时 / 远程显示)均经同一 API 工作;单连接模型下连接断开自动回到 LISTEN。

FR-NET-3 单连接模型与自愈

  • 需求:CH395F 配置为 8 Socket(索引寻址)+ TCP Server 单连接(set_fun_para(0x08),bit3 SOCKET_CLOSE;bit0 为保留位必须为 0),Socket 0 复用监听与数据通道;网络重建后服务自动重连。
  • 实现:三个 TCP 服务串行占用连接,断开自动重听;代次号(net_get_generation())驱动服务自愈。
  • 判据:FTP 旧会话异常断开后约 30 s 恢复监听;网络重建(改 IP)后服务自动重建监听。

网络层是全项目最成熟子系统(pending 机制 + 四份 Trap 记录 + 量化基线 + 探针族)。

5.2 存储子系统(FR-STO)✅

存储栈分层

FR-STO-1 三层存储栈

  • 需求:在 SPI NAND 上提供 FAT32 文件系统;具备磨损均衡、坏块管理、垃圾回收;上电无卷自动格式化。
  • 实现:FatFS(FAT32)→ dhara FTL → gd5f2gq5ue 驱动;defaultTask 挂载(无卷 f_mkfs)+ 卷健康探针/自愈。
  • 判据:FTP 可列目录/读写卷根文件;掉电后数据仍在。

FR-STO-2 坏块管理与持久化 BBT

  • 需求:坏块表持久化,重启后不丢失;不交给 dhara 管理。
  • 判据:全片擦除后容量恢复流程可用(见 docs/测试说明/存储维护与容量恢复.md)。

FR-STO-3 卷并发一致性

  • 需求:FTP 传输(ftpTask)与配置读写(defaultTask)并发访问卷时不得损坏。
  • 实现:FF_FS_REENTRANT=1 + 逐次加锁/放锁(超时 1 s);三条一致性协议(写 tmp+rename / 沉降去抖 / 单写者)。
  • 判据:并发 FTP 下载 + UI 保存无卷损坏、无死锁。

5.3 时间子系统(FR-TIME)✅

FR-TIME-1 墙钟维护

  • 需求:以 SD2506 RTC 建立 Unix epoch 墙钟基准,运行期以 tick 推进(零 I2C 流量),提供字符串格式时间。
  • 实现:sys_clock_init() 读一次 RTC 建基准(无效时按默认值自动校时);base+delta 法;30 天惰性再基准化(防 49.7 天 tick 回绕);sys_clock_get_str() → "YYYY-MM-DD HH:MM:SS"。
  • 判据:日志时间戳真实正确;主机侧单测 100 断言点通过。

FR-TIME-2 网络对时

  • 需求:PC 主动通过 TCP :8888 推送时间到设备,设备写回 RTC。
  • 实现:timeSyncTask 等 NET_READY → TCP listen :8888 → 收 PC 推送 → 写 RTC;30 s 无包则掉线重建监听。
  • 判据:对时后设备墙钟更新、日志时间戳正确。

已知限制:uint32 epoch → 2038 年上限。

5.4 配置引擎(FR-CFG)✅

配置文件分层架构

FR-CFG-1 通用配置文件

  • 需求:网络参数(IP/掩码/网关/MAC)持久化到 /config.ini(INI [network] 段);文件可经 FTP 下载/上传;格式纯文本、带注释、可编辑器编辑。
  • 实现:cfg_file 段键表引擎(段 RAM 副本复用模块静态结构体,键表 const 映射键→偏移);工厂模板首启自动生成。
  • 判据:文件缺失/损坏回退工厂默认并重建模板;FTP 上传后 2~5 s 自动生效。

FR-CFG-2 外科手术式保存 + 原子写

  • 需求:保存时保留用户注释/未知段/未知键(降级安全);写入原子(并发读者只见旧完整或新完整文件)。
  • 实现:受管键行替换,其余原样保留;临时文件 + unlink 目标 + f_rename;输出 >4096 B 拒绝保存。
  • 判据:设备保存后下载文件,用户注释与未来版本段落原样保留。

FR-CFG-3 变更检测与立即应用

  • 需求:FTP 上传配置后无需重启即生效;网络段变化触发网络重建。
  • 实现:defaultTask 每 2 s f_stat 比对 (size, mtime),连续 2 次稳定才重载(沉降去抖);[network] 段变化 → SYS_EVT_NET_RECONFIG → 网络重建(代次 +1,服务自愈)。
  • 判据:FTP 改 IP 后 2~5 s 生效(网络重建含等链路 ≤3 s)。

FR-CFG-4 旧档迁移(已取消 · 2026-10-10)

  • 原需求:旧固件的 /cfg/netcfg.bin(NCFG 二进制)首启自动迁移为 INI 并删除旧文件——已取消,不再实现。
  • 现口径:旧档若存在则被忽略(不读、不删、不迁移),配置直接回落工厂默认(/config.ini [network] 段模板)。
  • 取消理由:该一次性路径把整条配置写链(net_cfg_save → cfg_file_save → cfg_store_write_atomic → f_rename → FatFS → dhara FTL)挂进启动期调用图,defaultTask 静态最坏栈链 +600 B;本仓库不存在携带旧档的设备。
  • 判据:卷上残留 /cfg/netcfg.bin 时开机不产生任何迁移日志、旧档不被改动,/config.ini 按工厂默认生成。

FR-CFG-5 扩展性

  • 需求:未来所有模块配置(ADC/RS-485/端口等)进同一文件、按段组织。
  • 实现:未来模块接入三步——① 定义段结构体(静态工厂默认)② 写键表 ③ cfg_file_register()。

5.5 运行 / 自检记录与日志(FR-LOG)✅

FR-LOG-1 定长记录引擎

  • 需求:运行记录与自检记录持久化到 NAND,FTP 可直下。
  • 实现:sys_log 定长 64 B 文本记录(一行一条);/log/run.log(1024 条 / 64 KB 上限)、/log/selftest.log(512 条 / 32 KB);defaultTask 唯一写者;ISO8601 时间戳 + epoch。
  • 判据:UI"运行记录/自检记录"页可显示;FTP 可下载。

FR-LOG-2 控制台单写者日志

  • 需求:多任务并发日志不得字符级交错;异常场景(HardFault)日志可控。
  • 实现:4 KB 环形缓冲 + defaultTask 唯一发送(行级原子);内核前/ISR/异常钩子有界直发回退。
  • 判据:日志无交错;崩溃时能输出归因日志。

FR-LOG-3 上电/重启分类与待机显示

  • 需求:区分上电与重启;空闲切待机屏。
  • 实现:run.log 末条 epoch 时间差推断;硬件复位原因(RCC_CSR)优先;ui_standby 空闲 60 s 切入。

5.6 UI 与远程显示(FR-UI)✅

FR-UI-1 离屏渲染 + 双出口推流

  • 需求:MCU 无物理屏幕,UI 以 160×160 单色位图(1bpp,3200 B)渲染到离屏显存, 经两个出口送出:串口屏板通道(主,§5.16.2)与 TCP :7003(镜像);两路的按键都回注 UI。
  • 实现:LVGL 160×160 1bpp 离屏渲染到 g_ui_fbuf(3200 B)→ ui_net_sink 经 RemoDispBus 推流; 远端按键经协议注入。串口屏板通道尚未实现(§5.16.9 第 11 条)。
  • 判据:DTU-RemoteLCD 连 7003 出图(160×160 1bpp)+ 远端菜单导航可用; 屏板实物接入后 275 ms 节拍出图 + 状态灯正确(§5.16.10 第 8~15 条)。

FR-UI-2 菜单与内容页

  • 需求:42 节点层级菜单(最大 4 级)+ 内容页(装置信息/交流量/直流量等)。
  • 实现:三层拆分(数据层 ui_menu_tab 生成物 / 逻辑层 ui_menu 17 B 导航状态 / 显示层 ui_menu_view 级联框);内容页框架 + 页面插件描述符。
  • 判据:UI menu init: OK;菜单像素回归全 PASS。

FR-UI-3 待机屏

  • 需求:空闲超时(默认 60 s)自动切待机屏,仅确认键回菜单。
  • 判据:空闲后进入待机屏,按键返回菜单。

详见 §8 UI 规格。

5.7 看门狗与故障自恢复(FR-WD)✅

看门狗心跳模型

FR-WD-1 IWDG + 任务心跳位图

  • 需求:任务级死锁/饿死/断言死循环可自恢复(硬件复位),无需人工到场;不误杀正常长耗时窗口。
  • 实现:IWDG(LSI 独立时钟,PR=4 / RLR=1249 → 标称 2498 ms、最坏 ≈1701 ms);任务心跳位图(各自置位,无锁单字)+ defaultTask 单一喂狗者(task_wd_poll 每 100 ms 抽样);连续 8 次(800 ms)未达标 → 停喂 → 约 2.5 s 后复位;必需位掩码 0x37。
  • 判据:V2 任务饿死 ≤2.5 s 复位;V4 关中断死循环每 ~4.9 s 稳定复位;V5 30 min 真实负载零复位。

FR-WD-2 复位原因诊断

  • 需求:复位后可区分上电 / 看门狗 / 软件 / 引脚 / 欠压。
  • 实现:HAL_Init() 后一次性读 RCC_CSR 锁存并清标志;优先级 POR > PIN > IWDG > WWDG > SFT > LPWR > BOR。
  • 判据:串口 [APP] reset cause: <类型>;[WD] armed: 自检标记。

FR-WD-3 故障现场采集

  • 需求:HardFault / MemManage / BusFault / UsageFault 触发时输出完整现场。
  • 实现:4 个 Fault Handler 采集(PC/LR/xPSR/R0-R3/CFSR/HFSR/BFAR/MMFAR)+ fault_handler_enable() 使能 SHCSR 后三者。
  • 判据:日志形如 [ERR] MEMFAULT PC=... CFSR=... MMFAR=...。

已知边界:启动段(app_main_init + bring-up)无看门狗保护;ftpTask 首期不纳入监视(掩码剔除)。

5.8 LED 状态指示(FR-LED)✅

  • 需求:6 路 LED(低电平点亮)随系统状态变化。
  • 实现:defaultTask 循环驱动(闪烁指示系统活跃)。
  • 判据:目检 6 路 LED 随系统状态变化。

⚠ 本节只讲主板 LED。 屏板上另有 20 路状态指示灯(ID 0 电源常亮 + ID 1~19 位掩码), 由主机每帧下发 4 B 控制,属另一套输出,规格见 §5.16.3 ①。 两套 LED 的"位 → 业务状态"语义各自独立,不要混用同一个状态表。

5.9 ADC 采集与标定(FR-ADC)✅

FR-ADC-1 采样节拍与触发

  • 需求:8 路电气量(UA/UB/UC/UN、IA/IB/IC/IN)持续采集,1000 Hz(50 Hz 下 20 点/周波), 采集节拍与任务唤醒同源;不得用任务周期软定时冒充硬件节拍。
  • 实现:TIM3 更新事件(1 kHz)在 ISR 内触发 TPAFE CONVST,同一事件经 TRGO 触发 ADC1 一轮 9 通道并由 DMA2 循环搬入乒乓双缓冲;ISR 只置"消费者就绪"门并唤醒 adcTask(不做重运算)。
  • 判据:frame_seq 每 10 s 精确 +10000(1000.0 Hz)、frst_err=0、adc1_err=0、adc1_hw=0; 单拍消费耗时 ≤10 µs(DMA 搬运后实测 8 µs,软件轮询时为 122 µs)。

FR-ADC-2 语义通道映射

  • 需求:按语义取数(UA/UN/IA 等),不写死缓冲区下标——V0.2 换映射表即可切换硬件归属。
  • 实现:App/algo/adc_input.c 的语义表(TPAFE buf[6]/[5]/[2];ADC1 CH14/3/6/1/2/5)+ 开机 映射自检(STM32 映射通道必须落在扫描序列内,否则拒绝并自检留痕)。
  • 判据:ADC input layer init: OK;8 路 + 温度首帧全部读出、互异、非饱和。

FR-ADC-3 标定与量纲折算(标定折算)

  • 需求:把码值折算为工程量 (code + b) × k,系数与零点可落盘、掉电保持;未标定不得冒充二次值。
  • 实现:App/algo/adc_cal.c——k 以 Q16(µV/码 ×65536)、b 以码值存 [adc_cal] / [adc_cal_ofs] 段;ROM 默认 = 引脚侧 LSB(TPAFE 152.59 µV/码、STM32 805.66 µV/码); 三态可用性 ADC_CAL_F_VALID / ADC_CAL_F_CLIPPED 由 adc_cal_flags() 单点查询,104 / UI / 保护闭锁共用。
  • 判据:已知电压注入斜率与理论 LSB 偏差 ≤2%(2026-10-27 台架实测端子侧 6544.2 码/V,与引脚侧 理论 6553.6 差 −0.14%,零点 0~5 码、R²=0.9999997、极性对称 ≤0.34%);8 通道系数/零点往返一致。
  • 证据与现场步骤:docs/硬件平台/ADC通道映射说明.md §8.1、 docs/测试说明/ADC前端注入验证流程.md。

FR-ADC-4 采样有效性校验

  • 需求:芯片静默、丢帧、序号倒退、转换错误必须被检出并可闭锁保护,且不误报。
  • 实现:App/algo/adc_health.c 纯逻辑判定层——静默 100 ms 门限(电平位、可自愈)、丢帧边沿计数、 序号倒退锁存、FRSTDATA/HAL 错误/STM32 停摆计数增量;严重事件与上升沿写自检记录(每类每次开机一次)。
  • 判据:主机侧 31 用例全绿;台架零 [ERR](健康不误报),人为制造丢帧时 tgap 与 adc1_gap 同步可见。

FR-ADC-5 前端物理口径(已实测盖章)

  • 1k 串联 + 1k 到地 是源阻抗匹配、不是分压:ADCn 节点只有 {串阻、滤波电容、转换器引脚}, 「1k 到地」接在差分负端(ADC7_GND → R32 → AGND),故 AINn↔引脚变比 1:1。
  • 旧口径「2:1 分压 → 305.18 / 1611.3 µV/码」作废(那是芯片手册 ±10 V 档 LSB,不可混用)。
  • 剩余未知量只有子板/端子板变比,因此系数只能推到"µV/码 @ 引脚"(§4.6 量纲口径)。
  • 拓扑图 docs/images/ADC前端电路.svg。

5.10 RS-485 采集(FR-RS485)⬜ 冻结

  • 需求(已确认):半双工 RS-485 对下 ModBus RTU 采集(下行采集口;上行走以太网 104)。
  • 现状:rs485_init() 已调用;rs485_task.c 为空桩、未在 freertos.c 创建;App/protocol/ 为该 协议族预留(当前仅 104 在用)。整簇冻结(用户决定,2026-10-12)。
  • 重启门禁:先修「单缓冲包撕裂」「TX 超时拉 DE 未等 TC」两条,再谈接消费者;实现须满足 双缓冲 + 序号、DE 收尾超时路径、协议解析与硬件 I/O 分离。
  • 详见 docs/任务规划/暂缓-RS485.md。

5.11 遥测与相量(FR-MEAS)✅

FR-MEAS-1 全周傅氏相量

  • 需求:每 1 ms 产出基波/谐波相量,幅值直接是基波有效值,读者无锁取整份快照。
  • 实现:App/algo/phasor.c——N=20 全周 DFT,系数表离线预乘 √2/N;5 个实例 (IA/UA/UN 基波 + IA 二次/五次);每来新点整窗重算,算完单字节翻转计算区/使用区。
  • 判据:主机侧 57 用例全绿(系数表逐项复核、合成正弦幅值误差 ≤1%、双区交换);台架开机即产出 5 行 phasor(first),心跳持续刷新。
  • 双轨有效值:保护用基波有效值(抗衰减直流与谐波误动),计量/遥测要真有效值(谐波方和根) ——两者不可混用;本产品当前只实现基波轨,谐波方和根轨未做(§9)。

FR-MEAS-2 频率测量(测频与遥测快照)

  • 需求:45~55 Hz 内测频,精度优先于响应速度。
  • 实现:App/algo/freq.c——共轭乘积相位增量 + 解缠绕 + 自适应窗长(对齐纹波周期整数倍); 假值钳制带与系统合理带分离;幅值门 <50 码判无效;UA → IA 优先级。
  • 判据:45~55 Hz 扫频最坏误差 0.0101 Hz、1% 噪声 0.0160 Hz、启动收敛 ≤40 ms、阶跃 50→51 Hz ≤120 ms; 浮空(无信号)时 valid=0 不发散。

FR-MEAS-3 遥测快照(200 ms)

  • 需求:104 与 UI 共用同一份上游——"什么时候算新值、品质怎么判"只此一处决定;快照必须可无锁整体读。
  • 实现:App/algo/meas.c——每 200 ms(经过时间分频,非拍计数)取基波有效值 + 逐点品质,双区 + seq; 唯一发布者 = adcTask(meas_tick 全仓仅一处调用),其余任务只读。
  • 判据:主机侧布局用例钉死字段偏移(改字段 = 破协议);台架 104 与 UI 读数同源一致;快照未发布时 消费者得到 IV|NT 而不是 0。

FR-MEAS-4 品质与死区

  • 需求:品质必须如实反映"这一路能不能信";遥测变化上送不得被单点噪声触发。
  • 实现:品质位低字节与 104 QDS 同值直传;CLIPPED(削顶)由 104 侧映射为 IV; 死区 = 连续 2 个新测量点越限才确认(基准恒为上次上送值,防慢漂移吃掉基准),品质翻转当拍直报。
  • 判据:UB/UC/IB/IC/IN 五路恒 IV(品质驱动,V0.2 消除 H1 后零改动自动启用);死区两拍确认、 回摆撤销;TEMP 通道恒 NT。

5.12 保护功能(FR-PROT)🔶 软件就绪,判据现闭锁

FR-PROT-1 元件框架

  • 需求:统一"越限 + 返回系数滞回 + 定时限"元件核,判据为纯逻辑(吃测量值 + 定值),可离线单测; 新增元件只加实例表一行,不改核。
  • 实现:App/algo/prot_elm.c——数据驱动实例表 9 行;prot_elm_eval() 纯判据、prot_elm_run() 为 相量/频率到测量值的薄适配;延时用 now_ms 差值法(与节拍无关,精度不受 20 ms 节拍影响)。
  • 判据:主机侧 47 断言全绿(1.01× 启动 / 0.9× 返回 / 滞回保持 / 欠量方向 / 投退 / 闭锁联动 / 时基回绕)。

FR-PROT-2 元件清单(V0.1 有效子集)

元件 测量量 判据要点 104 遥信
过流 Ⅰ/Ⅱ/Ⅲ 段 IA 越定值经延时动作,返回系数滞回 YX16/17/18(并汇入 YX15 故障总)
过负荷 IA 越定值告警(默认不跳闸) YX23 过载
过压 / 欠压 UA 过量 / 欠量方向,各自延时 无遥信点(仅 SOE + 日志)
零序过压 UN(外部零序专用通道) 越定值经延时 汇入 YX15 故障总
过频 / 低频 测频结果 过量 / 欠量方向,默认 51.0 / 49.0 Hz 无遥信点(仅 SOE + 日志)

⚠ YX15 故障总的构成是 OC1∨OC2∨OC3∨3U0——电压类与频率类元件不在其中,其动作目前只能从 SOE、[PROT] 日志与 UI 记录看到。这是点表层面的已知缺口(送检点表要求独立分点时再补), 不要把它误读成"元件没动作"。

  • 未复刻的元件(建接口不使能,等条件):三相完整过流(B/C 相)、零序过流、方向/功率类、 PT/CT 断线、涌流制动、重合闸、故障隔离——原因见 §4.6 的 H1/H2,属 §9.1.1「三相与同期」, 解除条件为 V0.2 硬件。
  • 判据:[PROT] elm 边沿日志与 104 变位一致;未使能元件不误动。

FR-PROT-3 判据节拍

  • 需求:判据独立于采集任务,周期稳定,且不得阻塞在存储 I/O 上。
  • 实现:protectTask 20 ms 节拍(元件吃 50 Hz 基波有效值,相量每工频周更新,20 ms 足够); 纳入 IWDG 必需位;动作只投递 SOE(SPSC 环),不做 NAND I/O。
  • 判据:静态最坏链 872 B / 配置 2048 B(余 57%);动作到 104 上送端到端 ≤120 ms。

FR-PROT-4 闭锁(四源,任一命中即停走判据)

闭锁源 判据 行为
未标定 UA/UN/IA 的 ADC_CAL_F_VALID 未全部置位 整条判据链停走(产品构建默认态,等两点标定)
采样故障 adc_health_flags() 电平位(TPAFE/STM32 静默、序号倒退) 元件全部复位 + 本拍不判据,自愈后自动恢复
定值非法 定值校验和(sum32 正/反码)复核失败 闭锁相关保护并告警,需重写定值解除
全局软压板退出 PS_GLOBAL_EN = OFF(104 遥控 YK12) 元件复位 + 停判据,压板恢复即重返联

FR-PROT-5 出口(⬜ 未实现)

  • 需求:判据满足驱动跳闸/告警出口继电器,带保持/脉冲与回读自检。
  • 现状:V0.1 无出口硬件 → 保护"动作"= 遥信 + SOE + 日志;104 遥控 YK1~4 为否定确认。
  • 判据(立项后):动作驱动对应出口;出口回路自检可检出断线;遥控执行有确认与回读。

5.13 定值与运行参数(FR-SET)✅

FR-SET-1 三类参数

类 地址范围 内容 属性 本产品状态
固有参数 8001H~800AH 终端类型 / 操作系统 / 制造商 / 硬件版本 / 软件版本 / 校验码 / 规约类型 / 型号 / ID / MAC 只读 ⬜ 未实现(字符串类无法短浮点上送,未知 IOA 应答)
运行参数 8020H~8058H 遥测死区、PT/CT 变比、负荷越限/重载/过载报警、录波投退与定值、功率置负 可整定 🔶 已落死区 9 点 + k/b 覆盖 16 点(0x8030~0x804F);其余类别无消费者,留白不预埋
保护定值 8820H~8882H 过流 Ⅰ/Ⅱ/Ⅲ 段、零序过流、重合闸、低压/低频、励磁涌流闭锁、小电流接地等 可整定 🔶 40 项(Q10 定点):过流三段、过负荷、过压/欠压、零序过压、过频/低频 + 本地项(投退/返回系数/全局软压板)

FR-SET-2 定值模型与封存

  • 需求:定值改动必须原子可见——保护巡检任何时刻都看到自洽快照;范围校验失败整笔拒绝。
  • 实现:App/algo/prot_set.c——影子区写好后重封 sum32 正/反码,再单字交换活跃区; prot_set_selfcheck() 用 seqlock 式复核(提交撞见则本轮跳过);范围校验 + 整表 all-or-nothing 装载。
  • 判据:主机侧 90 断言(含伪造自洽越界对抗样本);104 写定值与巡检并发无 µs 级误锁。

FR-SET-3 持久化

  • 需求:定值掉电保持;档案损坏与版本换代必须能区分,损坏不得静默使用。
  • 实现:/prot_set.bin(magic + 版本 + 计数 + 值区 + sum32 正/反码对),走临时文件 + rename 原子写; 写路径 = 脏标志 → 事件位 → defaultTask 落盘(失败保留脏位下轮重试); 装载在 STORAGE_READY 之前整表原子完成。
  • 判据:非默认定值跨复位保持(台架 7.5 A 往返读回一致);版本换代(旧档)记 INFO, 真损坏记 ERROR + 自检留痕并回落出厂默认。

FR-SET-4 运行参数段

  • 需求:死区与通道系数可由主站整定并持久化,且系数只有一份真源。
  • 实现:App/algo/run_par.c——[run_par] 段 9 键(死区,毫单位 int32)+ k/b 覆盖 16 点; k/b 写为 adc_cal_set 代理(合法带 ROM×[0.5,2.0] 由执行段裁决),run_par 不存系数。
  • 判据:0x8027~0x802A(过压/欠压告警段)永不被覆盖(路由 run_par 先、未命中落 prot_set); 越带写回否定确认;整档保存一趟覆盖 [run_par] 与被改写的 [adc_cal]。

FR-SET-5 主站读写

  • 需求:主站可读定值、两段式写定值,失配/越界必须明确否定。
  • 实现:C_RD 读 + C_SE_NC 两段写;地址 = prot_set comm_addr(点表不另立地址表); comm_addr = 0 的本地项显式不可寻址(防 IOA=0 误命中)。
  • 判据:读回值 = 写入值(COT 正确);本地项读回 COT=14 + EVI;执行段写失败不影响旧值。

5.14 SOE 与动作记录(FR-SOE)✅

FR-SOE-1 记录格式

  • 需求:动作与状态变化必须带时标留痕,且保护路径不得因写盘被拖慢。
  • 实现:App/log/soe_rec.c——64 B 定长记录 = 类型 + 元件号 + IV 位 + seq + CP56Time2a + epoch + 值 + 校验和; 六类边沿:元件动作 / 复归、软压板投 / 退、采样数据块 / 恢复。
  • 判据:/log/soe.log 经 FTP 下载后逐条解码通过(校验和、seq 严格 +1、CP56 与 epoch 交叉一致)。

FR-SOE-2 落盘与上送

  • 需求:写盘单写者;104 变位与落盘记录同源同时基。
  • 实现:protectTask 投递 SPSC 环(深度 8,禁 DBG)→ defaultTask 排空落盘; 104 自发单点换 M_SP_TB_1(带 CP56 时标),总召/周期保持 M_SP_NA_1。
  • 判据:动作路径零 NAND I/O(protectTask 静态链 872 B 改前后不变);104 时标 = 事件上送时刻, 与落盘记录(事件发生时刻)差 ≤ 一拍 + 排空延迟(≤50 ms)。

FR-SOE-3 记录体系(✅ 软件面已落地;真机判据待台架)

  • 现状:七类文本记录(运行 / 自检 / 事故 / 告警 / 启动 / 操作 / 遥控)+ 二进制 SOE 已落地, 「记录类型 = 日志 ID 本身」(一类记录一个文件,记录体内无类型字段位);UI 六页已绑 (记录 5 页 + 运行报告,2026-10-28)。运行报告的四个数取自 boot_stats(SD2506 用户 SRAM 上电次数 + 本次复位原因快照)与 iec104_serv 的四个只读观测计数,经 info 帧下发 (口径 docs/UI设计/UI_数据供给设计说明.md §4.4)。
  • 判据:五类记录各有写入点、可翻最近 20 条、空记录明确显示"无记录"、共用 reader——软件面已满足 (空态与四个范围标签由 60 张像素黄金钉住;模拟器侧这些文件没有写入方,只拍到空态)。 真记录翻页、掉电后保持、清除记录后归零、boot_count 自增与四态判定待台架复核 (docs/任务规划/登记簿.md §7)。

5.15 IEC 60870-5-104 上行(FR-IEC104)✅

本产品为被控站(受控端):104 TCP 服务器,端口 [comm] 段 port(工厂默认 2404),主站主动连入。 点表口径见 §6.8,设计细节见 docs/子系统设计/IEC104上行设计说明.md。

FR-IEC104-1 链路层

  • 需求:APCI U/S/I 帧、STARTDT/STOPDT/TESTFR、k/w 窗、t1/t2/t3;TCP 流重组与坏帧自恢复。
  • 实现:App/protocol/iec104/iec104_link.c(纯逻辑:收=喂流、发=回调、时基注入);参数 k=12 / w=8 / t1=15 s / t2=10 s / t3=20 s;序号 15 bit 回绕、超时一律差值法。
  • 判据:主机侧 174 断言全绿;台架主站往返 STARTDT → 总召四组 → actterm 全通过。

FR-IEC104-2 遥测上送

  • 需求:遥测短浮点、系数 1、点号落在 0x4001 起的遥测段(段基址见 §2.5.3);支持背景/总召、 周期(60 s)、死区与品质上送。
  • 实现:数据源 = 测频与遥测快照(§5.11);品质直传,CLIPPED 映射为 IV;死区运行时副本(运行参数段可读写)。
  • 判据:总召读回值与 UI 同源一致;死区两拍确认、品质翻转直报;削顶五路恒 IV。

FR-IEC104-3 遥信上送

  • 需求:双位置遥信上双点、其余单点;变位突发 + 背景扫描;无效点也入表并置 IV。
  • 实现:iec104_pts.c 点表(33 点)+ COV 判定;突发单点带 CP56 时标。
  • 判据:YX15~18/23/31 为活数据;YX1~14/19~22/24~30/32~33 恒 IV(缺行比置 IV 更糟)。

FR-IEC104-4 遥控

  • 需求:双点命令两段式(选择 82H / 执行 02H),失配或越界否定确认。
  • 实现:YK11 信号复归 → 跨上下文复归请求;YK12 全局软压板 → 定值原子写; YK1~4 开关、YK13 电池活化、YK14 解除闭锁 = 否定确认(无硬件)。
  • 判据:YK11/YK12 两段正答且行为可观测(压板退出态跨复位保持);否定确认带正确 COT + PN。

FR-IEC104-5 定值与运行参数读写

  • 需求:C_RD 读、C_SE_NC 两段写;地址即定值表 comm_addr;写成功即持久化。
  • 实现:见 §5.13;路由顺序 = run_par 表先、未命中落 prot_set。
  • 判据:读回一致、越界否定、断电重启保持。

FR-IEC104-6 对时

  • 需求:主站 C_CS 对时写入设备墙钟;时标无效如实置 IV。
  • 实现:CP56 → epoch ms → sys_clock(含 RTC 写回);epoch >2^32 显式拒绝回 PN。
  • 判据:对时后日志时间戳跟随主站;C_CS 后 SOE 时标同步。

FR-IEC104-7 响应时间(点表推荐值)

参数 要求 本产品实测 / 设计
终端启动时间 ≤100 s 开机到 net init: OK ≈0.6 s,到 104 监听 <2 s
104 连接 / 总召 ≤3 s / ≤8 s 连接 <1 s;总召分片 + 单轮 4 ASDU 预算,实测远小于 8 s
SOE 上送 ≤5 s 变位到上送 ≤120 ms
遥控选择 / 撤销 / 执行 ≤5 s 同轮应答(ms 级)
读定值 / 改定值预置 / 执行 ≤10 s / ≤5 s 同轮应答(ms 级)
读文件目录 / 文件 ≤30 s ⬜ 未实现(文件传输未立项)
录波文件存储 ≤15 s ⬜ 未实现(录波未立项)

FR-IEC104-8 单连接与自愈

  • 需求:单连接语义(CH395F 单 socket);断链自动重听;网络重建(改 IP)后服务自愈;协议故障主动拆链。
  • 实现:监听与数据通道复用同一 socket(EOF 时 net 层 auto_relisten,应用层不关 fd); net_get_generation() 变化即重建;坏帧 / N(R) 倒退 / t1 超时 / 发送 3 连败 → 本端拆链促主站重连。
  • 判据:断链后自动恢复监听;改 IP 后重建;V0.1 为首到优先(后连优先需 net 层支持,未实现)。

FR-IEC104-9 本期未实现项(如实登记,均为 §9.1 复刻进度条目)

项 原因 归属
多主站 / 双链路冗余 单连接 socket 语义;后连优先需 net 层扩展 规模型
归一化值 / 标度化值上送 点表要求短浮点(系数 1),无需另做 不适用
双点遥信带时标 V0.1 双点恒 IV,无意义 随开入硬件(X3)
定值区切换 / 定值文件下装 产品未定义多定值区(参考有 4 区) 规模型
文件传输(目录 / 读文件 / 录波) 录波子系统未开始 规模型
固有参数 8001H~800AH 字符串类无法短浮点上送 规模型
主站 IP 白名单 单 socket 上"拒绝"= 断链重听,可被扫描打成 SPI 风暴且易锁死真主站 不适用

5.16 屏板链路:串口主通道 + 网络镜像(FR-HMI)🔶

口径更正(2026-10-28):参考产品的屏与键不在主机板上。主机侧源码里 5 个"碰硬件"的函数 KeyGet() / WriteScreenByByte() / LCD_LED_Update() / getRs485Key() / anyNewKey() 全树只有声明、没有实现(由屏板 BSP 库提供);按键轮询函数名即 Key_Rs485_Process() (注释"轮询从485传来的按键值");屏板插槽号 CN_SLOT_DISP = 0(注释"显示板插槽号固定为0")。 结论:屏和键都在一块独立的屏板板件上,主机只负责"送帧 + 收键"。本产品与参考同构, 不在本仓实现的只剩那块屏板板件硬件本体(独立工程 DTU-LCD);主机侧"送帧 + 收键"链路是范围内待做(§5.16)。

两条通道,串口为主、网络为镜像:参考把同一份显存同时喂给两个出口——串口屏板通道 (LCD_LED_Update 变化驱动 + WriteScreenByByte 500 ms 兜底)和网络显示总线(TCP 7003)。 也就是说"显示信息不只走网络,还走串口"。本产品目前只有网络这一路,串口屏板通道整条缺失 (§5.16.9 第 11 条),这是本项复刻的最大缺口——没有它,产品无法脱离 PC 独立带屏运行。

屏板固件已到手(2026-10-28):屏板侧源码在 D:\Code\DTU Code\DTU-LCD(STM32F103ZE + UC1698U 160×160 单色 + 20 路状态指示灯 + 7 个物理按键),物理层与帧格式全部可从代码确定。 原"四项未知"(波特率 / 帧格式 / 方向控制 / 分片)已全部消解 → 见 §5.16.2、§5.16.3。 该链路不是可选项:屏板是主动召唤方,主机不应答则屏板无画面、无灯、无键。

5.16.1 一份显存、两个出口(串口为主,网络为镜像)

参考的 HMI 只有一份显存(g_tVsr[0].pwbyLCDMemory,物理基址 CN_VIDEO_ADDRESS_BASE = 0xC1F00000, 非 cache 区,3200 B),但有两个互不影响的出口——串口屏板通道是主通道,网络总线是镜像:

出口 归属任务 调用 下行载荷 节拍
串口屏板通道(主) tDisp(Dsp_Main) LCD_LED_Update(ptr, 3200, ledbuf, 4) 显存 3200 B + 面板 LED 4 B 变化驱动(anyNewKey() || LCD_UPDATE_FLAG)
串口屏板通道(周期兜底) tRemoDisp(RDisp_Main) WriteScreenByByte(byLcdMemory) 显存 3200 B 500 ms(tTimerLCD)
网络显示总线(镜像) tRemoDisp(RDisp_Main) RDisp_Proc / RDisp_Send 0xAA/0xBB 帧(INIT/KEY/LCDMEM) 客户端召唤驱动

上行(按键)同样是两条,最后在 Key_Read() 汇合:

上行通道 采集方式 载荷 与另一路的关系
串口屏板通道(主) getRs485Key() 轮询 + anyNewKey() / ClearNewKeyEvent() 事件 物理键号 1~10 映射为逻辑键值写入 g_tKey
网络显示总线(镜像) RDisp_Proc_SaveKey → g_tRemoteKey 键值位掩码 1 B 写入 g_tRemoteKey
汇合点 Key_Read()(Key.c:199) — 先取远程、再被本地覆盖——两键同时挂起时本地(串口)优先

串口通道的物理层与协议,交付源码里看不到——屏板侧的 5 个入口全是未实现的外部符号 (KeyGet / WriteScreenByByte / LCD_LED_Update / getRs485Key / anyNewKey), Release/ 下的 .o 与 .out 由更完整的树编译而来。能确定的只有调用契约(协议本身已由屏板源码补齐,见 §5.16.2):

注:上表"物理键号 1~10"是参考主机侧的假设。屏板固件实测只有 7 个物理键, 键值 1~9 有入口、10 无入口,且 9/10 语义与参考的 F1/F1|ENT 不同(§5.16.3 ②)。

契约项 已确定的内容 依据
下行粒度 3200 B 整帧 + 4 B LED,一次调用一帧(无分片参数) LCD_LED_Update(ptr,len,ledbuf,ledbuflen) 签名
下行长度 len = 3200 为实参,非推导 Disp_Pub.c:8295-8298
上行粒度 单字节物理键号,0 表示无键 getRs485Key() 返回 uint8_t,Key.c:176 判 key == 0 即返回
事件语义 有"新键事件"与"清除事件"两个动作 anyNewKey() / ClearNewKeyEvent()
屏板地址 板件槽号 0(CN_SLOT_DISP) Key.c:8 注释"显示板插槽号固定为0"
按键消息 TAG 0xC22C(CN_MBUS_TAG_KEY,注释"与开入 TAG 相同") Key.c:9(该宏在本文件内未被引用,属备用/历史路径)
面板指示灯 WritePanelLED(pbyLedFlag) 已在 BSP 中实现(SR1200_peri.c:362) 与屏板同一块面板
背光 / 对比度 Lcd_BackLight()(Lcd_BKOn/Lcd_BKOff 走 GPIO)、Lcd_SetContrast(值, 亮) omapl138_lcd.c:240-247、Disp_Interface.c:3281
屏板初始化 Lcd_init_display(0xC1F00000) 由 LocalDisp_StartTask() 调用,不经过任何 UART 打开动作 Disp_Main.c:56

⚠ 原"四项未知"已由屏板固件消解(2026-10-28,实测值见 §5.16.2): ① 波特率 700000 8N1;② 无帧头,整帧定长 + 尾部 CRC-16/MODBUS; ③ 软件 DE(屏板侧 PA1,低 = 发送);④ 不分片——一帧一整屏,屏板召唤、主机应答。 上表保留作为取证过程,说明"只看参考主机侧源码能确定什么、不能确定什么",不是待办。

5.16.2 串口通道:物理层与帧格式(屏板源码实测)

屏板固件工程 DTU-LCD 已在手(STM32F103ZE / 512 KB Flash / 64 KB RAM / 72 MHz,UC1698U 160×160 单色), 链路协议逐字节可确定。原"四项未知"全部消解,本节即为主机侧必须实现的契约。

⚠ 角色与直觉相反:屏板是 Modbus 主站,主机是从站。 屏板主动发请求,主机在请求后应答; 主机从不主动推送,也不允许主动推送(半双工总线,谁先说谁占用)。 这与 §5.16.4 的 TCP 7003 通道方向相反——网络通道是客户端召唤,串口通道是屏板召唤。

物理层

项 屏板侧实测值 依据
接口 RS-485 半双工 rs485.c
引脚 TX = PA2、RX = PA3、DE = PA1 rs485.h
DE 极性 低 = 发送,高 = 接收 RS485_SEND_ENABLE() 拉低、RS485_RECEIVE_ENABLE() 拉高
波特率 700000 bps #define BAUDRATE 700000
数据格式 8 数据位 / 无校验 / 1 停止位,无流控,16 倍过采样 rs485.c 初始化
接收 HAL_UARTEx_ReceiveToIdle_IT(空闲断帧),DMA 版本被注释掉 rs485.c:192-195
发送 HAL_UART_Transmit(..., 1000) 阻塞发完,随即切回接收 RS485_SendBuff()
缓冲 RX 4208 B、TX 8 B UART_RX_LEN / UART_TX_LEN

700 kbaud 在两种候选时钟下都零误差(2026-10-28 更正分频算法):16 倍过采样(OVER8 = 0)时 USARTDIV = fCK / (16 × 波特率),写入值 BRR = (整数部分 << 4) | (小数部分 × 16)。

  • 屏板链路的默认端口 USART1 挂 APB2 = 84 MHz:84 000 000 / (16 × 700 000) = 7.5 → 整数 7、小数 8 → BRR = 0x0078,误差 0 %。
  • 若改用 APB1 上的实例(UART4 / USART2 / USART3,42 MHz):42 000 000 / (16 × 700 000) = 3.75 → 整数 3、小数 12 → BRR = 0x003C,误差 0 %。

⚠ 旧版本本节写的"42 000 000 / 700 000 = 60 → USARTDIV = 60.0、BRR = 0x3C0"是错的—— 漏掉了公式里的 16 倍过采样。照 0x3C0 写下去实际波特率是 43 750,不是 700 000。 若改时钟树或改用 HSI,必须重算——700 kbaud 下 2 % 误差已足以丢帧。

端口裁定(用户决定,2026-10-28):屏板走 USART1,日志口让位。 屏板链路改用 USART1(PA9/PA10)——这条通道是 MCU 引脚直出 TTL,不经过板上任何收发器, 因此收发器速率上限问题不复存在:本板 485 通道上的 U15 = TP8485E-SR 只有 250 kbps (docs/芯片手册/TP8485E-SR.md)这件事,对屏板链路不再构成约束。 作为交换,调试日志迁到 RS-232 通道(V0.1 板上 RS232#3 = USART2 PD5/PD6, 备选 RS232#1 = UART5 PC12/PD2,两者都经隔离器 → U13 TPT3232E → CN1), 迁移在屏板链路跑通之后做,见下方"主机侧端口重排"。

⚠ "PA10 未接线"这条旧结论已撤销(2026-10-28 用户确认):App/log/console_log.c 与 docs/子系统设计/控制台单写者日志设计说明.md §12 里的"PA10 悬空"是 2026-10-02 的归因推断, 不是实测;PA10 一直是接线的。所以屏板链路不需要额外飞线。

但 ORE 锁存的真正充分条件与引脚悬不悬空无关——RX 使能了却从不读 DR:线上只要出现 任意一个字节或一个噪声沿,RXNE 置位后没人读,下一个事件就把 ORE 锁存;而 ORE 只能用 "先读 SR 再读 DR"清除,于是永不自愈。这条对本实现有两条硬要求: ① 屏板链路要用 RX,就必须真的消费 DR,并在 HAL_UART_ErrorCallback 里清 ORE 后重挂接收 (否则一次噪声就永久锁死,症状与"屏板不回帧"一模一样);② 新日志口设 UART_MODE_TX 仍然是对的——那是从机制上把 RX 摘掉,与 PA10 接不接线无关。

帧 A:召唤 / 按键(屏板 → 主机,固定 6 B)

偏移 长度 字段 取值
0 1 从站地址 固定 0x01(主机的从站地址,不是屏板地址)
1 1 功能码 固定 0x03(读保持寄存器)
2 1 命令类型 0x00 = KEY_CMD(按键事件,立即召唤)
0x01 = RT_CMD(周期刷新,275 ms 一次)
3 1 按键值 KEY_CMD 时有效(见 §5.16.3 键值表);RT_CMD 时恒为 0(按键发完即清 key_bk,见 RS485_Process())
4 1 CRC-16 高字节 CRC-16/MODBUS
5 1 CRC-16 低字节 同上

CRC-16/MODBUS(多项式 0xA001 反转式、初值 0xFFFF、查表法 auchCRCHi[]/auchCRCLo[]), 只覆盖前 4 字节,高字节在前(cmdbuf[4] = crc>>8、cmdbuf[5] = crc)。

帧 B:图像应答(主机 → 屏板,固定 4208 B)

偏移 长度 字段 说明
0 3200 Picture[] 显存位图:160 行 × 20 B/行,1 bpp,MSB 在前,bit=1 → 白
3200 4 info[0..3] 普通图:LED 状态,32 位位掩码,小端(info[0] = bit0~7)
LOGO 图:info[0..1] = 宽、info[2..3] = 高(均大端)
3204 1 info[4] LOGO 魔数高字节 0x89
3205 1 info[5] LOGO 魔数低字节 0x45
3206 2 info[6..7] 保留,屏板不读
3208 998 保留填充 屏板不读,但参与 CRC 计算,须固定填充(建议 0x00)
4206 2 CRC-16 覆盖 [0, 4205],高字节在前

⚠ 帧长以代码为准:4208 B,不是 3208 B。 屏板 readme 与 BMP_LEN 都写"3208 字节", 但接收侧实参是 Check_CRC(DR, UART_RX_LEN),UART_RX_LEN = 4208 → CRC 取 DR[4206]/DR[4207]、 覆盖 DR[0..4205];rs485.h 注释亦为"接收缓冲区长度,与 Modbus 数据帧长度一致"。 若主机只发 3210 B,屏板会在 DR[4206] 处读到陈旧字节,CRC 必失败并静默丢弃。 有效载荷只有前 3208 B,其后 998 B 为凑齐 CRC 窗口的填充。此项须台架实测复核后固化。

⚠ 应答帧不是合法 Modbus RTU 响应:没有地址、没有功能码、没有字节数域,是一段裸二进制块。 因此不能套用现成 Modbus 从站栈,只能按上表手工组帧。

⚠ 同一 4 字节双解释:info[0..3] 在普通图里是 LED 位掩码、在 LOGO 图里是宽高。 区分只靠 info[4..5] == 0x89 0x45。先判魔数再解释这 4 字节,顺序不能反。

时序与预算

参数 屏板侧常量 实际时间 含义
基准节拍 5 ms 定时器 — Process_Count() 每 5 ms 递增
周期召唤 RS485_RT_COUNT_MAX = 55 275 ms 无按键时每 275 ms 召唤一次
应答超时 RS485_ACK_COUNT_MAX = 40 200 ms 发帧后 200 ms 未收齐 → 本次超时
连续超时 RS485_ACK_OVERTIME_MAX = 5 5 次 连续 5 次超时 → 强制允许重发(不重启串口,重初始化被注释)
屏板自复位 sysRunTime > 1 000 000 ≈5000 s(83 min) 屏板自己无条件 HAL_NVIC_SystemReset()

200 ms 是硬指标:700 kbaud 8N1 → 10 bit/字节 → 4208 B ≈ 42 080 bit ≈ 60.1 ms, 占预算 30 %,留给"取显存快照 + 组帧"约 140 ms,宽裕。 但若主机把整帧拆成多次 HAL_UART_Transmit 且中间被高优先级任务抢占,很容易越线—— 建议一次性 DMA 发送 + 发送完成中断,不要逐块阻塞发。

主机侧端口重排(2026-10-28 用户裁定)

串口 引脚 V0.1 板上通道(docs/硬件平台/V0.1_网表详细分析报告.md §4.2) 重排后用途
USART1 PA9 / PA10 调试口 + U5 直连 TTL(ST_TX0/RX0),MCU 直出、不经任何收发器 ✅ 屏板链路(700 kbaud)
USART2 PD5 / PD6 RS232#3(U10 隔离 → U13 TPT3232E → CN1) ✅ 调试日志(115200,屏板链路之后迁移)
UART5 PC12 / PD2 RS232#1(U9 隔离 → U13 → CN1) 备选日志口,与 USART2 二选一
UART4 PC10 / PC11,DE = PA15 RS485#4(U11 隔离 → U15 → A/B → CN1) 冻结簇,本项不碰
USART3 PB10 / PB11 U5 直连 TTL(ST_TX2/RX2) 空闲

为什么是 USART1:它是唯一一条不经收发器、MCU 引脚直出的通道,而 700 kbaud 恰好卡在收发器上 (U15 = TP8485E-SR 只有 250 kbps,docs/芯片手册/TP8485E-SR.md)。换到这条线上,速率问题从根上消失, 也不用改任何硬件。UART4 保持 RS-485 冻结簇不动——rs485_init(&g_rs485, &huart4, …) 与 V0.1 一致,无需摘除。

这次重排带来两件事,必须在任务里体现:

  1. 日志口迁移不是一行改动:App/log/console_log.c 里 huart1 出现 5 处(含 huart1.Instance == NULL 的空指针短路判据),自愈函数 con_uart_reinit() 还直接写 USART1_IRQn、__HAL_RCC_USART1_CLK_*、MX_USART1_UART_Init()。建议收口成一处可配置端口宏, 而不是逐处散改。
  2. 新日志口必须设成只发不收(UART_MODE_TX):USART1 控制台之所以要背一整套僵尸通道自愈, 根源就是"RX 悬空 + RX 使能 → ORE 锁存 → HAL 轮询 TX 恒快速失败"。日志口不需要收, 就别再开 RX,否则等于把同一场病搬到新口上。

⚠ TTL 直连没有 DE:主机侧不再有半双工方向控制,DE 极性、建立时间、等 TC 收尾全部不适用。 只有选"USART1 引脚 → 外部 485 模块 → 屏板 A/B"这种接法时才需要处理外部模块的 DE, 此时极性由那个模块决定,不可照抄屏板(屏板的"低=发"是它自己那套收发器的接法)。

⚠ 主机 RX 只需吃下 6 B 召唤帧(不像屏板要吃 4208 B):16 B 缓冲 + 空闲中断断帧就够。 TTL 直连没有自发自收问题(TX/RX 是两根独立线);只有走外部 485 模块时才会回灌。

本节描述屏板固件实际做什么——决定主机侧要下发什么、以及哪些语义必须由产品自己定义。

① 状态指示灯(4 B 位掩码下行)

屏板有 20 路 LED,由主机每帧的 info[0..3] 控制。解码规则(LED_Printf):

leddata = (ledbuf[3]<<24) | (ledbuf[2]<<16) | (ledbuf[1]<<8) | ledbuf[0];  /* 32 位小端 */
LED_POW(LED_ON);                                                           /* ID 0 无条件常亮 */
for (i = 1; i < LED_COUNT; i++)                                            /* LED_COUNT = 20 */
    LED_Set(i, (leddata & (1UL << i)) ? LED_ON : LED_OFF);
  • ID 0 = 电源灯,硬件常亮,不受位掩码控制(leddata 的 bit0 被忽略)。
  • ID 119 一一对应 bit1bit19;bit20~bit31 未使用,填 0。
  • 全部低电平点亮(LED_ON = 低)、推挽输出、内部上拉、高速模式。
  • 只在普通图像帧到达时刷新;LOGO 帧走另一分支,不动 LED。

屏板侧 LED 引脚表(led_config[20],仅备查——主机不直接驱动):

ID 引脚 备注 ID 引脚 ID 引脚 ID 引脚
0 PC8 电源灯,常亮 5 PC11 10 PC7 15 PC12
1 PC9 运行灯 6 PD0 11 PA8 16 PD1
2 PA9 7 PD2 12 PA10 17 PD3
3 PA11 8 PD4 13 PA12 18 PD5
4 PA15 9 PD6 14 PC10 19 PD7

对本产品的含义:§5.8 的主板 6 路 LED(LED1~6)与屏板 20 路指示灯是两套独立输出, 语义不同——主板 LED 表"设备自身状态",屏板指示灯是"操作员面前的状态/告警灯组"。

⚠ 位掩码 → 业务状态的映射表,参考源码里没有。参考的 LCD_LED_Update(ptr, 3200, ledbuf, 4) 只证明"主机侧填这 4 B",填哪几位对应哪个业务状态在未实现的屏板 BSP 里。 因此"哪几号灯表哪个状态"必须由本产品定义(建议按 §5.8 的 6 路语义扩展到 19 路, 并保留 1~2 路作屏板自检/通信状态)。这是本项唯一需要"新设计"而非"照抄"的地方。

② 按键上行

项 屏板侧实测
库 MultiButton,只绑 BTN_SINGLE_CLICK(单击事件)
扫描 5 ms 定时器内 Button_Ticks()
电气 输入模式、无内部上拉/下拉(依赖外部)、低电平有效
引脚 KEY_ENTER=PD12、KEY_UP=PD11、KEY_DOWN=PD10、KEY_LEFT=PD13、KEY_RIGHT=PD8、KEY_ESC=PB15、KEY_RESET=PB3
JTAG PB3 需 __HAL_AFIO_REMAP_SWJ_NOJTAG() 才能当普通 GPIO
回调 任意键按下 → BackLight_ON() + 更新 keyStatus,主循环转交 RS485_Process()

键值枚举(KEY_TYPE,即帧 A 偏移 3 的 key 字节):

值 名称 值 名称
0 KEY_NONE(无键) 5 KEY_ADD
1 KEY_ENTER 6 KEY_DEC
2 KEY_UP 7 KEY_LEFT
3 KEY_DOWN 8 KEY_RIGHT
4 KEY_ESC 9 KEY_RESET
10 KEY_FACTORY

⚠ 两套键号只在 1~8 对齐,9/10 语义不同,必须显式建映射:

语义 屏板 KEY_TYPE(帧 A 的 key) 参考主机 getRs485Key() 物理键号
确认 ENT 1 1
上 UP 2 2
下 DOWN 3 3
取消 ESC 4 4
加 ADD 5 5
减 SUB 6 6
左 LEFT 7 7
右 RIGHT 8 8
9 KEY_RESET(复位键) F1
10 KEY_FACTORY(工厂模式键) F1|ENT 组合

帧 A 的 key 字节只能按屏板枚举解释。主机收到 9/10 时不得按 F1 / F1|ENT 处理。 若产品要求保留 F1/F2 语义,只有两条路:改屏板固件 或 在主机侧加语义映射表——二者选一,须先定。

⚠ key_configs[] 只有 7 项,且与枚举不自洽:表内第 7 项为 {PB3, KEY_RESET}(注释却写"加键"); 枚举有 KEY_ADD(5) / KEY_DEC(6) / KEY_FACTORY(10),但 key_configs[] 没有映射任何 ADD/DEC 物理键。 即实物只有 7 个物理键(上/下/左/右/确认/取消/复位),ADD/DEC/FACTORY 有枚举无入口。 屏板 readme 的按键表列了 8 个键,与代码不符——以 key_configs[] 的 7 项为准。 这直接影响 §5.16.9 第 8 条"补 F1/F2"是否成立:屏板上根本没有 F1/F2 物理键, 网络通道的 8 键表是给远程工具用的;串口通道只可能收到 1/2/3/4/7/8/9 这 7 个值 (5/6/10 有枚举无入口)。

③ 背光

  • 任意键按下 → BackLight_ON()(按键回调里,不在 5 ms 定时器内)。
  • 5 ms 定时器每拍调 BackLight_Close(),超时熄灭(时长在 160160D.C,屏板自管)。
  • LOGO 帧到达时也会 BackLight_ON()。
  • 主机侧不参与背光控制——参考主机的 Lcd_BackLight() / 空闲 120 s 熄灭在主机 BSP里, 而屏板固件自己就管背光,两条路径不能同时启用。本产品按"屏板自管"实现,主机不做(§5.16.9 第 14 条)。

④ LOGO 与 Flash

  • 魔数命中(info[4]==0x89 && info[5]==0x45)→ 按 LOGO 处理: Picture 存入屏板 Flash 0x0803F000(扇区 126),宽高取 info[0..1] / info[2..3](大端), 然后点背光、ClearScreen()、LOGO_Printf()、延时 2 s(4 × delay_ms(500))。
  • 上电时 BMP_Get() 从同一地址读回并显示。
  • LOGO 帧不刷新 LED、不进入常规画面;一帧 LOGO 会永久覆盖屏板上一次的 LOGO。
  • 主机侧要提供"下发 LOGO"的一次性操作(建议放在屏板联调/出厂配置流程,不进常规刷新循环)。

⑤ 屏板自身的健壮性机制

机制 实现 对本产品的影响
CRC 错计数 连续 ≥3 次错 → 计数清零(重初始化串口被注释掉) 错帧静默丢弃,链路不会自愈,只能靠下一次召唤重试
应答超时 200 ms × 连续 5 次 → 强制允许重发 主机长时间不应答不会锁死屏板,恢复后自动续上
系统自复位 sysRunTime > 1 000 000(≈5000 s)→ HAL_NVIC_SystemReset() 每 83 分钟屏板重启一次,约 1 s 空窗
看门狗 5 ms 定时器内 Clear_Watchdog() 主循环卡死 → 屏板复位
DMA 接收 屏板提交记录明写"DMA 接收的问题没有解决" 长帧接收可靠性未经充分验证,台架必须压测

⚠ 5000 s 周期性自复位必须被主机容忍:复位期间屏板约 1 s 不响应召唤。 主机的链路监视不能把这种周期性空窗判成"屏板掉线",更不能联动告警/保护。 判据建议:连续 ≥ 10 s 无任何应答才置"屏板离线"。

待与屏板固件方确认的 5 项(不影响本产品先开工,但验收前必须闭环):

  1. 线上一帧到底是 4208 B(代码实参)还是 3210 B(readme + BMP_LEN)——决定主机发多少字节。
  2. Check_CRC 用缓冲区容量而非实际接收长度,短帧会被误判;是否计划改为传 Size。
  3. 键值 9 / 10 是否要改成 F1 / F1|ENT(对齐参考),还是保持"复位 / 工厂"语义。
  4. key_configs[] 是否要补 ADD / DEC 物理键(当前 7 键,枚举 11 项)。
  5. 屏板 4208 B 接收缓冲与 700 kbaud 在长线(> 50 m)下的误码率实测数据。

5.16.4 链路 B 帧格式(逐字节)

项 规格
传输 TCP 7003;设备为 Server(TcpAddServer + TcpAddConnection(..., EN_NET_MODE_SERVER, RDisp_MsgRecv));目标 IP 填 255.255.255.255 = 接受任意客户端
连接参数 TcpSetConnPara(iTcpNo, 10240, 10240, 0, 30, 5);收发缓冲各 10240 B
建链条件 getnetport() != 1 才建 Server(该函数源码无注释,疑为单网口板件跳过本链路;未验证,勿照抄此条件)
帧结构 [TAG 1B][CMD 1B][LEN_H 1B][LEN_LO 1B][DATA nB][CRC 1B]
TAG 0xAA = 客户端→设备(CN_RDISP_C_TAG);0xBB = 设备→客户端(CN_RDISP_R_TAG)
LEN 数据段长度(不含 4 B 头与 CRC),大端
CRC 数据段逐字节异或(RDisp_CalCrc),不覆盖头与 CRC 自身
最长帧 CN_RDISP_FRAME_LEN_MAX = 9800(数据段上限)
接收定界 逐字节找 0xAA(最多 10240 次防死循环)→ 再收 3 B(CMD+LEN)→ LEN > 10237 视为噪声重新同步 → 再收 LEN+1 B(数据+CRC)→ 返回 LEN+4

接收侧不校验 CRC:RDisp_MsgRecv 只做定界;CRC 只在 RDisp_Proc_LcdMem / RDisp_Proc_SaveKey 内比对,且 INIT / KEEPLIVE 帧根本不校验。这是参考的既有行为, 本产品在全帧校验上更严(见 §5.16.9 第 10 行),不作退让。

5.16.5 命令集与数据段布局

CMD 名称 客户端请求 设备应答 备注
0 KEEPLIVE 空 不应答 源码 return,注释"无 keep alive 报文";仅重置 1 分钟通信计时
1 INIT 空 16 B(见下表) 工具召唤屏幕参数
2 KEY [键值 1B] 空(LEN=0) 键值写入 g_tRemoteKey,byKeyValid = EN_KEY_FLAG_NEW
3 LCDMEM [起始偏移 4B 大端] [起始偏移 4B][显存 nB] 支持断点续传;拒绝语义见 §5.16.6
4 ACK — — 参考 RDisp_Send 中为空分支,未使用
5 NCK — — 同上,未使用
0xFF IDLE — — 内部空闲码,不上线

INIT 应答数据段(16 B,即 RDisp_Form_InitInf 的单色子集):

偏移 长度 字段 取值
0 2 LCD 像素宽(大端) UI_SCREEN_W = 160
2 2 LCD 像素高(大端) UI_SCREEN_H = 160
4 4 显存字节数(大端) UI_FB_SIZE = (160*160)/8 = 3200
8 8 键值表 F1/F2/U/D/L/R/ENT/ESC 0x04/0x80/0x02/0x40/0x10/0x08/0x20/0x01

为什么是 16 B 而不是参考的 29 B:参考的 29 B 里有 13 B 是颜色信息 (1 B 颜色位 CN_RDISP_LCD_TYPE + 12 B RGB 三色 CN_RGB_RED/GREEN/BLUE)。 三处源码证据表明这 13 B 在参考自己的构建里就是死字段:

  1. RemoDispBus.h:46 CN_RDISP_TYPE_MONO = TRUE → CN_RDISP_LCD_TYPE = CN_MODE_GREY_MONO、 CN_RDISP_MEMSIZE = (X>>3)*Y,即链路显存本身就是 1 bpp,不是彩色显存。
  2. RDisp_Form_InitInf 里三个 RGB 值是编译期常量 CN_RGB_RED/GREEN/BLUE, 不是逐帧数据,每次召唤都发同样的 12 B。
  3. RDisp_LcdColor_To_Mono() 对 CN_MODE_GREY_MONO 直接 return TRUE,不做任何转换; 真正干活的 RDisp_Lcd16B_To_Mono()(RGB565 → 单色)挂在 CN_MODE_COLOR_16B 分支, 本构建永不进入,是死代码。

本产品的屏板同样是单色 1 bpp(DTU-LCD 的 ScreenPrintf() 只吃 1 bpp 点阵), 所以这 13 B 既无接收方、也无语义。整段删除,不对齐多色协议:29 − 13 = 16 B。 这不是"少实现"——参考能力全集里的多色分支连参考自己都没启用(§2.4.1)。

键值是位掩码,不是枚举——可组合下发:CN_KEY_F1|CN_KEY_ENT = 0x24(Key.c 物理键号 10 即此值)。 CN_KEY_ADD=0x82、CN_KEY_SUB=0x84 只在 RS-485 通道使用,不进 7003 键值表。

5.16.6 显存上送的续传与拒绝语义

RDisp_Form_LcdMem / RDisp_Proc_LcdMem 的完整规则:

  1. 分片:dwSendBase + 9800 > 3200 成立 → 本帧发 3200 - dwSendBase 字节;否则发 9800 B。 因 MEMSIZE = 3200 < 9800,实际恒为单帧 3204 B(4 B 偏移 + 3200 B 位图); 分片逻辑为"显存变大"预留,当前不触发。
  2. 推进:发完后 dwSendBase += dwLen;若 >= MEMSIZE → bNeedFlash = TRUE、dwSendBase = 0。
  3. 拒绝:召唤时若 bNeedFlash 为真(上一帧刚发完、新图还没拷贝)→ 返回 -1,且把 dwSendBase 清 0,不应答。含义是"一帧图像只允许被完整上送一次",客户端要下一帧 必须等主机完成下一次刷新。
  4. 越界:dwSendBase >= MEMSIZE → 返回 -2,不应答。
  5. 成功:返回 1,置 wSendCode = LCDMEM,由 RDisp_Send 组帧发出。
  6. 刷新来源:RDisp_Main 每轮检查 bNeedFlash,为真则 memcpy(byLcdMemory, __Lcd_Pub_GetScreenAddr(0), 3200) → RDisp_LcdColor_To_Mono() 转单色 → 清 bNeedFlash、dwSendBase = 0。

RDisp_LcdColor_To_Mono() 这一步本产品不需要(参考自己也不走):该函数按 CN_LCD_TYPE 分派, 而本构建 CN_LCD_TYPE = CN_MODE_GREY_MONO → 命中第一分支直接 return TRUE,不做任何转换; 只有 CN_MODE_COLOR_16B 才调 RDisp_Lcd16B_To_Mono() 做 RGB565 → 单色,那条路是死代码。 本产品的 g_ui_fbuf 本来就是 1 bpp 单色(LVGL 单色渲染,UI_FB_SIZE = 3200),拷贝即可送, 没有"颜色 → 单色"的转换环节。这是"不对齐多色协议"带来的简化之一。

为什么必须有 bNeedFlash 握手:显存由显示任务异步改写,若允许客户端随时按偏移拉取, 跨两次刷新的位图会在客户端拼成撕裂帧。参考用"整帧一次性 + 拒绝重拉"消除这个窗口, 本产品当前无此保护(§5.16.9 第 4 行)。

5.16.7 按键注入与状态机

项 规格
存储 tagRKeyCtrl g_tRemoteKey { byUsrFlg, byKeyValid, byKeyValue, bUseRkey }
有效性 EN_KEY_FLAG_NULL=0(无新键)/ EN_KEY_FLAG_NEW=1(有新键)/ EN_KEY_FLAG_SAM=2(采样中)
注入 收 KEY 帧 → byKeyValue = DATA[0]、byKeyValid = EN_KEY_FLAG_NEW
消费 Key_Read() 读到 NEW 后立即清 NULL(边沿消费,不重复触发)
合并顺序 有本地键板时:先取远程 g_tRemoteKey,再被本地 g_tKey 覆盖——两键同时挂起时本地优先
连接联动 TCP 连上 → bUseRkey = TRUE;断开 → FALSE + wSendCode = IDLE + dwSendBase = 0
背光 Key_HaveNewKey() 每次调用都执行 MenuProc_Have_Key()(无新键也点背光),再返回是否有新键

5.16.8 时序、超时与重试

定时器 周期 作用
tTimerLCD 500 ms 参考主机侧串口屏板通道的周期兜底节拍(WriteScreenByByte)。
⚠ 本产品不照抄:屏板固件自己按 275 ms 主动召唤(§5.16.2),主机只需"来一帧答一帧",无需自带节拍
tTimerComBrk 1 分钟 通信中断判定;每收到任一帧、每次发送成功都重置
tTimerAbandon 200 ms 发送未完成时的放弃窗口

发送状态机(RDisp_Send):

  1. TcpGetSendState(iTcpNo) <= 0 → 直接返回(链路未建或芯片发送忙),不组帧。
  2. wSendFlag == CN_RDISP_SEND_BUSY → 重发上次缓冲;成功 → IDLE + 重置 tTimerComBrk; 失败且 tTimerAbandon 未到 → 返回;已到 → IDLE 后重新组帧(宁可丢帧不阻塞)。
  3. 组帧:byCRC = XOR(DATA);填 TAG=0xBB、CMD、LEN;CRC 写在 DATA 之后。
  4. TcpSend 返回值 必须等于 wMsgLen 才算成功(部分发送视为失败,进 BUSY 重试)。

显存刷新互斥:g_tShareSetBuf.dwReserSet[3] 三态——0xaa = 被其他模块占用(本轮跳过)、 0x55 = 显示已刷新(供远程工具判断)、0 = 空闲。取用前查 0xaa、用后清 0。

任务模型:taskSpawn("tRemoDisp%d", 111, 0x0008, 0x35000, RDisp_Main, ...) ——prio 111、栈 0x35000(212 KB,VxWorks 字节语义)、主循环 taskDelay(1), 每轮 DogTask_InfoUpdate(EN_TASK_DSP, ...) 喂狗,退出时 DogTask_InfoError 报异常。

5.16.9 与参考的差异(本产品当前实现)

# 项 参考 本产品 处置
1 INIT 应答长度 29 B(= 宽高 4 + 颜色位 1 + 显存 4 + RGB 三色 12 + 键值表 8) 8 B(宽 2 + 高 2 + 帧字节 4) 补 8 B 键值表 → 16 B;颜色 13 B 不对齐(单色屏无接收方,§5.16.5)
2 KEEPLIVE 应答 不应答 回显空 KEEPLIVE 帧 改为不应答(或留兼容开关)
3 LCDMEM 非 0 偏移 支持续传(从 dwSendBase 起) 仅支持偏移 0,非 0 静默忽略 补续传
4 召唤拒绝语义 bNeedFlash 为真 → -1 不发 无 补(防撕裂帧)
5 越界语义 >= 3200 → -2 不发 无 补
6 链路监视 tTimerComBrk 1 分钟 无 补(掉线判定 / 重连驱动)
7 发送重试 BUSY + 200 ms 放弃 依赖 net_send 阻塞模型 评估是否需独立实现
8 键值集(网络通道) 8 键(含 F1 / F2) 6 键(无 F1 / F2) 补 F1 / F2;仅网络通道——屏板无 F1/F2 物理键(§5.16.3 ②)
9 任务模型 独立任务 prio 111 / 栈 212 KB uiTask 10 ms 轮询(prio BelowNormal / 16 KB) 形态差异,不追平(X1 / X2)
10 接收侧 CRC 仅 LCDMEM / KEY 校验 全帧校验 本产品更严,保留
11 串口屏板通道 有:显存 3200 B + 状态灯 4 B 下行、键号上行,变化驱动 + 500 ms 兜底 无(只有 7003 网络通道) 新建,按 §5.16.2 逐字节实现,见 §9.13
12 双出口并发 同一份显存同时喂串口与网络,互不阻塞 只有网络一个出口 随第 11 条一并实现
13 屏板状态指示灯 20 路(ID 0 电源常亮 + ID 1~19 位掩码),4 B 小端随每帧下发 无;主板另有 6 路 GPIO LED(LED1~6) 新建;"位 → 业务状态"映射须自定(参考源码无此表,§5.16.3 ①)
14 背光 / 对比度 主机 BSP 有 Lcd_BackLight / Lcd_SetContrast + 空闲 120 s 熄灭 无 不做——屏板固件自管背光,两条路径不能同时启用

来自屏板固件的新增约束(参考主机侧源码里看不出来,但对实现是硬约束):

  • 角色反转:屏板是 Modbus 主站(主动召唤),主机是从站 0x01;与网络通道"客户端召唤"方向相反。
  • 帧长 4208 B(有效载荷 3208 B + 998 B 填充 + 2 B CRC),不是 readme 写的 3208 B(§5.16.2)。
  • 700000 8N1,主机侧走 USART1 TTL 直连(无 DE);若改走外部 485 模块,DE 极性由该模块决定,不可照抄屏板。
  • 屏板每 ≈5000 s 自复位一次,约 1 s 空窗;主机链路监视须容忍(建议连续 ≥10 s 无应答才判离线)。
  • 屏板只有 7 个物理键,键值 9/10 是"复位 / 工厂",与参考主机的 F1 / F1|ENT 语义不同。
  • 单色:屏板是 1 bpp 单色面板,参考的 13 B 颜色信息(颜色位 + RGB 三色)无接收方,不对齐。

第 1 / 3 / 4 / 5 / 8 条是客户端可见的报文口径差异——现有 DTU-RemoteLCD 按 8 B INIT 实现, 补到 16 B 后客户端必须同步改,否则会错位解析。这是本项复刻唯一的跨端风险点。 注意:16 B 与参考的 29 B 不是同一口径——13 B 颜色字段被有意删掉, 客户端不得按 29 B 预留缓冲再截取前 16 B 使用(从偏移 4 起含义即不同: 参考偏移 4 是颜色位,本产品偏移 4 是显存大小的高字节)。

第 11 / 12 / 13 条是整条链路缺失,不是报文细节差异——它决定了本产品能否脱离 PC 独立带屏运行。

第 14 条从"待决定"改为已决定不做:屏板固件自己管背光与超时熄灭,主机再插一手会打架。

5.16.10 复刻完成判据

  1. 任意 TCP 客户端连 7003 → 发 INIT → 收到 16 B(宽 2 + 高 2 + 显存 4 + 8 键值表), 字段值与 §5.16.5 逐字节一致;不得出现颜色位或 RGB 字段。
  2. 发 LCDMEM(0) → 收到 3204 B;再次发 LCDMEM(0)(新图未就绪)→ 无应答(对应参考 -1)。
  3. 发 LCDMEM(3200) → 无应答(对应参考 -2)。注:该分支在 bNeedFlash 为真时先被 -1 截住, 只能在"新图已拷贝、尚未上送"的窗口内触发,属边角路径,判据以"无应答且不越界读"为准。
  4. 发 KEEPLIVE → 无应答,且链路 1 分钟内不被本端主动断开。
  5. 发 KEY(0x24) → 收到空 KEY 应答,界面表现为 F1+ENT 组合键。
  6. 断开 TCP 60 s 以上 → 设备侧可观测到"通信中断"(日志 / 状态位),重连后自动恢复推流。
  7. 8 键逐个下发 → 界面动作与按键表一致;组合键 F1|ENT 生效。

串口屏板通道(与上面 7 条并列,待建后验收):

  1. 主机上电后,屏板按 275 ms 节拍发帧 A(6 B,形如 01 03 01 xx CRC_H CRC_L); 主机每帧在 ≤200 ms 内回帧 B(4208 B,CRC 覆盖 [0, 4205]),屏板连续 10 分钟无超时。
  2. 帧 B 前 3200 B 与主机 g_ui_fbuf 逐字节一致(160 行 × 20 B,1 bpp,MSB 在前,bit = 1 → 白)。
  3. 屏板 7 个物理键逐个按下 → 主机收到的 key 依次为 1/2/3/4/7/8/9 (ENTER / UP / DOWN / ESC / LEFT / RIGHT / RESET),界面动作与 §8.2 菜单树一致; 0 表示无键、不产生事件。
  4. 状态灯下行:主机把 19 路业务状态映射为位掩码 → 屏板 LED 1~19 的亮灭与掩码逐位一致; LED 0 恒亮、不受掩码控制(bit0 置位不改变任何灯)。
  5. 双通道并发:同一时刻 7003 客户端在拉帧、屏板在召唤,两侧画面一致,互不丢帧、不串帧; 串口侧 4208 B 发送阻塞不得导致 7003 侧超时(反之亦然)。
  6. 屏板自复位容忍:屏板跑满 ≈5000 s 触发自复位,主机不误判"屏板离线"(无告警、不触发保护), 约 1 s 后自动续上。
  7. 拔掉屏板 → 7003 侧不受影响;插回后自动恢复,无需复位主机。
  8. LOGO 下发:下发一帧 LOGO(info[4..5] = 0x89 0x45)→ 屏板写 Flash 0x0803F000 并显示 2 s; 断电重启后仍显示该 LOGO,且屏板 LED 状态未被这帧改动。

6. 接口规范

6.1 网络服务端口

服务 协议 / 端口 用途 核对方法
FTP TCP 21 文件上传/下载(根目录 /,NAND 存储) 登录后任意 FTP 客户端列目录/读写(鉴权见 §7.6)
墙钟对时 TCP 8888 PC 主动推送时间到设备 对时后核对设备时间 / 日志时间戳
远程显示(RemoDispBus) TCP 7003 远端看图(160×160 1bpp)+ 远端导航按键 DTU-RemoteLCD 或任意 TCP 客户端连 7003 收帧
IEC 60870-5-104 上行 TCP 2404 被控站接入:遥测/遥信上送、总召、遥控/定值下发(点表见 §6.8) 任意 104 主站连 2404,STARTDT+总召往返(→ docs/子系统设计/IEC104上行设计说明.md)

现场组网要求:设备与客户端同网段(默认 .100/24、网关 .1);跨网段先改 IP 再上线。

6.2 RemoDispBus 协议

RemoDispBus 帧格式

口径:本节按参考源码(HMI/RemoeDisp/RemoDispBus.c)给线上格式;本产品当前实现与该口径的 逐项差异、以及为什么会有差异,见 §5.16.9。以参考为准,差异项按 §9.13 排期收敛。

本节只讲网络通道(TCP 7003)。串口屏板通道不走本协议——它是 RS-485 上的 Modbus RTU 风格裸二进制帧(6 B 召唤 + 4208 B 图像应答,CRC-16/MODBUS 高字节在前), 帧格式已按屏板源码逐字节定版,见 §5.16.2。 两条通道共用同一份显存,但帧格式、校验、时序、主从方向全都不同,不能共用组帧代码。

项目 内容
传输 TCP,端口 7003;设备为 Server,目标 IP 255.255.255.255 = 接受任意客户端
帧格式 [TAG(1)][CMD(1)][LEN_H(1)][LEN_LO(1)][DATA(n)][CRC(1)]
方向标识 TAG 0xAA = 客户端→服务端,0xBB = 服务端→客户端
校验 CRC = 数据段逐字节异或(低 8 位,不含 TAG/CMD/LEN,也不含 CRC 自身)
字节序 多字节字段大端(网络字节序)
最短帧 5 字节(LEN=0)
最长帧 数据段 ≤ 9800 B(CN_RDISP_FRAME_LEN_MAX)
缓冲 收发各 10240 B(CN_RDISP_BUF_RECV/SEND)
接收方式 逐字节有限状态机(TAG 定界 + 长度定长 + CRC 校验,自动重同步)

命令集:

CMD 名称 请求数据段 应答数据段
0 KEEPLIVE 无 无应答(仅重置 1 分钟通信计时)
1 INIT 无 [宽u16][高u16][显存u32][8 键值](16 B;参考的 29 B 含 13 B 颜色信息,本产品不对齐)
2 KEY [按键码u8] 无(空帧确认,LEN=0)
3 LCDMEM [起始偏移u32] [偏移u32][1bpp位图 3200B](3204 B);偏移非 0 时续传,bNeedFlash 期间不应答

INIT 字段明细与按键码表:见 §5.16.5(含 16 B 逐字段偏移)。

单色口径:本产品只实现单色分支。参考 INIT 里的颜色位 CN_RDISP_LCD_TYPE 与 CN_RGB_RED/GREEN/BLUE(共 13 B)整段删除,不做多色对齐——屏板是 1 bpp 单色面板, 没有彩色/灰度的接收方;参考侧 RDisp_LcdColor_To_Mono() 这道"彩色转单色"也因此不存在 (本产品显存本来就是单色)。

按键码:F1=0x04 / F2=0x80 / UP=0x02 / DOWN=0x40 / LEFT=0x10 / RIGHT=0x08 / ENTER=0x20 / ESC=0x01;位掩码可组合(如 F1|ENTER = 0x24)。

位图格式:1bpp 单色,MSB 优先(bit7 = 该字节第一个像素);像素 (x,y) → byte_i=(y*W+x)/8、bit_i=7-(x%8);位值 1=白、0=黑;160×160 → 3200 B。

关键常量:UI_NET_SINK_PORT=7003、RM_MAX_RX_PAYLOAD=256、RM_RX_BUF=64、帧重组缓冲 261 B (本产品侧常量;参考侧对应 CN_RDISP_TCP_PORT / CN_RDISP_FRAME_LEN_MAX / CN_RDISP_MEMSIZE)。

详见 docs/UI设计/RemoDispBus协议与接收设计说明.md。MCU 与模拟器共用同一份 ui_net_sink.c。

6.3 对时协议

  • 载体:TCP :8888,PC 主动推送,设备接收并写 RTC。
  • 行为:timeSyncTask 监听 → 收包 → 写回 RTC;30 s 无包则掉线重建监听(约 4 s)。
  • 待补充:推送报文的具体帧格式(当前实现细节见 App/sync/time_sync.c 与 test/host/time_sync_server.py)。

6.4 FTP 服务

  • 实现:lftpd(轻量 FTP 服务器),root = /(FatFS 卷根),端口 21,单客户端。
  • 支持命令:登录 / TYPE I / PASV / STOR / RETR / LIST / DELE / QUIT。
  • 鉴权(已鉴权 · 2026-10-11):口令登录([ftp] 段 user / pwd_hash = SHA-256(user‖password) / write);未登录仅 USER/PASS/QUIT/FEAT/SYST/NOOP 放行,其余一律 530;write=0 可禁 STOR/DELE;连续 5 次失败锁 60 s;出厂默认 admin/admin,默认口令在用有启动告警。口径详见 docs/子系统设计/网络配置说明.md §3.4。
  • 启动门:ftpTask 必须等 NET_READY 且 STORAGE_READY(两位 NoClear)才 lftpd_start。
  • 注意:同一时刻只服务 1 个会话,旧会话异常断开后约 30 s 恢复监听;测试脚本须内置连接重试,不要用裸 TCP 工具探测 21 端口。
  • 实测:128 KB 上传下载逐字节一致(约 49/60 KB/s)。

6.5 配置文件格式

位置:MCU /config.ini(卷根);模拟器 sim_config.ini(工作目录)。

语法:key=value(key [a-z0-9_]+ 大小写敏感);[section];;/# 注释行;UTF-8(容忍 BOM);CRLF(设备写出)/ LF 均接受;行长 >127 字符该行无效;文件 >4096 B 视为损坏。

出厂模板(首启自动生成):

; DTU 通用配置文件
[network]
; IP 地址
ip=192.168.1.100
; 子网掩码
mask=255.255.255.0
; 默认网关
gateway=192.168.1.1
; MAC 地址 (全零 = 使用芯片内置 MAC)
mac=00:00:00:00:00:00

值类型:IP4(a.b.c.d)、MAC(aa:bb:cc:dd:ee:ff)、UINT(十进制,兼容 0x)、STR(≤31 字符)。

工厂默认:IP 192.168.1.100 / 掩码 255.255.255.0 / 网关 192.168.1.1 / MAC 全零(= 芯片内置)。

MAC 全零是"使用芯片内置 MAC"的哨兵,不是"MAC 为 0"。恢复出厂:FTP DELE /config.ini → 下次上电重新生成模板。

6.6 调试串口

项 值
端口 USART1(PA9 TX / PA10 RX),115200 8N1
用途 printf 日志 + @test 采集通道
配置源 .serialtest/config.json(单一配置源)
工具 仓库内置 Python 串口助手(.dsh/skills/serial-assistant/,常驻 daemon + CLI)

启动标记(@test 判据):

  • Required:App init OK / Network Init / net init: OK / PHY: 100M FULL
  • Forbidden:FAIL / ERROR / HardFault / [ERR]

6.7 对外 API 一览

模块 关键 API 说明
net_socket socket/bind/listen/accept/recv/send/close + select/poll BSD Socket 抽象
net_cfg net_cfg_load/save/get/set/get_mac/set_active_mac/fmt_ipv4/set_apply_cb/request_apply 网络配置(签名与语义稳定)
cfg_file cfg_file_register/load/save/poll/section_data 配置引擎核心(双端共享)
sys_clock sys_clock_init/get/get_str/get_time 墙钟时间服务
sys_log syslog_post(RUN / SELFTEST) 定长记录引擎
ui_net_sink ui_net_sink_start(port) / ui_net_sink_poll() 远程显示服务端
ui_content_page ui_content_page_open/close/invalidate/is_open 内容页框架
task_watchdog task_wd_beat/poll/start + 观测接口 看门狗判定状态机
sys_events sys_evtHandle + 9 个事件位 启动屏障 + 落盘请求
adc_input adc_input_init/poll/raw/desc 语义取数与有效性语义取数(8 电气量 + 温度)
adc_health adc_health_init/report/flags 语义取数与有效性采样有效性判定(纯逻辑)
adc_cal adc_cal_init/apply/flags/set/b_codes/prot_blocked 标定折算 + 三态可用性
phasor phasor_init/run/read 全周傅氏相量全周傅氏相量(双区)
freq freq_run/get/valid 测频与遥测快照测频(自适应窗)
meas meas_tick/snap 测频与遥测快照(200 ms,双区)
prot_set prot_set_init/load/selfcheck/set_sealed/get/locked 保护判据定值模型(原子写 + 封存)
prot_elm prot_elm_init/run/eval/state/request_reset 保护判据元件框架(9 实例)
run_par run_par_init/get/set_104_write/dirty_peek 运行参数段(死区 + 系数代理)
soe_rec / soe_store soe_rec_encode/decode · soe_store_post/drain SOE 编解码 + 落盘投递
iec104 iec104_link_* / iec104_pts_* / iec104_serv_* 104 链路 / 点表 / 板端胶水

6.8 IEC 60870-5-104 点表摘要

权威口径:验收以《检测平台配电终端送检要求(点表)》为准;本表是 V0.1 实现摘要, 逐点细节与未实现项见 docs/子系统设计/IEC104上行设计说明.md §3。 段基址与参考产品逐字对齐(8 段全表见 §2.5.3):遥信 0x0001、保护 0x1001、遥测 0x4001、 参数 0x5001、遥控 0x6001、设定 0x6201、电能 0x6401、步位置 0x6601。 点表规模是当前最大差距:本产品 9 遥测 / 33 遥信 / 2 遥控,参考产品 31 遥测 / 138 开入 / 31 开出。

遥测(0x4001 段起,短浮点,系数 1)

IOA 点 来源 V0.1
4011 / 4014 / 4015 1Ua / 1U0 / 1Ia 遥测快照(TPAFE 侧,有效) ✅
4012 / 4013 / 4016~4018 1Ub/1Uc/1Ib/1Ic/1I0 快照(STM32 侧,削顶) ❌ 恒 IV
4019~401C 1P/1Q/1S/1Pf 需跨转换器同刻 ❌ 恒 IV(V0.2)
401D 1f 频率 测频结果 ✅(未收敛则 IV)
4010 / 401E / 401F UBA 后备电源 / V1/V2 直流 无硬件通道 ❌ 未入表(X3)

与参考的差额:参考 g_tYcIndexTab 共 31 点——双回线各三相电流/电压(12)、双回线各三组 线电压(6)、双回零序电流/电压(3)、频率(1)、直流 2 路(2)、有功/无功/视在/功率因数 单相 3 + 三相 1(4)、电度 8 种另列。本产品 9 点,缺的是第二回线、线电压、零序双回与 功率四量——前者等通道(X4),后两者等标定后的功率运算。

遥信(0x0001 段起,V0.1 定义 33 点):1~4 开关位置(双点,恒 IV)、5~14 预留(IV)、 15 故障总、16~18 过流 Ⅰ/Ⅱ/Ⅲ 段、19~20 零序过流 Ⅰ/Ⅱ(IV)、21~22 接地故障/重载(IV)、 23 过载、24~30 外部遥信(RS-485 冻结 → IV)、31 保护闭锁、32~33 预留(IV)。 有效位图 YX_VALID_MASK = YX15~18 / 23 / 31(6 点)。

与参考的差额:参考 g_tInputModelTab 共 138 点(开关合/分位、未储能、就地远方、接地位置、 隔离位置、停用重合闸、保护投入、检修压板、远方信号、手合手分、电源输入、活化状态、电池欠压…), 另 g_tOutputModelTab 31 点开出(保跳/保合/遥分/遥合/遥控备用/电池活化/电机保护/闭锁…)。 两者都需要一次设备接口硬件(X4),属 §9.1 阻塞型。

遥控(0x6001 段起,双点两段式):YK1~4 开关(否定确认)、YK11 信号复归、YK12 遥控软压板、 YK13 电池活化(否定)、YK14 解除闭锁(否定)。

定值与运行参数:保护定值地址 = prot_set.comm_addr(基址 0x8820,过压/欠压沿用告警段 0x8027~0x802A);运行参数段 0x8030~0x8038(死区 9 点)/ 0x8040~0x8047(k 覆盖 8 路)/ 0x8048~0x804F(b 覆盖 8 路),共 25 项。 逐项地址为本仓自定,送检点表到位后以送检为准替换常量段。

与参考的差额:参考 104 定值映射 107 项占 0x8820~0x8891(8 个空洞), 底层定值表 249 项 / 23 单元。本产品 40 项,缺的是重合闸(16)、电压时间型自愈(17)、 同期(13)、看门狗(63)、遥测越限(10)等整单元(§2.5.4)。

链路参数:k=12 / w=8 / t1=15 s / t2=10 s / t3=20 s;IOA 3 字节、公共地址 2 字节、传送原因 2 字节; 公共地址与端口可配([comm] 段,工厂默认 1 / 2404,改后需重启生效)。


7. 非功能需求

7.1 可靠性

需求 要求 落地
自恢复 任务死锁/饿死/断言死循环 → 硬件复位 IWDG + 心跳位图(§5.7)
掉电不丢配置 配置原子写(旧档迁移已取消,2026-10-10) tmp+rename;旧 /cfg/netcfg.bin 不读、不删、不迁移
错误可追溯 错误码分级/透传/留痕,不吞不猜 错误码通道四要素(分类/透传/分级/留痕)
存储自愈 卷损坏可探针/自愈;丢弃可观测 卷健康探针 + 丢弃计数 + TX 僵尸通道自愈
不误杀 正常长耗时窗口不触发复位 启动段不喂狗 + 心跳切片 + 白名单

错误码通道四要素(CH395F 范式,后续任何驱动/子系统建立错误通道时应沿用): ① 分类(超时/真故障/参数错)② 透传(逐层上报,禁 (void)ret)③ 分级(可恢复重试/不可恢复上报) ④ 留痕(不可恢复写 syslog selftest,可恢复计数并 UI/日志可见)。 纪律:自愈逻辑严禁把"名字/参数类错误码"归入"卷损坏触发集"。

7.2 性能指标

指标 基线值 来源
M3 压力档帧周期 med 60.1 / p95 66.4 / max 69.3 ms(零尖峰) docs/测试说明/链路延迟测试说明.md
队列响应性(挂起客户端) 92.5 ms(pending 一期) test/host/e02_probe.py
FTP 传输速率 约 49 / 60 KB/s(上传/下载) 128 KB 实测
网络重建生效 2~5 s(含等链路 ≤3 s) 配置设计
UI 刷新 10 ms 循环 ui_task_func
IWDG 停喂到复位 ≤2.5 s IWDG 设计
采样节拍 1000 Hz(每 10 s 帧号 +10000,零丢帧) 台架 @test
单拍采集消费 ≤10 µs(DMA 搬运后实测 8 µs) adc_task 实测
相量刷新 1 ms(每拍整窗重算 5 实例) phasor_run
遥测快照周期 200 ms(经过时间分频) meas_tick
测频精度 45~55 Hz 最坏 0.0101 Hz 主机侧扫频用例
保护判据节拍 20 ms(延时精度由 now_ms 差值保证) protectTask
动作到 104 上送 ≤120 ms(判据拍 + COV + 服务周期) 台架主站往返

7.3 内存与资源预算

权威来源:.map 受管快照(docs/内存管理/RAM使用分析与优化方案.md §2.1,由 scripts/check_mem_numbers.py --write 生成)+ 2026-10-22 栈预算快照 (docs/内存管理/data/stack_report_20261022.md)。本节数值随代码演进会过期,提交前以受管快照为准。

静态区(产品构建,2026-10-24 .map):

区域 用量 容量 占比
Flash ER_IROM1 261,928 B 1024 KB 25.0%
ROM 合计 263,500 B 1024 KB 25.1%
RW_IRAM1 81,072 B 131,072 B 61.9%
RW_CCM 57,376 B 65,280 B 87.9%

运行时栈预算(9 任务,静态最坏链 × 真机水位取更坏者):

任务 配置 静态最坏链 真机峰值 余量 判定
defaultTask 5120 B 3024 B 2152 B 40% ✅
netTask 3840 B 1912 B 1116 B 50% ✅
ftpTask 4096 B 1456 B 740 B 64% ✅
uiTask 16384 B 1336 B 4052 B 75% ✅
testTask 8192 B 736 B — 91% ✅
timeSyncTask 2560 B 1264 B 616 B 50% ✅
adcTask 2560 B 1320 B 952 B 48% ✅
iec104Task 2560 B 1456 B 580 B 43% ✅
protectTask 2048 B 872 B 828 B 57% ✅

定栈规则:改栈或加大栈内局部变量前后必须重跑 scripts/stack_report.py (Keil 静态调用图 × 串口 [STACK] 水位,判定取两者更坏者;余量须 ≥ max(1024 B ISR, 30%))。 LVGL 内存池 16 KB(静态占用,2026-10-15 由 40 KB 收缩);FreeRTOS 堆 56 KB(CCM,水位 87.9% < 92% 门禁)。 卡点已从主 SRAM 移到 CCM(余 ~7.9 KB)——再加任务或抬栈前先看 docs/内存管理/RAM使用分析与优化方案.md §4。

7.4 可维护性(测试与门禁)

测试分层:

层 内容 运行位置
静态门禁 pre-commit 钩子族:格式 / 编码 / 静态分析 / 文档链接 / 体积 / 生成物新鲜度 / 编号 本地 / CI
主机侧纯逻辑单测 MSVC 离线编译真实源码 本地 / CI
板端测试套件 板端套件(testTask 串口 [PASS]/[FAIL] 汇总) 本地(需真机 + 串口)
主机侧回归 模拟器像素 / 池水位回归 + 真机 @test 闭环(含探针) 本地(模拟器免硬件;@test 需真机 + ST-LINK)

构建 / 测试命令:

# 构建(@build):0 错 0 警
& '.venv\Scripts\python.exe' .dsh/skills/keil-build/scripts/keil_build.py   # 退出码 0=PASS / 1=构建失败 / 2=环境错误
# 自动化测试(@test):串口采集 → 烧录 → 日志校验
& '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/run_boot_test.py   # 0=PASS / 1=FAIL / 2=采集或烧录错误 / 3=用法错误
# 全库门禁
pre-commit run --all-files

pre-commit 门禁族(钩子数量随套件增长,以 .pre-commit-config.yaml 为准):

族 代表钩子 作用
格式 / 仓库卫生 trailing-whitespace、end-of-file-fixer、check-added-large-files、check-merge-conflict、check-yaml、gitlint 行尾与空白、超大文件、冲突标记、提交信息规范
编码与源码纪律 no-mojibake、coding-standard、nested-comment、bom-guard、layer-deps、bsp-err 乱码、命名与常量位置、注释嵌套、BOM 漂移、分层依赖、BSP 错误码契约
静态分析 cppcheck、test-cppcheck 主机侧与测试代码静态检查
文档一致性 doc-links、id-check、task-table、mem-numbers、mem-budget、size-gate 链接与章节引用、编号、任务表、内存数字、体积门禁
生成物新鲜度 generated-fresh、font-charset、lv-conf-sync、ui-golden、setview-check、uinav-selftest 菜单/字体/像素黄金等生成物与源一致
主机侧单测 watchdog / sys-clock / cfg-file / phasor / adc-input / adc-health / adc-cal / meas / freq / prot-set / prot-elm / run-par / iec104 / soe / nand-port / ui-data 等 *-unit-test MSVC 离线编译真实源码跑断言
结构与注册 registration-check、test-suite-switch、cubemx-survival 双端注册、套件互斥、CubeMX 保护区审计

受管事实源(禁止手改,由脚本生成):

  • 任务表(README.md / AGENTS.md)← scripts/gen_task_table.py
  • 内存/Flash 快照 ← scripts/check_mem_numbers.py
  • 菜单表 ← tools/menu_gen/gen_menu.py
  • 中文字体 ← tools/font_gen/make_font.py

7.5 可移植性(双端)

项 MCU 模拟器
构建 Keil MDK-ARM v5(ARMCC) CMake + SDL2 + MSVC
共用源码 Drivers/BSP/UI/*、Drivers/BSP/NETCFG/net_cfg.c、App/cfg/cfg_file.c 同左
平台后端 *_mcu.c(CH395F/FatFS) *_sim.c(Winsock/宿主文件)
验证 @build 0/0 → @test 串口闭环 check_menu_rows.py + check_content_pages.py(像素黄金参考)

新源文件必须双端注册(Keil .uvprojx + simulator/CMakeLists.txt),否则不参与编译。

7.6 安全与权限

项 现状
FTP 鉴权 已鉴权(2026-10-11):口令登录([ftp] 段存 SHA-256 摘要,不存明文)+ 连续 5 次失败锁 60 s + write=0 可选只读;出厂默认 admin/admin,默认口令在用有启动告警。边界:FTP 明文传口令,挡未授权访问、不挡网络嗅探(详见 docs/子系统设计/网络配置说明.md §3.4)
UI 菜单权限 受保护叶子(行尾 #P)先经密码页;密码仅编译期写入(查看 000 / 修改 123),不落 Flash、无运行期设置页
远程显示 无鉴权,单连接;现场同网段部署
104 上行 无应用层鉴权(标准 104 本身不带认证):安全边界 = 现场同网段部署 + 单连接语义 + 首到优先。主站 IP 白名单不实现(单 socket 上"拒绝"= close + 重听,可被端口扫描打成 SPI 风暴,且配错即锁死真主站;属协议语义决定,非范围裁剪,见 §9 卷首)→ 需冗余/白名单时随 net 层立项
配置面 配置与定值只能经 FTP(需口令)或 104(同网段)改写;UI 侧修改需修改密码。本地无串口配置命令通道

8. UI 规格

8.1 屏幕与渲染

项 值
屏幕尺寸 160 × 160 px
色深 1bpp 单色(MSB 优先),帧缓冲 3200 B;无灰度、无彩色——参考与本产品的链路都是单色,7003 INIT 的颜色字段已删(§5.16.5)
渲染 LVGL 离屏渲染到 g_ui_fbuf;MCU 无物理屏,经**串口屏板通道(主)+ TCP 7003(镜像)**双出口送出
内存池 LV_MEM_SIZE = 16 KB(2026-10-15 由 40 KB 收缩,实测峰值占 40%)
主题 dark mono(单色深色)
刷新 uiTask 10 ms 循环
绘制缓冲 I1 draw buffer 需 +8 B palette 头

8.2 菜单树(42 节点)

级联框总览

规模:菜单节点 9 个(含根)+ 叶子节点 33 个 = 42 节点;最大深度 4 级(L0~L3)。 绑定现状(2026-10-28 实测):已绑内容页 28 叶 / 未绑 5 叶(页面注册表 UI_PAGE_MAP_COUNT = 28, 与已绑叶数一致);未绑 5 叶 = 无开入硬件 3 + 手动录波 1 + SNTP 1(取舍与重开条件见 docs/任务规划/UI补齐.md §5);原「当前执行 6 项」(记录 5 页 + 运行报告)已于 2026-10-28 落地绑页。

根页(主界面)7 个一级条目:装置信息 / 实时数据 / 参数定值 / 三遥设置 / 装置维护 / 通讯参数 / 记录查询。

完整层级树:

主界面 (L0)
├─ 装置信息                          [叶子]
├─ 实时数据 ▶                        [菜单]
│   ├─ 交流量  ├─ 直流量  └─ 遥信量
├─ 参数定值 ▶
│   ├─ 整定 ▶(参数 / 定值 / 控制字 / 软压板)
│   └─ 查看 ▶(参数 / 定值 / 控制字 / 软压板)
├─ 三遥设置 ▶(遥测死区 / 遥测系数 / 遥信类型 / 遥信防抖 / 双点遥信)
├─ 装置维护 ▶(时钟设置 / 强制复归 / 手动录波 / 清除记录)
├─ 通讯参数 ▶(通讯设置 / 网口设置 / SNTP设置)
└─ 记录查询 ▶(SOE记录 / 事故记录 / 操作记录 / 保护告警 / 保护启动 /
              遥控记录 / 自检记录 / 运行记录 / 运行报告)

三层代码架构:数据层 ui_menu_tab(生成物,g_menu_tab[42] 扁平父子索引表,≈0.7 KB Flash)

  • 逻辑层 ui_menu(唯一 17 B 导航状态)+ 显示层 ui_menu_view(持全部 LVGL 对象,零导航状态)。

导航模型:树形逐级进入——ENTER/→ 进入子页,ESC/← 返回上一级;页面 = 对表的一次 parent == 节点 过滤(现算不落地)。

显示模型:横向级联子框——每级一个框,子框左缘 = 父框右缘(共享 1px 边框列);子框顶边对齐父框 "选中行"行顶,溢出时整框上移使底边对齐选中行行底;选中行整行反色(白带黑字),菜单行带 ▶。

改菜单流程:编辑 ui_menu_tree.txt(缩进即层级)→ 重跑 tools/menu_gen/gen_menu.py → 导航/渲染代码零改动。

8.3 内容页

已绑 28 页(按分组;逐页形态见 docs/UI设计/页面补齐规划.md):

分组 页面 形态
装置信息 装置信息 静态键值行 6 行不分页;副标题"馈线自动化终端"
实时数据 交流量 / 直流量 / 遥信量 数据列表(交流量 24 行 / 每页 8,共 3 页;直流量 3 行单页)
参数定值 查看 4 页(参数 / 定值 / 控制字 / 软压板) 只读列表
参数定值 整定 4 页(参数 / 定值 / 控制字 / 软压板) 可编辑(写值 + 置脏 + 保存反馈)
三遥设置 遥测死区 / 遥测系数 可编辑(运行参数段,0x8030~0x804F)
装置维护 时钟设置 / 强制复归 / 清除记录 操作页(执行类必须出真反馈,不得"点了没效果")
通讯参数 通讯设置 / 网口设置 可编辑([comm] / [network] 段,保存后按各自生效时机)
记录查询 SOE 记录 / 自检记录 / 运行记录 记录列表(共用 reader)
记录查询 事故记录 / 操作记录 / 保护告警 / 保护启动 / 遥控记录 记录列表(每记录 2 行、空态显「无记录」;写入点与判据见 App/log/README.md §五类记录)
记录查询 运行报告 只读列表 13 行分 2 页;四个数逐个挂范围标签(自电池周期 / 本次开机),跨开机累计按裁定不做

未绑 5 叶(2026-10-28:记录 5 页与运行报告页已落地绑页,原「当前执行 6 项」清零): 遥信类型 / 遥信防抖 / 双点遥信 = 等开入硬件(§9.1.1「出口与开入」);手动录波 = 等录波子系统 (§9.1.2「录波子系统」);SNTP 设置 = 等 SNTP 对时(§9.1.2「SNTP 对时」)。

  • 内容页为独立全屏屏,由框架一次性自绘(零 LVGL 子对象),ESC 返回菜单屏。
  • 菜单导航状态不压层,返回即原样还原;同一时刻至多一个内容页打开。
  • 节点→页映射在逻辑层 menu_content_page_for(node);未绑叶子进入空白终点框(不伪造数据)。
  • 数据供给走注入通道(rt / par / info / 遥测死区与系数第四表),页面不直接触算法层; 像素黄金用例当前 60 张(菜单 8 状态另计;2026-10-28 记录 5 页与运行报告 2 页落地,+7 张)。

8.4 密码与权限

项 值
查看密码 000(授只读权限)
修改密码 123(授修改权限)
存储 ui_pwd_def.h 编译期写入,不落 Flash
流程 受保护叶子先 arm → 开密码页 → 确认一致后回调 → 先关页再续做进入动作(携授予权限)

8.5 中文字体

  • 字体 ui_font_cn_12.c:宋体 12px 1bpp 子集(当前 218 唯一字 / 313 字形,2026-10-28 实测; 122/217、179/274、185/280 均为历史快照。字形数 = 汉字/符号数 + ASCII 0x20~0x7E 共 95 个)。
  • 生成流程:tools/font_gen/extract_cn.py(扫 UI 源码 → ui_cn_chars.txt)→ tools/font_gen/make_font.py。
  • 约束:任何 UI 文案新增汉字后必须走此流程,否则显示为空白方块。

9. 复刻进度与路线图

口径:本章条目全部来自 §2.5.2 的 🔶 / ⬜ 行——即"参考源码有、本产品还没做或只做了一部分"。 "不做"一词在本章不出现:1:1 复刻口径下没有主动放弃的能力,只有尚未排期的能力。 唯二例外是 §2.5.7 标为"不适用"的两条(归一化值上送、主站 IP 白名单),那是协议语义决定, 不是范围裁剪。

命名:本节条目一律用语义短语(编号规范 P-8 语义优先),不发字母+数字号—— 避免与其它文档的 S/A/P 编号族撞名。

9.1 复刻缺口总表

按缺口性质分两类:阻塞型(缺外部资源或硬件,排期无用)与规模型(无外部依赖,只等排期)。

本节是清单;§9.4~§9.12 是逐项明细——参考源码到底有哪几项、本产品有哪几项、 差额具体落在哪个定值 / 哪个点 / 哪个模块上、以及"怎么算做完了"。排期与估算以明细为准。

9.1.1 阻塞型(等外部条件,排期不能解决)

条目 对应 §2.5.2 现状 缺的是 解除条件
标定闭锁 1~3 9 个元件、定值、闭锁链、SOE、104 上送全部就绪,但 ADC_CAL_F_VALID 未置位 → 判据整体停走 外部资源:子板/端子板变比 + 标准源 端子变比确认 → 8 通道两点标定 → VALID 置位(届时自动解卡,无需改代码)
出口与开入 7、8 无硬件;保护动作只体现为遥信 + SOE;遥控开关量否定确认 硬件 + 立项:出口继电器、开入回路、回读自检 开入开出作为独立模块立项(不可移植项 X3 解除)
三相与同期 4、12 建接口不使能(B/C 相与 IN 削顶、跨转换器无同刻) V0.2 硬件 8 路电气量全接 TPAFE + 中点偏置
电度计量 6 未实现(功率积分需跨转换器同刻) V0.2 硬件 同上(不可移植项 X4 解除)
对下采集 17(子站侧) rs485_task.c 空桩、未建任务、协议族未实现;整簇冻结 决策 + 门禁:用户已决定暂缓 先修「单缓冲包撕裂」「TX 超时拉 DE 未等 TC」→ 接消费者
第三方送检 17 自有主站工具往返已通过 标定 + 第三方环境 标定闭锁解除后送检

9.1.2 规模型(无外部依赖,只等排期)

条目 对应 §2.5.2 参考 现状 差额
定值铺开 1、2 249 项 / 23 单元 40 项(覆盖参考 35 + 本地 5)/ 5 组 +214 项 / +18 单元
映射铺开 3 107 项 0x8820~0x8891 40 项局部 +67 项
元件铺开 12 45 个模块 8 个模块 / 9 个实例 +37 个模块(过流类 6 / 电压类 5 / 重合闸 5 / 方向功率 4 / 涌流故障 5 / 自动控制 5 / 记录 5 / 录波采样 2)
遥测铺开 4、5 31 点 + 模型 35 行 9 点 +22 点 + 模型表
录波子系统 10、15 3 类型 / 6 段 / 65 通道 / RAM 16 个 / COMTRADE 64·64·16 0 整子系统
记录体系 9、13 13 类队列(128/256 条) 8 类 +5 类(越限 / 闭锁 / COS / 顺控 / 顺控执行)
UI 记录页 9、13 参考有完整记录页与运行报告 六页已绑并纳入像素黄金回归(2026-10-28) 只剩真机判据(docs/任务规划/登记簿.md §7)
多规约栈 17 12 种 1 种(104) +11 种(101 / 102 / 103 / CDT / ModBus / Whm_GB / 61850 / CAN + 子站侧 3 类)
国密算法 18 Comm/Ecc/ 全套 0 SM2 / SM3 / ECDSA
软压板铺开 11 9 面(表容量 32) 1 面 +8 面
SNTP 对时 17 参考对时走 SNTP 私有 TCP 8888 + 104 C_CS SNTP 客户端
固有参数 1 8001H~800AH 字符串类参数 未实现(无法短浮点上送) 随送检点表设计
遥测增强 4、5 k=1~9 谐波方和根 + 4 点平均 仅基波轨 谐波 / 等周波调频 / 零序自产外接切换 三条算法轨
屏板链路对齐 20 串口屏板通道(700000 8N1 / USART1 TTL 直连、无 DE,帧 A 6 B 召唤、帧 B 4208 B 应答:显存 3200 B + 状态灯 4 B 位掩码 + 4 B info)+ 7003 四命令(INIT 16 B,单色口径)+ 续传 / 拒绝握手 / 链路监视 / F1·F2 只有 7003 四命令(INIT 8 B);串口通道 0;无状态灯下行;无续传、无 bNeedFlash 拒绝、无 1 分钟监视、键值 6 个 串口通道整条(协议已定版)+ 7003 报文口径 6 项(明细见 §9.13)

一句话:「标定闭锁」是唯一"再排期也没用"的缺口(等标准源);「出口与开入」「三相与同期」 「电度计量」等 V0.2 硬件;「对下采集」等用户决策;其余规模型条目全部可在现有硬件上推进, 只取决于排期。 这张表与 docs/任务规划/登记簿.md 一一对应;状态只在登记簿维护, 本节不另建状态。

9.2 推进顺序

顺序唯一权威 → docs/任务规划/README.md §2.0(本表只是产品视角摘要, 冲突时以该节为准)。

顺序 工作 类别 当前状态 开始条件
1 UI 补齐(记录 5 页 → 运行报告) 规模型 清单已清空(2026-10-28) 六页已落地;余 5 叶属不做项,重开条件见 docs/任务规划/UI补齐.md §5
2 net 层跨上下文收口 平台 下一顺位(未开工) UI 清单已清空,切换条件已满足;开工待用户点头
3 其余结构与可靠性评估 平台 排队 net 收口后
4 端子/子板变比确认 → 两点标定 阻塞型 等外部资源 子板实物/原理图、标准源到位可插入
5 标准源送检与第三方 104 主站验收 阻塞型 等标定 保护 VALID 置位;送检窗口前 2 日冻结特性
6 定值铺开 / 映射铺开 / 遥测铺开 / 软压板铺开 规模型 等排期 标定后(工程量才有意义)
7 元件铺开与遥测增强 规模型 等标准源/硬件 先解除未标定闭锁;三相类等 V0.2
8 录波子系统 → 记录体系 → 多规约栈 规模型 不排 各自重启条件
9 验证窗口事项(CI 远端、PC peer、负向注入) 平台 逢条件顺带 条件到位即执行
10 出口与开入 / 三相与同期 / 电度计量 / 对下采集 阻塞型 不排 V0.2 硬件 / 用户决策

不可颠倒的顺序(一):变比确认 → 两点标定 → 保护解卡 → 送检。未完成标定就送检, 保护表现为不动作;保持该闭锁,不用非标准源走捷径(用户裁定,2026-10-25)。

不可颠倒的顺序(二):点表铺开必须晚于标定——否则铺出去的全是 IV 点, 主站无法区分"没做"与"接线错",比不铺更糟。

9.3 未接线开关说明

开关 位置 现状
功能裁剪开关 App/app/app_cfg.h(当前无宏) 没有任何生效的裁剪开关:原三个 APP_*_ENABLE 占位宏因全库零消费点已于 2026-10-22 删除,各模块一律编译进产品——ADC / RS-485 均为必需链路(ADC = 遥测/保护来源,RS-485 = 对下 ModBus RTU 采集)。将来确需裁剪时在真实初始化点接入门控,并同步登记回该文件
TEST_SUITE_* test/board/test_config.h 测试套件互斥,一次构建只开一个;全注释 = 正常产品固件
rs485_task.c App/task/(未建任务、白名单登记) 唯一的结构白名单缺口:RS-485 整簇冻结期间刻意不接线,随该簇一并出白名单
DTU_BENCH 构建宏(protect_task.c 等) 台架构建下允许保护判据在未标定时动作(仅测试用);产品构建(#ifndef DTU_BENCH)下保护闭锁

9.4 定值复刻明细(参考 249 项 → 本产品 40 项)

参考定值表的每一行固定 21 个字段:标识 ×2 / 类型(数值 | 枚举)/ 所属单元 / 单位组 / 值类型 / 最小值 / 最大值 / 步长 / 两个标志 / 上下限原始值 ×3(0xAA / 0xAAAA / 0xFF)/ 104 地址 / 单位 ×2 / 小数位 / 长度 / 显示名 / 结束标记。 本产品对应物是 App/algo/prot_set.h 的 PS_* 枚举(PS_ID_COUNT = 40)。

40 项的去向必须能对上账,否则"还差多少"无从谈起:

去向 项数
覆盖参考定值项 35
本产品本地扩展项(参考无对应行) 5(PS_RET_OVER / PS_RET_UNDER 返回系数,PS_RET_OF / PS_RET_UF 频率返回系数,PS_GLOBAL_EN 全局软压板)
合计 40

因此定值差额 = 249 − 35 = 214 项。

9.4.1 23 个定值单元逐单元差额

单元 语义 参考项数 本产品覆盖 差额
WatchDog 过流三段 / 零序三段 / 过负荷 / 重载 / 过载 / 过频 / 低频 63 22 41
SYS3 系统参数(零飘、死区、变比、防抖、脉宽、FA 模式…) 45 0 45
VolTimeRecv 电压时间型馈线自动化(失电分闸 / 得电合闸 / 联络) 17 0 17
AutoReCls 重合闸 16 0 16
SYN 同期(FTU 型) 13 0 13
OverCurI0 接地告警(小电流接地选线) 13 0 13
VolPro 电压保护(失压 / 过压 / 零序过压) 13 9 4
WAVESTART 录波启动 12 0 12
MeaLimit 遥测越限 10 0 10
OverCurSpeed 过流 / 零序后加速 8 0 8
SYS1 PT 参数 6 2 4
SYS2 CT 参数 4 2 2
Auto_FG 延时自动分闸 4 0 4
Auto_HH 延时自动合闸(电池活化) 4 0 4
InRush 励磁涌流闭锁 3 0 3
OverCur 短路告警 3 0 3
VolQuaRate 电压合格率 3 0 3
FZDDL 非遮断电流闭锁 3 0 3
BHKO 保护出口展宽 2 0 2
MeaRecord 遥测记录周期 2 0 2
PowerSet 功率电压组 2 0 2
PTBreak PT / 控回断线告警 2 0 2
AutoCtrl 自动复归 1 0 1
合计 249 35 214

单元名 WatchDog 有误导性:它装的是全部保护元件的动作定值(过流 / 零序 / 负荷 / 频率), 不是看门狗参数。移植时不要按名字去找"看门狗定值"。

9.4.2 已覆盖单元的逐项对照(35 项)

过流三段:参考 24 项,本产品 12 项(每段缺 4 项,共缺 12)

参考项(Ⅰ/Ⅱ/Ⅲ 段各一份) 本产品 说明
过流 n 段投入 PS_OCn_EN ✅
过流 n 段跳闸投入 PS_OCn_TRIP ✅ 语义 = 0 告警 / 1 跳闸
过流 n 段定值 PS_OCn_CUR ✅ 二次值 A
过流 n 段延时 PS_OCn_DLY ✅ ms(参考为 S,换算在整定入口)
过流 n 段方向投入 — ❌ 无方向元件(DirCell / PowDirJudge 未复刻)
过流 n 段低压投入 — ❌ 无复压闭锁(bNOVOpen 无来源)
过流 n 段告警投入 — ❌ 参考把"告警投退"与"跳闸投退"拆成两项,本产品只有一项
过流 n 段低压定值 — ❌ 同上

这一处差额最容易被低估:本产品的三段过流是"简化版三段",参考的三段每段还带 方向 / 低压 / 告警 三个独立开关和一个低压定值。缺这四项时,三段过流只能做无方向、 无复压闭锁的纯过流保护——在环网或双电源线路上会误动。

零序过流三段:参考 18 项,本产品 0 项

参考在 WatchDog 内另有完整的零序三段(每段 6 项:投退 / 方向 / 告警投入 / 跳闸 / 定值 / 时限)。 本产品 PS_3U0_* 三项是零序过压(属 VolPro),不是零序过流——两者不可混为一谈: 零序过流看 3I0 幅值,零序过压看 3U0 幅值。因此零序过流保护目前完全没有定值载体, OverCurrent_I0 元件也无从判据。

过负荷 / 重载 / 过载:参考 12 项,本产品 4 项

参考项组 本产品 差额
过负荷报警(投退 / 跳闸 / 定值 / 时限) PS_OL_* 4 项 ✅ 齐
重载报警(同上 4 项) — ❌ 缺 4
过载报警(同上 4 项) — ❌ 缺 4

参考把"过负荷 / 重载 / 过载"分成三级(默认 150 A / 70 A / 100 A 步长,时限 9000 s / 0 / 0), 对应事件 435 / 436 / 437。本产品只有一级过负荷。三级是同一判据不同门槛, 复刻成本低(元件框架已具备),但需先补 OverLoad 的三个实例与三条事件映射。

过频 / 低频:参考 8 项,本产品 6 项 + 2 本地项

参考项 本产品 说明
过频 / 低频 保护投退 PS_OF_EN / PS_UF_EN ✅
过频 / 低频 保护定值 PS_OF_HZ / PS_UF_HZ ✅ 参考单位 HZ 存 5000~5500(0.01 Hz),本产品存 Hz 浮点
过频 / 低频 保护时限 PS_OF_DLY / PS_UF_DLY ✅
过频 / 低频 跳闸投退 — ❌ 缺 2:参考区分"保护投入"与"跳闸投入",本产品只有前者

电压保护:参考 13 项,本产品 9 项

参考项 本产品 说明
失压保护投退 / 定值 / 时限 PS_UV_EN / PS_UV_VOL / PS_UV_DLY ✅
过压保护投退 / 定值 / 时限 PS_OV_EN / PS_OV_VOL / PS_OV_DLY ✅
零序过压投退 / 定值 / 时限 PS_3U0_EN / PS_3U0_VOL / PS_3U0_DLY ✅
失压 / 过压 / 零压 跳闸投退(3 项) — ❌ 缺 3
零压 告警投退(1 项) — ❌ 缺 1

PT / CT 参数:参考 10 项,本产品 4 项

参考项 本产品 说明
母线一次额定(kV) PS_PT_PRI ✅ 本产品存 V
母线二次额定(线)(V) PS_PT_SEC ✅
额定 TA 一次值(A) PS_CT_PRI ✅
额定 TA 二次值(A) PS_CT_SEC ✅
母线二次额定(相)(V) — ❌ 缺:线 / 相两种二次额定的换算关系需显式给出
零序一次额定(kV) — ❌ 缺
零序二次额定(V) — ❌ 缺
零序一次额定(A) — ❌ 缺
零序二次额定(A) — ❌ 缺
PT 接入数目(1~3) — ❌ 缺:决定用线电压还是相电压作判据源

9.4.3 完全未覆盖单元逐项清单(163 项)

214 项差额中,51 项落在 §9.4.2 已部分覆盖的四个单元里(过流 12 / 零序 18 / 重载与过载 8 / 频率 2 / 电压 4 / PT·CT 6 / 备用控制字 1),余下 163 项落在下面这些一项都没有的单元里。 逐项列出以便排期时按"整单元"认领,不要拆散。

系统参数 SYS3(45 项)——零飘门槛 10 项:额定电压零飘门槛、额定电流零飘门槛、直流电压零飘、 功率零飘、频率零飘、功率因数零飘、相角零飘门槛、备用 ×4;死区 7 项:电流死区、电压死区、 直流电压死区、功率死区、频率死区、功率因数死区、相角死区;开入开出 4 项:开入防抖(1060000 ms)、 分闸脉宽、合闸脉宽、开入手动分合;变比 5 项:PT 变比、相 CT 变比、零序 CT 变比、功率变比、电量变比; 其余 19 项:开关类型、故障遥信保持时间、功率置负、单项接地选线投入、单相接地跳闸时间、FA 模式、 对时切换长延时、断线告警确认时间、事故总判小电流接地告警、加速段保护开放时间、 重合闸检有压等待时间、连续分闸时间、分闸次数、备用参数 0108。

本产品的死区落在运行参数段(0x8030~0x8038 九点,RAM 副本 + 104 可写), 变比落在 prot_set 的 PT/CT 四项。语义已覆盖、载体不同——复刻 SYS3 时是把这 两类合并进定值表,不是重新实现。

电压时间型自愈 VolTimeRecv(17 项):就地 FA 模式、LS(0/1,1 = 联络)、 失电分闸投退、失电分闸时限(0100000 s)、得电合闸投退、X 时间(1100 s,默认 7)、 故障电流检测、故障电流定值(110000 A)、Y 时间(1100 s,默认 5)、联络开关合闸、 联络充电时限(01800 s)、联络合闸时限(0300 s)、正方向选择、残压定值(0300 V)、 残压判定时限、停电时间(110 s)、人工闭锁。

这是馈线自动化(FA)的核心:失电分闸 → 得电合闸 → 联络转供。对应元件 NoVolTrip / HaveVolCls / ConnectBrkCls / FaultIsola / FaultRecov 五个模块。 无开入(开关位置)与出口(分合闸)时无法闭环,属 X3 依赖项。

重合闸 AutoReCls(16 项):重合闸投退、充电时间(0100000 s)、重合闸次数(03)、 一次 / 二次 / 三次重合闸时间(060000 s)、重合闸闭锁时间(09900 s)、整组复归时间、 大电流闭锁投退、大电流闭锁定值、重合闸检同期、重合闸检无压、同期检无压定值(015000 V)、 同期检角差定值(130°)、过流禁止重合闸、零序禁止重合闸。

参考支持三次重合且每次时间独立可整定,充电时间与整组复归时间分离——这三项 是"重合闸能不能用"的关键(无充电时间 = 每次跳闸都立即重合,会连击)。 依赖出口(合闸)与开入(开关位置),属 X3 依赖项。

同期 SYN(13 项,FTU 型专属):检无压投退、检同期投退、频差 / 角差 / 压差 / 滑差闭锁投退 (4 项)、检无压定值(10009999 V)、检频差定值(0200,0.01 Hz)、检角差定值(1180°)、 检压差定值(09999 V)、检频率滑差值(0200 Hz/s)、开关合闸时限(0200 s)、整组复归时间。

需两路电压同刻(母线侧 + 线路侧)才能算角差与频差——本产品 V0.1 只有一个转换器的 电压通道,属 X3 / H1 依赖项。

录波启动 WAVESTART(12 项):电流启动投退 / 定值(010000 A)、低压启动投退 / 定值 (010000 V)、零压启动投退 / 定值(030000 V)、零流启动投退 / 定值(01000 A)、 零流突变投退 / 定值(0~1000 A)、录波启动延时、保护启动录波。

录波启动是独立于保护判据的触发源:即使保护不动作,只要越启动值也要录波。 本产品无录波子系统,这 12 项无处落地(见 §9.9)。

遥测越限 MeaLimit(10 项):有压鉴别投退 / 线路有压定值(0300 V)、无压鉴别投退 / 线路无压定值(0300 V)、线路有压时限(2100000 s)、电压越上限 / 越下限(0100000 V)、 电流越上限(0~10000 A)、越上限延时 / 越下限延时。

越限记录(OVER 队列,128 条)的判据来源。本产品无越限记录类,故这 10 项也无载体。

过流后加速 OverCurSpeed(8 项):后加速投退、线路 1 前加速投退、过流后加速电流值 (110000 A)、过流后加速时限(010000 s)、零序后加速投退、线路 1 前加速投退(重复项, 参考源码如此)、零序后加速电流值(1~1000 A)、零序后加速时限。

接地告警 OverCurI0(13 项):线路接地告警投退、零序电流反极性、零序电压反极性、 接地备用 02、接地告警投退、接地跳闸投退、接地方向投退、接地定值(010000 A)、接地时限、 接地跳闸时限(0600 s)、零压启动定值(1~10000 V)、接地重合投退、接地后加速投退。

反极性两项是现场接线纠错开关(CT / PT 装反时不必改线,改定值即可), 属"现场可维护性"需求,不是可选项。

其余小单元(合计 29 项):励磁涌流闭锁 3(闭锁投退、涌流制动系数 1100、闭锁复归时间); 短路告警 3(投退 / 时限 / 线路 01 短路电流定值);电压合格率 3(上限 / 下限定值 0200 %、周期类型 04); 非遮断电流闭锁 3(电流闭锁投退、停电跳闸投退、非遮断电流值 110000 A); 出口展宽 2(跳闸出口时间、合闸出口时间,1100000 ms); 遥测记录 2(遥测记录周期 02880、极值记录周期 0360); 功率电压组 2(14 组);PT 断线 2(断线告警、控回断线告警);自动复归 1(自动复归投退); 延时自动分闸 4(延时复归投退、2:时 1:分 0:秒、延时复归时限 ×2); 延时自动合闸 4(自动活化投退、2:分 1:时 0:日、自动活化周期 0360、自动活化时限 023000 s)。


9.5 遥测复刻明细(参考 31 点 → 本产品 9 点)

参考 g_tYcIndexTab 的 31 点是按"两回线 × 三相 + 线电压 + 零序 + 功率"组织的完整电气量集。 本产品 9 点(0x4011~0x4018、0x401D)只覆盖第一回线的相量与频率。

# 参考遥测 参考枚举 本产品 差额原因
1 1 回 A 相电流 EN_YCMEA_IA01 0x4015 ✅
2 1 回 B 相电流 EN_YCMEA_IB01 0x4016 ✅ 削顶 → 恒 IV
3 1 回 C 相电流 EN_YCMEA_IC01 0x4017 ✅ 削顶 → 恒 IV
4 2 回 A 相电流 EN_YCMEA_IA02 — ❌ 无第二回线
5 2 回 B 相电流 EN_YCMEA_IB02 — ❌
6 2 回 C 相电流 EN_YCMEA_IC02 — ❌
7 1 回 A 相电压 EN_YCMEA_UA1 0x4011 ✅
8 1 回 B 相电压 EN_YCMEA_UB1 0x4012 ✅ 削顶 → 恒 IV
9 1 回 C 相电压 EN_YCMEA_UC1 0x4013 ✅ 削顶 → 恒 IV
10 2 回 A 相电压 EN_YCMEA_UA2 — ❌
11 2 回 B 相电压 EN_YCMEA_UB2 — ❌
12 2 回 C 相电压 EN_YCMEA_UC2 — ❌
13 1 回 AB 线电压 EN_YCMEA_UAB1 — ❌ 需两相相量之差
14 1 回 BC 线电压 EN_YCMEA_UBC1 — ❌
15 1 回 CA 线电压 EN_YCMEA_UCA1 — ❌
16 2 回 AB 线电压 EN_YCMEA_UAB2 — ❌
17 2 回 BC 线电压 EN_YCMEA_UBC2 — ❌
18 2 回 CA 线电压 EN_YCMEA_UCA2 — ❌
19 1 回零序电流 EN_YCMEA_3I01 0x4018 ✅ 近似对齐(本产品为外部零序通道)
20 1 回零序电压 EN_YCMEA_3U01 0x4014 ✅ 近似对齐
21 2 回零序电压 EN_YCMEA_3U02 — ❌
22 频率 EN_YCMEA_FR1 0x401D ✅
23 直流 1 EN_YCMEA_DC_01 — ❌ 无直流采样通道
24 直流 2 EN_YCMEA_DC_02 — ❌
25 A 相有功 EN_YCMEA_PA_1 — ❌ 需跨转换器同刻(H1)
26 B 相有功 EN_YCMEA_PB_1 — ❌
27 C 相有功 EN_YCMEA_PC_1 — ❌
28 总有功 EN_YCMEA_P_1 — ❌
29 总无功 EN_YCMEA_Q_1 — ❌
30 总视在 EN_YCMEA_S_1 — ❌
31 功率因数 EN_YCMEA_COS_1 — ❌

缺的 22 点按依赖分三批:

批次 点数 内容 依赖
线电压与功率 13 6 线电压 + 7 功率/功率因数 H1:电压在 TPAFE、电流在 STM32 ADC1,无共同触发,功率的 U×I 需同刻
第二回线 7 2 回 6 相量 + 3U02 采样通道数(V0.2 硬件)
直流 2 DC_01 / DC_02 无直流采样通道

线电压本身不一定要等 H1:Uab = Ua − Ub 只需同一转换器内的两相相量, 若两相都落在 TPAFE 侧即可算。当前 Ub/Uc 削顶(在 STM32 侧),所以连带算不出。 先解决"三相电压全落 TPAFE"这一件事,能一次解锁 6 个线电压点。

遥测模型 g_tAnaModelTab(35 行):参考为每个遥测点定义死区、变比、系数、越限档等属性行, 是"点表 + 整定"的合体。本产品的对应物拆成了三处:iec104_pts.c 的 YC 表(地址 + 死区系数)、 run_par.c 的死区九点、adc_cal.c 的 k/b。复刻模型表 = 把这三处收敛成一张可整定的表。

电度 g_tYmIndexTab(8 种,本产品 0):正向有功 Pt1、正向无功 Qt1、Q1 象限、Q4 象限、 反向有功 Pt0、反向无功 Qt0、Q2 象限、Q3 象限。地址段 0x6401~0x6600。 电度 = 功率对时间积分,与功率同批解锁(同一 H1 依赖)。


9.6 开入 / 开出复刻明细(138 + 31 → 本产品 0)

参考把"开入"分成四类,本产品一个都没有(无硬件,不可移植项 X3)。

开入 138 点的构成:

类别 点数 含义
软遥信 EN_KI_SOFTYX_* 104 由保护元件/逻辑产生的内部状态,不占物理端子(如"过流Ⅰ段动作""重合闸充电完成""FA 投入")
硬件开入 EN_KI_* / EN_KIA_* 27 物理端子:开关合位 / 分位 / 未储能 / 就地远方 / 接地位置 / 隔离位置 / 停用重合闸 / 保护投入 / 检修压板 / 远方信号 / 就地 FTU 手合手分 / 电源输入 / 活化状态 / 电池欠压 / 活化投入
双点遥信 EN_KI_TWIN_YX_* 6 开关位置用双点表达(00 中间态 / 01 分 / 10 合 / 11 无效)
多态遥信 EN_KI_INT8U_* 1 8 位状态量(如"设备状态"枚举)

104 点 ≠ 104 个端子。真正要接线的是 27 个硬件开入;104 个软遥信是元件输出, 只要元件复刻出来就自然存在。这个区分决定了工作量估算:不是"买 138 路开入板", 而是"27 路端子 + 104 个元件状态映射"。

开出 31 点的构成:

类别 点数 明细
出口类 11 保跳 1(BH_TZ1)、保合 1(BH_HZ1)、遥分 1(YT01)、遥合 1(YH01)、遥分 2(YT02)、遥合 2(YH02)、电池活化(DCHH)、活化退出(DCHH_Esc)、信号复归(FG)、开入变位(KICHANGE)、录波启动(WAVE_START)
信号类 20 事故信号 SignTV、运行 SignRun、通信中断 SignCOMM、硬件故障 SignHW、储能 SignCN、电池欠压 SignBatQY、失电 SignSD、过负荷 SignGL、接地 SignJD、闭锁 SignBM、备用 SignBS、自检 SignCHK、重合 SignCH、备用 3 个 SignBAK1~3、告警 SignALM、保护动作 SignPro、就地 FA SignJDFA、集中 FA SignJZFA

本产品当前保护动作只体现为遥信 + SOE,没有任何物理出口。这在"保护测控装置"的 定义里是硬缺口:保护判据做得再准,不跳闸就等于没保护。X3 解除前,YX 里的 动作类遥信必须如实标 IV,不能让主站误以为已跳闸。


9.7 动作事件复刻明细(参考 33 条 → 本产品 9 条)

参考 g_tActRecTab 的 33 条动作事件编号 421~453,是"保护动作 → 事件码 → 记录 → 上送"的 中间层。本产品用 App/log/sys_log.h 的七类记录 + SOE,没有事件码表。

事件码 参考事件 本产品 说明
421 线路励磁涌流闭锁 ❌ InRushCur 未复刻
422 线路Ⅰ段过流保护动作 ✅ PS_OC1_*
423 线路Ⅱ段过流保护动作 ✅ PS_OC2_*
424 线路Ⅲ段过流保护动作 ✅ PS_OC3_*
425 线路零序Ⅰ段过流保护动作 ❌ 无零序过流定值载体
426 线路零序Ⅱ段过流保护动作 ❌ 同上
427 线路零序Ⅲ段过流保护动作 ❌ 同上
428 线路后加速保护动作(过流) ❌ OverCurrent_SpeedUp 未复刻
429 线路后加速保护动作(零序) ❌ OverCurrentI0_SpeedUp 未复刻
430 零序过压保护动作 ✅ PS_3U0_*
431 线路欠压保护动作 ✅ PS_UV_*
432 线路过压保护动作 ✅ PS_OV_*
433 高频保护动作(过频) ✅ PS_OF_*
434 低频保护动作 ✅ PS_UF_*
435 线路过负荷保护动作 ✅ PS_OL_*
436 线路重载保护动作 ❌ 三级负荷只做了一级
437 线路过载保护动作 ❌ 同上
438 线路接地保护动作 ❌ OverCurI0 未复刻
439 一次重合动作 ❌ 重合闸未复刻
440 二次重合动作 ❌ 同上
441 三次重合动作 ❌ 同上
442 接地重合动作 ❌ 同上
443 接地后加速动作 ❌ 同上
444 失电分闸动作 ❌ NoVolTrip 未复刻
445 得电合闸动作 ❌ HaveVolCls 未复刻
446 闭锁合闸动作 ❌ 需开入(闭锁压板)
447 闭锁分闸动作 ❌ 同上
448 联络开关合闸动作 ❌ ConnectBrkCls 未复刻
449 联络开关分闸动作 ❌ 同上
450 保护动作备用 02 — 参考即备用
451 A 相故障 ❌ 需分相判别(三相全接)
452 B 相故障 ❌ 同上
453 C 相故障 ❌ 同上

本产品覆盖 9 / 33 条。注意 428 与 429 在参考源码里同名(都叫"线路后加速保护动作"), 靠事件码区分过流与零序——移植时不能按名字去重。

事件码缺失的连带后果:事故报告(CN_NUM_QUE_REC_RPT 队列)无法生成。 参考的事故报告是按事件码索引动作时序的,没有事件码表就没有"保护动作报告"这一页。


9.8 保护元件复刻明细(参考 45 个模块 → 本产品 8 个)

模块级口径:参考 RelayUnit/ 45 个 .c 文件 = 45 个元件模块。本产品覆盖 8 个模块 (7 个判据模块 + 1 个记录模块),以 9 个实例落地(OverCurrent 一个模块出三段实例)。

类别 参考模块 本产品 缺
过流类 8 2(OverCurrent、OverLoad) 6
电压类 8 3(OverVol、OverVol_U0、LackVol) 5
频率类 2 2(OverFr、LackFr) 0
重合闸 5 0 5
方向 / 功率 4 0 4
涌流 / 故障 5 0 5
自动控制 5 0 5
记录类 6 1(SOERecord) 5
录波 / 采样 2 0 2
合计 45 8 37

缺的 37 个模块,逐个给出"缺它意味着什么":

模块 类别 判据要点 缺它的后果 依赖
OverCurrent_I0 过流 零序电流三段 + 方向 接地故障无保护 定值载体(零序 18 项)
OverCurrent_SpeedUp 过流 后加速:重合后短延时无选择跳闸 重合于故障时靠 Ⅰ 段延时切除,慢一拍 重合闸
OverCurrentI0_SpeedUp 过流 零序后加速 同上(接地) 重合闸
FZDOverCur 过流 非遮断电流闭锁(负荷电流以下不允许跳闸) 小电流跳闸可能拉弧不熄 定值 3 项
OverCurWarn 过流 过流告警(只告警不跳闸) 过流只能跳不能告警 定值(告警投入)
OverCurWarn_I0 过流 零序过流告警 同上 定值
LineHaveVol 电压 线路有压鉴别 无法区分"有压合闸"与"无压合闸" 定值(MeaLimit 有压鉴别)
HaveVolCls 电压 得电合闸 FA 的"来电自动合闸"缺失 开入 + 出口
NoVolTrip 电压 失电分闸 FA 的"失电自动分闸"缺失 开入 + 出口
PTBreak 电压 PT 断线(电压消失但电流正常) 断线时电压类保护可能误动/拒动 定值 2 项
CTBreak 电压 CT 断线 同上(电流侧) 定值
AutoReCls 重合闸 充电 → 跳闸 → 延时重合 → 整组复归 瞬时故障必须人工合闸 开入 + 出口 + 16 项定值
AutoReCls_JD 重合闸 接地故障重合 同上(接地) 同上
OnceCch 重合闸 一次重合(表内无定值,条件编译) — 同上
TwiceCch 重合闸 二次重合(表内无定值,条件编译) — 同上
ConnectBrkCls 重合闸 联络开关合闸(转供) 环网无法转供 开入 + 出口 + 17 项定值
DirCell 方向 / 功率 方向元件(功率方向判别) 双电源/环网会反送电误动 三相电压 + 三相电流同刻(H1)
PowDirJudge 方向 / 功率 功率方向(有功/无功象限) 同上 同上
PowerSet 方向 / 功率 功率电压组切换(1~4 组) 多组 PT/CT 变比无法切换 定值 2 项
YcOverLimit 方向 / 功率 遥测越限判据 越限记录无来源 定值(MeaLimit 10 项)
InRushCur 涌流 / 故障 二次谐波制动(励磁涌流闭锁) 变压器空投时过流误动 谐波算法(见 §9.12 遥测增强)
FaultIsola 涌流 / 故障 故障隔离 FA 无法定位故障区段 开入 + 出口
FaultRecov 涌流 / 故障 故障恢复供电 同上 同上
BusEarthAlm 涌流 / 故障 母线接地告警 母线接地无告警 零序电压
SgzAlarm 涌流 / 故障 事故总告警 事故总信号缺失 事件码表
AutoCtrlTrip 自动控制 自动控制跳闸(电池活化等) 活化流程无法跳闸 出口
ManualTrip 自动控制 手动跳闸 就地手动分闸缺失 开入 + 出口
MusterRecov 自动控制 总复归(复归所有保持态) 动作态只能靠重启清 无(可先做)
ExvRec 自动控制 事故记录 事故报告缺失 事件码表
ExvRecGW 自动控制 事故记录(网关侧) 同上 同上
CORecord 记录 COS 变位记录 开入变位无记录 开入
FrzRecord 记录 冻结记录(整点冻结电量) 电度无冻结 电度
YcMeaRecord 记录 遥测定时记录 无遥测历史 定值 2 项
YcMeaLimitRec 记录 遥测越限记录 无越限记录 越限判据
YcVolQuaRate 记录 电压合格率统计 无合格率 定值 3 项
WaveQdCell 录波 / 采样 录波启动判据 录波无触发源 录波子系统
RlyCommSam 录波 / 采样 保护通信采样(跨装置采样同步) 多装置差动类保护不可能 通信 + 对时

唯一"现在就能做"的是 MusterRecov(总复归):它不依赖任何硬件,只把各元件的 保持态与出口标志清一遍。本产品已有 prot_elm_request_reset 单字请求标志(§3.5), 接上即可。其余 36 个模块都至少依赖定值载体、开入、出口、事件码四者之一。


9.9 故障录波子系统规格(本产品 0)

录波是唯一一个"完全独立的子系统"级缺口:它不在保护链路上,但有独立的采样率、 独立的存储格式、独立的文件传输通道。参考实现的硬指标如下,可直接作为复刻验收判据。

指标 参考值(APP/EquipCfg/Const_Wave.h) 说明
录波采样率 CN_SAM_RATE × CN_WAVE_RATIO = 20 × 4 = 80 点/周波(50 Hz 下 4000 Hz) 保护计算用 20 点/周波,录波要 4 倍过采样才能看清波形
录波段数 CN_WAVE_SECT_NUM = 6 段 每段独立缓冲,支持连续多次录波
启动前缓冲 CN_WAVE_CYCLE_SUM_REFRE_BUF = 5 周波(100 ms) 循环刷新,保证故障前有数据
动作后 CN_WAVE_CYCLE_SUM_ACTED = 10 周波(200 ms)
返回段 CN_WAVE_CYCLE_SUM_RET = 2 周波 返回过程也要录
手动录波 CN_WAVE_CYCLE_SUM_HAND = 6 周波
单次最长 CN_WAVE_MAX_TIME = 9000 ms 超长故障(如持续性接地)按此截断
RAM 录波个数 CN_WAVE_RAM_NUM = 16 RAM 里最多同时存 16 份,满了转存文件
COMTRADE 保存数 动作 64 / 启动 64 / 手动 16 三类独立配额,满了循环覆盖
单份最大开关变位 CN_WAVE_MAX_RECSWI = 64
布尔量通道 CN_WAVE_NUM_BOOLFLG = 320 全局布尔变量按位录波
模拟量通道 原始 + 计算 = CN_WAVE_ALL_ANA_NUM 本产品对应 65 通道(g_tMeasureModelTab)
录波类型 动作 TYPE_ACT=1 / 启动 TYPE_START=2 / 手动 TYPE_HAND=3
文件格式 COMTRADE(.cfg + .dat) 主站侧通用格式,非私有
上送方式 104 文件传输(F_FR_NA_1 目录 / F_SR_NA_1 读文件) 本产品 104 未实现文件传输

复刻所需的四件东西(缺一不可):

  1. 4 倍过采样缓冲:当前 adcTask 以 1000 Hz 出样本,录波要 4000 Hz。要么提高采样率 再抽取给保护(改变整条链节拍),要么在 TPAFE 侧单独开一条 4 倍速通路(改驱动)。
  2. 环形缓冲 + 触发点定位:5 周波前缓冲 + 10 周波后缓冲,触发时刻要能反算出缓冲内偏移。
  3. COMTRADE 编码器:.cfg(通道定义、采样率、时标)+ .dat(二进制采样值)+ .hdr。
  4. 文件存储与配额管理:SPI NAND 上按 64/64/16 配额循环覆盖,需与现有 FatFs + dhara 层对接。

排期判断:录波不是"加个功能",是新增一条 4 倍速采样通路 + 一套文件格式 + 一个配额管理器。 它排在定值/元件铺开之后,因为录波通道表(65 路)本身依赖元件输出。


9.10 记录体系复刻明细(参考 13 类 → 本产品 8 类)

参考用 13 个定长队列分类存记录,容量按类分配(GlobalDef/Const_Sys.h):

参考队列 容量 语义 本产品
REC_ACT 128 动作记录(保护动作) ✅ 事故记录 /log/accid.log
REC_ALM 128 告警记录 ✅ 保护告警 /log/alarm.log
REC_OVER 128 越限记录 ❌
REC_START 128 启动记录(元件启动但未动作) ✅ 保护启动 /log/start.log
REC_LOCK 128 闭锁记录(保护被闭锁) ❌
REC_SOE 256 SOE(带时标的开入变位) ✅ soe_store(SPSC 深度 8 → 落盘)
REC_COS 256 COS(无时标的状态变位) ❌
REC_CHK 128 自检记录 ✅ /log/selftest.log
REC_RUN 128 运行记录(上电/重启) ✅ /log/run.log
REC_OPT 128 操作记录(复归/对时/定值保存) ✅ /log/oper.log
REC_YK 128 遥控记录 ✅ /log/yk.log
REC_SC 128 顺控记录 ❌
REC_SCSTEPINFO 128 顺控执行明细 ❌

缺的 5 类及其依赖:

缺的队列 依赖 能否先做
越限记录 越限判据(MeaLimit 10 项定值 + YcOverLimit 元件) 可先做判据、后做记录
闭锁记录 闭锁源已具备(四源闭锁,§5.12),只缺记录落点 ✅ 最该先补——现在闭锁发生了但无记录,现场排障靠猜
COS 记录 开入(X3) ❌
顺控记录 / 顺控执行明细 顺控功能(参考 YKRly.c 63 KB 的顺控执行引擎) ❌ 整功能未立项

闭锁记录是本表里性价比最高的一项:闭锁源(未标定 / 采样故障 / 定值校验和 / 软压板退出) 已经全部实现,但闭锁的发生与解除都没有留痕。加一个 REC_LOCK 等价队列, 只需在 protect_task 的闭锁判定处加一条写入,不依赖任何硬件。

格式差异:参考是二进制定长记录 + 独立队列 + 循环覆盖;本产品是文本行(64 B 定长)+ 文件。 文本行的优点是 FTP 直接可读、现场排障友好;缺点是容量利用率低、无结构化解码。 复刻时建议保留文本格式(本产品优势),只补队列分类与配额。


9.11 规约栈复刻明细(参考 12 种 → 本产品 1 种)

规约 参考源码 链路 用途 工作量特征
IEC 60870-5-104 Comm/Pub/Rly_IEC104.c TCP 主站接入(本产品已实现) ✅ 已完成
IEC 60870-5-101 Rly_IEC101.c、Rly_IEC101_B.c 串口 主站接入(老站) 与 104 共享 ASDU 层,只换链路层(平衡/非平衡链路、可变帧长)
IEC 60870-5-102 Rly_IEC102.c 串口 电度采集 独立 ASDU(电度专用类型),依赖电度
IEC 60870-5-103 RLY_IEC103.c、RLY_IEC103-tcp.c、Rly_IEC103T.c 串口 / TCP 保护装置信息接口 三种变体(串口 / TCP / T 型),ASDU 与 101/104 不同族
ModBus Rly_ModBus.c 串口 / TCP 通用工业设备 简单,对下采集首选
CDT Rly_Cdt.c 串口 循环式远动(老国标) 帧结构简单,无确认机制
Whm_GB Whm_GB.c 串口 国标电度 依赖电度
IEC 61850 struct61850.h、GlobalUnit/SttnLvlGoose.c 以太网多播 MMS / GOOSE / SV 最大工作量:需 MMS 栈 + ASN.1 + 多播组管理
CAN Rly_Can.h CAN 总线 内部总线 依赖 CAN 硬件
子站 IEC 101 Comm/Mon/Rtu_IEC101*.c(含 ABB / 西门子 / 无优先级变体) 串口 对下接 FTU / 开关 对下主站侧,与对上从站侧是不同角色
子站 IEC 104 Rtu_IEC104.c、Rtu_Dbg104.c、Rtu_RIS104.c TCP 对下 含调试与 RIS 变体
BALA101 / ModBus Rtu_BALA101*.c、Rtu_ModBus.c 串口 对下 与 RS-485 簇同批
加密 Comm/Ecc/(SM2 / SM3 / ECDSA) — 安全加固 国密算法库,纯软件可移植

排期分层:

层 规约 理由
先做 ModBus(对上 + 对下)、IEC 101 与 104 共享 ASDU 或结构简单;对下采集是配网终端必备
次做 IEC 103、CDT、BALA101 老设备兼容,结构清晰
后做 IEC 102、Whm_GB 依赖电度(H1)
末做 IEC 61850 需 MMS/ASN.1/多播,单核 M4 资源需专项评估
并行 SM2 / SM3 / ECDSA 纯软件,无硬件依赖,可随时插入

一个容易漏的点:参考同时有对上(Comm/Pub,本机作从站)与对下(Comm/Mon,本机作主站) 两套规约。本产品只有对上 104。做"配网终端"时对下那套(101/104/ModBus 主站侧) 是必须的——否则接不了一次开关。


9.12 复刻完成判据(逐缺口可验证)

每一条缺口给出"怎么算做完了",避免"实现了但没验收"。

缺口 完成判据
定值铺开 PS_ID_COUNT = 249(或按单元分批:每批新增项在 104 上可读写、跨复位保持、校验和正确);check 脚本比对参考表逐项一致
104 定值映射 107 个地址(0x8820~0x8891 含 8 空洞)全部可读可写;空洞地址返回"未知信息体地址"
元件铺开 45 个模块对应 45 个实例;每个实例有:定值项齐全、启动/动作/返回三态可观测、事件码正确、单测覆盖判据边界
遥测铺开 31 点全部非 IV(除物理不可达点明确标 IV);线电压与相量满足 Uab = Ua − Ub 误差 ≤ 0.5 %
开入开出 27 路硬件开入可读、31 路开出可驱动;开入防抖可整定;双点遥信四态正确(00/01/10/11)
录波 4000 Hz 采样;三类录波各生成一份 COMTRADE 且被第三方工具打开;配额 64/64/16 循环覆盖正确
记录体系 13 类队列各有落点;每类容量达标;断电不丢已确认记录
多规约 每种规约与对应主站/子站工具完成一次完整交互(连接 / 总召 / 变位 / 遥控 / 断链重连)
国密 SM2 签名验签、SM3 摘要与标准测试向量一致
软压板 9 面全部可投退且行为可观测(投退后对应功能确实停走/恢复)
出口与开入 保护动作 → 出口继电器动作 → 开入回读确认,全链路 ≤ 120 ms
标定解卡 8 通道两点标定后 ADC_CAL_F_VALID 全置位;注入标准源,保护动作值与定值误差 ≤ 3 %
屏板链路 串口通道:屏板 275 ms 召唤、主机 ≤200 ms 回 4208 B,连续 10 min 无超时;显存 3200 B 与 g_ui_fbuf 逐字节一致;7 个物理键(1/2/3/4/7/8/9)动作正确;状态灯位掩码逐位一致、LED 0 恒亮;屏板 ≈5000 s 自复位不误判离线;LOGO 下发后断电重启仍在;网络通道:INIT 应答 16 B 逐字段一致且无颜色字段、LCDMEM 偏移 0 得 3204 B、重复召唤无应答、偏移 ≥3200 无应答、KEEPLIVE 无应答且 1 分钟不掉链、8 键(含 F1|ENT 组合)动作正确(§5.16.10 十五条)

9.13 屏板链路复刻任务规划

口径:条目一律用语义短语(编号规范 P-8),执行序即表序。 改动范围只含本产品固件与 DTU-RemoteLCD 客户端;屏板固件不在本仓库, 其行为以 §5.16 为契约做黑盒验收。

两种部署形态,两条通道都要:① 串口直连屏板(参考的形态,第 1015 条)——屏板直接挂在设备 串口上,无需任何网络设备;② 串口服务器透传 / 网络镜像(第 29 条)——屏板或调试软件经以太网连 7003。 现场用串口服务器把屏板接到网上时,两种形态等价,但固件侧不能只实现后者: 只有 7003 时,设备离开网络就没有任何本地显示,与参考产品不等价。

方向相反,别写错:网络通道是"客户端召唤、设备应答";串口通道是"屏板召唤、设备应答"。 两条通道共用同一份显存快照,但帧格式、校验、时序完全不同(网络用 0xAA/0xBB + XOR, 串口用裸二进制 + CRC-16/MODBUS),不能共用组帧代码。

执行细则另立:逐项任务的改动点、判据、代码骨架、台架联调步骤与风险清单在 docs/任务规划/屏板链路.md;本节只保留需求视角的缺口与顺序,不复制执行细节。

序 任务 改动点 判据 跨端
1 报文口径定版 本节 + §5.16 + §6.2 按参考源码成文 文档门禁全绿(已完成) —
2 INIT 应答补足 16 字节 ui_net_sink.c 的 remo_send_init() 组帧由 8 B 扩到 16 B:补 8 B 键值表;不加颜色位与 RGB(单色屏不对齐多色协议,§5.16.5) 16 B 逐字节比对通过,且报文内无颜色字段 是
3 键值表补 F1 / F2 ui_net_sink.h 键值宏补 0x04 / 0x80;ui_net_sink_inject_key() 映射;UI 键处理接受组合键 下发 0x04 / 0x80 / 0x24 界面响应正确 否
4 显存断点续传 CMD_LCDMEM 分支去掉"仅偏移 0"限制:按偏移取 g_ui_fbuf + off,长度 min(9800, 3200 − off) off=1600 得 4+1600 B,内容与整帧尾部逐字节一致 否
5 召唤拒绝握手 新增"帧代次 + 已上送"等价状态:新图未就绪时重复召唤不应答;偏移 ≥3200 不应答 §5.16.10 第 2、3 条通过 是
6 链路监视 1 分钟通信中断计时(收到帧 / 发送成功即重置);超时置状态位并落一行日志 断链 60 s 有明确日志与状态;重连后自动恢复推流 否
7 KEEPLIVE 静默 去掉空帧回显,改为仅重置计时 §5.16.10 第 4 条通过 是
8 发送重试评估 对比参考"BUSY + 200 ms 放弃"与现有 net_send 阻塞模型,出结论并回填 §5.16.9 第 7 行 结论有实测数据支撑(实现 / 明确不实现) 否
9 客户端一致性回归 DTU-RemoteLCD 按 16 B 解析;把 §5.16.10 第 1~7 条做成自动化用例 七条判据全 PASS 是
10 串口物理层落地 按 §5.16.2 定版:700000 8N1、BRR = 0x0078(USART1,APB2 84 MHz)、无 DE(TTL 直连,不走收发器)、RX 缓冲 16 B + 空闲中断断帧、发送走 DMA 一次性发完(禁逐块阻塞,DMA2_Stream7 TX / DMA2_Stream2 RX 已在 .ioc 配好但控制台未用) 环回 + 示波器实测 700 kbaud 分频零误差;屏板能收到帧 A 并回帧 B 否
11 帧 A 解析 / 帧 B 组帧 新增屏板通道模块:识别 6 B 请求(01 03 type key CRC_H CRC_L)、校验 CRC-16/MODBUS(高字节在前);组 4208 B 帧 B(3200 显存 + 4 B LED + 4 B info 保留 + 998 B 填充 + 2 B CRC) 屏板出图与 g_ui_fbuf 逐字节一致;info[0..3] 与下发的 LED 掩码一致 否
12 状态灯位映射表 定义"业务状态 → 屏板 LED 位"映射(参考源码无此表,须自定);info[0..3] 按 32 位小端填,bit0 恒 0、bit20~31 恒 0 §5.16.10 第 11 条通过 否
13 串口上行按键 帧 A 的 key 字节按屏板 KEY_TYPE 解释——实际可达值只有 1/2/3/4/7/8/9(5/6/10 无物理入口);映射为逻辑键值后与 7003 注入同一入口合并 §5.16.10 第 10 条通过;9/10 语义按 §5.16.3 ② 处置 否
14 双通道并发 + 自复位容忍 两出口各自独立发送上下文;串口 4208 B 阻塞不拖 7003;链路监视按"连续 ≥10 s 无应答"判离线,忽略屏板 ≈5000 s 周期自复位 §5.16.10 第 12、13、14 条通过 否
15 LOGO 下发流程 一次性下发 LOGO 帧(info[4..5] = 0x89 0x45,宽高大端);放在出厂 / 联调流程,不进常规刷新循环 §5.16.10 第 15 条通过;断电重启后 LOGO 仍在 否
16 日志口迁移(USART1 → RS-232 通道) ① console_log.c 的 huart1、USART1_IRQn、__HAL_RCC_USART1_CLK_*、MX_USART1_UART_Init() 收口成一处端口宏,指向 RS232#3(huart2 / USART2,默认)或 RS232#1(huart5 / UART5);② 该实例改 UART_MODE_TX(只发不收,避免重演 ORE 锁存);③ 不动 UART4 的 g_rs485 绑定 日志在 RS-232 侧(CN1)可读且内容与迁移前一致;USART1 完全空出;连续 10 分钟无 ORE 锁存、无 [ERR] 否

批次划分:

批 任务 理由
第一批(无跨端风险,可独立发版) 3、6、8 只动本端,旧客户端不受影响
第二批(跨端,须与客户端同步发版) 2、4、5、7、9 报文口径变更,两端必须同版本
第三批(独立立项,不随 RS-485 冻结) 16、10、11、12、13、14、15 屏板串口通道是独立需求,与 §5.10 冻结的"对下采集簇"不是一回事。第 16 条必须排在 10 之前:日志不腾出 USART1,屏板链路就没法独占这条通道(两者共用同一个 USART1->DR,同时用就是互相插字节)

⚠ 唯一破坏性变更:第 2 条把 INIT 应答从 8 B 改成 16 B。旧客户端会把 16 B 的前 8 B 当全部、 把后 8 B 当作下一帧的 TAG 去找,解析状态机会被这 8 B 拖住直到超时——表现为"连上了但不出图"。 因此第 2、5、7、9 条必须同批发布,且发版说明中明确"客户端需升级"。

⚠ 16 B 与参考的 29 B 不可互换:删掉 13 B 颜色字段后,偏移 4 之后全部前移—— 参考的"显存大小在偏移 5、键值表在偏移 21"在本产品变成"偏移 4、偏移 8"。 客户端不得复用参考的 29 B 解析器再截前 16 B(会读出颜色位当显存高位)。

屏板固件边界:本表不覆盖屏板侧固件(帧解析 / 显存写入 / 按键扫描 / 状态灯驱动)。 屏板固件工程在 D:\Code\DTU Code\DTU-LCD,不在本仓库,其契约已按源码逐字节成文(§5.16.2 / §5.16.3)。 本产品只要满足 §5.16.10 的十五条判据即为兼容。

第三批的前置阻塞:第 11~15 条需要屏板实物才能验收(无实物只能做到"帧发出去了")。 第 11 条的帧长仍有一处待实测复核——代码实参是 4208 B,屏板 readme 写 3208 B(§5.16.2); 台架抓到第一帧真实报文后立即固化,在此之前以代码实参为准,不得按 readme 实现。

一条物理前置 + 一条实现纪律: ① 台架串口线挪位——现在的 CH340/COM6 接在 USART1 调试口上,日志迁到 RS-232 侧后 必须改接到 CN1(或 U14),否则 @test 与 serial-assistant 全部抓不到日志,等于把台架弄瞎。 这条要在第 16 条动代码之前完成。 ② RX 要真的读、ORE 要真的清——PA10 一直是接线的(原"未接线"结论已撤销,§5.16.2), 但"RX 使能却不读 DR"本身就足以让 ORE 永久锁存。第 11 条实现时必须在 HAL_UART_ErrorCallback 里清 ORE 并重挂接收,否则一次噪声就永久静默。

已消解的旧阻塞:原"屏板协议拿不到、不得按猜测定契约"的告警不再适用——物理层、帧格式、 键值、状态灯、时序均已从 DTU-LCD 源码确定。剩下的只是"实物联调确认",不是"协议未知"。


10. 验收判据

10.1 构建与静态门禁

项 判据
构建 @build → BUILD_OK: 0 errors, 0 warnings(退出码 0)
静态门禁 pre-commit run --all-files 全部通过(钩子族见 §7.4)
主机侧单测 全部套件全绿(看门狗、时钟、配置、相量、采集层、标定、遥测、测频、定值、元件、运行参数、104、SOE 等;套件与断言数随代码演进,以 .pre-commit-config.yaml 与 test/host/ 为准)
栈门禁 scripts/stack_report.py 9/9 PASS(余量 ≥ max(1024 B, 30%))
体积门禁 check_size_gate.py --ci PASS(体积凭证与 git 索引一致)
双端构建 Keil 与 CMake 均 0 错 0 警
UI 回归 菜单行 + 内容页像素黄金 + 导航自检全 PASS

10.2 上电自检(@test)

层 判据
Required 标记(基础) App init OK / Network Init / net init: OK / PHY: 100M FULL
Required 标记(采集链,可选启用) ADC input layer init: OK / phasor(first) / freq(hb)(顺序锚点 App init OK>phasor(first)>phasor(hb))
Required 标记(保护链,可选启用) protect task start / set=40 elm=9 计数锚
Required 标记(104,可选启用) [I104] 监听/接入行
Forbidden 标记 无 FAIL / ERROR / HardFault / [ERR](四个 Fault 的崩溃日志都以 [ERR] 开头,出现即不通过)
自检记录 selftest: no fault record
固件身份 fw build 身份戳匹配 + 烧录后回读 No difference found
退出码 @test → 0(PASS)

10.3 现场验收清单

# 项目 方法 通过标准
1 上电自启动 断电上电 + 串口采集 @test PASS,无 Forbidden 标记
2 网络连通 PC ping 设备 IP 通(PHY 100M FULL)
3 远程显示 DTU-RemoteLCD 连 7003 出图(160×160 1bpp)+ 远端菜单导航可用
4 FTP FTP 客户端连 :21 列目录 / 读写 / 下文件
5 UI 功能 远端操作 菜单 7 项导航、内容页、密码(查看 000 / 修改 123)、网口设置保存后立即生效
6 对时 PC 推送 8888 设备墙钟更新、日志时间戳正确
7 掉电保持 写文件 / 改网口配置 / 改定值 → 重启 数据仍在(/config.ini、/prot_set.bin 按新值生效)
8 LED 状态 目检 6 路 LED 随系统状态变化(低电平点亮)
9 104 总召与变位 PC 主站连 :2404 → STARTDT → 总召 四组数据回全、actterm 正常;制造变位后 COT=3 上送
10 104 遥控与定值 YK12 软压板投退、C_SE 写定值 两段式正答、压板行为可观测、定值跨复位保持
11 保护闭锁态 未标定状态下观察 YX31 与日志 判据停走且明确可见(不得静默不动作)
12 记录可追溯 FTP 下载 /log/soe.log、/log/run.log、/log/selftest.log 记录连续、时标正确、解码校验通过
13 屏板链路一致性 串口屏板 + TCP 客户端同时接入,按 §5.16.10 十五条逐项验证 串口侧:275 ms 召唤 / ≤200 ms 回 4208 B、显存 3200 B 逐字节一致、状态灯 4 B 掩码逐位一致、7 键动作正确、自复位不误判离线;网络侧:INIT 16 B、重复召唤 / 越界无应答、KEEPLIVE 静默、8 键(含组合)动作正确

10.4 台架验收(已闭环)

用例 内容 结论
V2 任务饿死 → IWDG 复位 ✅ 800 ms 声明 stall,≤2.5 s 复位(reset cause: IWDG)
V4 关中断死循环 → IWDG 复位 ✅ 每 ~4.9 s 稳定复位(IWDG 独立于中断)
V5 30 min 真实负载长跑 ✅ 120/120 FTP PASS,零 IWDG 复位
堆分配改造 配置引擎堆分配改造(真机) ✅ [CFG] load: OK(经 FreeRTOS 堆);FTP 改 IP 复位即生效
存储/网络套件 16/16 PASS ✅
采样节拍与相量 帧号 1000 Hz、5 实例产出、双区刷新 ✅ 2026-10-11
ADC 前端注入 已知电压注入:零点 / 线性 / 斜率 / 映射 / 极性 ✅ 2026-10-27 五项 PASS(斜率偏差 −0.14%,R²=0.9999997)
104 主站往返 STARTDT / 总召四组 / 变位 / 遥控 / 定值读回 ✅ 2026-10-12 18/18 PASS
定值与压板持久化 YK12 投退 + 非默认定值跨复位 ✅ 2026-10-12 21/21 + 13/13 + 4/4 + 4/4 PASS
SOE 落盘 自发 M_SP_TB_1 带时标 + FTP 下载解码 ✅ 2026-10-12 56 条记录全 PASS

11. 相关文档

主题 文档
文档索引 docs/README.md
项目全景架构 docs/架构设计/项目架构总览.md
存储架构 docs/架构设计/STM32F4-Base存储架构说明.md
启动顺序 / 就绪屏障 docs/架构设计/项目启动顺序管理.md
配置引擎 docs/子系统设计/配置文件设计说明.md
网络配置 docs/子系统设计/网络配置说明.md
墙钟时间 docs/子系统设计/系统墙钟时间维护说明.md
运行/自检记录 docs/子系统设计/运行与自检记录设计说明.md
控制台单写者日志 docs/子系统设计/控制台单写者日志设计说明.md
看门狗 docs/子系统设计/看门狗设计说明.md
BSD Socket API docs/网络/BSD_Socket_API_使用指南.md
Net 层阻塞模型 docs/网络/Net层阻塞模型架构设计.md
UI 架构 docs/UI设计/UI_设计架构.md
菜单页面 docs/UI设计/菜单页面设计.md
内容页 docs/UI设计/内容页架构.md
远程显示协议 docs/UI设计/RemoDispBus协议与接收设计说明.md
采集与算法层(语义取数与有效性~保护判据) docs/算法/采集与算法层设计说明.md
保护功能复现规划(产品定义 / 定值 / 路线) docs/算法/继电保护功能复现规划.md
全周傅氏算法原理 docs/算法/傅氏算法详解.md
采样有效性校验 docs/算法/采样有效性校验设计说明.md
ADC 采样节拍与 DMA docs/子系统设计/ADC采样节拍设计说明.md
ADC 通道映射与实测 docs/硬件平台/ADC通道映射说明.md
ADC 前端注入验证流程 docs/测试说明/ADC前端注入验证流程.md
IEC 60870-5-104 上行 docs/子系统设计/IEC104上行设计说明.md
数据可信(标定 / 快照 / 运行参数) docs/任务规划/数据可信.md
页面补齐规划 docs/UI设计/页面补齐规划.md
编号规范 docs/编号规范.md
部署环境 docs/环境与部署/项目部署环境要求.md
硬件网表 docs/硬件平台/V0.1_网表详细分析报告.md
待办登记簿 docs/任务规划/README.md
实机测试指南 docs/测试说明/实机测试实施指南.md
测试标准流程 docs/测试说明/测试开发标准流程.md
RAM 预算与优化 docs/内存管理/RAM使用分析与优化方案.md
AI 开发规范 AGENTS.md(仓库根)
开发者入门 README.md(仓库根)

12. 变更记录

日期 变更 说明
2026-10-05 初版 基于项目全量内容(架构 / 子系统 / UI / 测试 / 硬件网表 / 待办)编写完整产品需求设计文档:产品定位、六层架构与任务模型、V0.1 硬件规格、10 类功能需求(含 2 项待实现)、接口规范、非功能需求、UI 规格、待实现项与路线图、验收判据
2026-10-10 FR-CFG-4 旧档迁移取消 删除旧固件 /cfg/netcfg.bin(NCFG 二进制)的首启自动迁移:旧档若存在则被忽略(不读、不删、不迁移),配置回落工厂默认。理由:该一次性路径把整条配置写链挂进启动期调用图,defaultTask 静态最坏栈链 +600 B,而本仓库不存在携带旧档的设备;net_cfg_legacy.c/h 与 cfg_store_legacy_path() 一并移除。§7.1「掉电不丢配置」同步
2026-10-27 v1.1 全面刷新(以参考产品 CLS100 为横向基准) ① 新增 §2.5「与参考产品 CLS100 的能力对照」(12 个能力域逐域给出参考实现 / 本产品现状 / 结论),并据此重写 §2.1 现状口径与 §2.4 产品范围(分"已验收 / 已实现但受制约 / 非本期"三档);② 新增 §4.6「V0.1 硬件能力边界」(H1 双转换器无共同采样触发 / H2 无中点偏置 / H3 无出口开入 / H4 无本地屏 / H5 无 SDIO)作为范围裁剪的硬依据;③ 任务模型由 6 任务更正为 9 任务(补 adcTask / iec104Task / protectTask,栈配置改为 words/B 双列),事件位补至 bit8,启动时序补配置段注册与 adc1_disable 铁律,线程间通信补双区快照 / SPSC 环 / 脏位;④ 功能需求新增五节:§5.9 ADC 采集与标定(FR-ADC,含标定折算与前端物理口径)、§5.11 遥测与相量(FR-MEAS)、§5.12 保护功能(FR-PROT,9 元件 + 四源闭锁)、§5.13 定值与运行参数(FR-SET)、§5.14 SOE 与动作记录(FR-SOE)、§5.15 IEC 104 上行(FR-IEC104,含点表推荐响应时间);⑤ 新增 §6.8 104 点表摘要,§6.7 对外 API 补 10 个模块;⑥ §7.2 补采样/相量/遥测/保护/上送七项实时指标,§7.3 内存与栈预算全部换为 2026-10-24 受管快照与 2026-10-22 栈快照,§7.4 门禁改为按族描述,§7.6 补 104 与配置面安全边界;⑦ §8 菜单绑定现状(22/33/42)与内容页分组重写;⑧ §9 改为「缺口总表(G1~G10)+ 推进顺序 + 未接线开关」,删除已闭环的 ADC/104 缺口;⑨ §10 验收补栈/体积门禁、采集与 104 锚点、六条现场项与五项台架闭环用例。本次只改本文件
2026-10-27 v1.2 改为 1:1 复刻口径(以参考工程源码为唯一清单) ① 范围口径反转:产品范围由「按硬件裁剪」改为「参考源码能力全集」,差异只允许来自 5 项物理不可移植项(X1 双核分工 / X2 VxWorks / X3 本地屏 / X4 一次设备接口 / X5 计量通道,§2.4.1);② §2.5 由「12 域能力对照 + 取舍依据」重写为 「1:1 复刻基线」,判定依据从参考项目的分析文档改为 参考工程源码的常量表与模块文件(§2.5.1 三要素:点表即契约 / 地址即接口 / 模块即元件);③ 新增 §2.5.2 19 项能力清单(源码实测):定值 249 项 / 23 单元(g_tSetModelTab)、104 定值映射 107 项 0x8820~0x8891(g_tCommSetParaTab)、遥测 31、遥测模型 35、电度 8、开入 138、开出 31、动作事件 33、录波通道 65、软压板 9、保护元件 45 模块、记录队列 13 类、自检 3 类型、录波 3 类型 / 6 段、规约 12 种、加密 SM2/SM3/ECDSA;④ 新增 §2.5.3 104 地址空间 8 段表并 更正段基址笔误——参考 Rly_IEC104.h 为 1 起编,遥测 0x4001、遥控 0x6001(v1.1 及更早写 4000H+ / 6000H+),§5.15 与 §6.8 同步更正;⑤ 新增 §2.5.4 定值 23 单元分布表(WatchDog 63 / SYS3 45 / VolTimeRecv 17 / AutoReCls 16 …,并说明枚举 28 个中 4 个表内无项的原因)与 §2.5.5 45 元件九类归集表(含 PRS_OverCurrent.c 判据结构对照);⑥ 新增 §2.5.6 规约全集 13 行表(对上 9 种 / 对下 3 类 / 加密)与 §2.5.7 差异归因表,结论改为「差距全部是进度而非范围」;⑦ §9 重写为「复刻进度与路线图」:删除全部「不做」表述,缺口分 阻塞型(标定闭锁 / 出口与开入 / 三相与同期 / 电度计量 / 对下采集 / 第三方送检)与 规模型(定值 40→249、映射 40→107、元件 9→45、录波子系统、规约 1→12、国密等)两表,条目一律用语义短语命名以免与其它文档的 S/A/P 编号族撞名(编号规范 P-8),推进顺序补「点表铺开必须晚于标定」铁律;⑧ §2.1 产品定位补 1:1 复刻目标与三项差距量化(定值 40 vs 249 / 遥测 9 vs 31 / 开入开出 0 vs 138·31);⑨ §6.8 点表摘要逐段补「与参考的差额」说明(遥测缺第二回线与线电压、遥信缺 138 点开入、定值缺整单元)。本次只改本文件
2026-10-28 v1.3 缺口逐项细化(新增 §9.4~§9.12) ① 定值:给出 40 项去向对账(覆盖参考 35 + 本地扩展 5),差额由「+209」更正为 +214 项;新增 23 单元逐单元差额表、已覆盖 35 项逐项对照(过流三段每段缺方向 / 低压 / 告警 / 低压定值 4 项;零序过流三段 18 项全缺,注意 PS_3U0_* 是零序过压不是过流;三级负荷只做一级;频率缺「跳闸投退」;电压缺 4 项跳闸 / 告警投退;PT·CT 缺 6 项)、完全未覆盖 163 项逐项清单(SYS3 45 / VolTimeRecv 17 / AutoReCls 16 / SYN 13 / WAVESTART 12 / MeaLimit 10 / OverCurSpeed 8 / OverCurI0 13 / 小单元 29);② 遥测:31 点逐点对照,缺 22 点按依赖分三批(线电压与功率 13 / 第二回线 7 / 直流 2),指出「三相电压全落 TPAFE」可一次解锁 6 个线电压点;③ 开入开出:138 = 软遥信 104 + 硬件 27 + 双点 6 + 多态 1,澄清「104 点 ≠ 104 个端子」;31 开出 = 出口 11 + 信号 20;④ 动作事件:33 条(421~453)逐条对照,覆盖 9 条;记录参考源码 428/429 同名需按事件码区分;⑤ 保护元件:口径改为模块级 45 → 8,37 个缺失模块逐个给出「缺它的后果 + 依赖」,差额由「+35」更正为 +37,指出 MusterRecov 总复归是唯一无硬件依赖、可立即开工的元件;⑥ 录波:14 项硬指标(80 点/周波 = 4000 Hz、6 段、前 5 后 10 返回 2 手动 6 周波、9000 ms、RAM 16、COMTRADE 64/64/16、65 通道)与复刻所需四件东西;⑦ 记录体系:13 类队列容量表,覆盖 8 类,缺越限 / 闭锁 / COS / 顺控 / 顺控执行;指出「闭锁记录」性价比最高(四源闭锁已全实现却无留痕);⑧ 规约栈:12 种逐种链路 / 用途 / 工作量特征 + 四层排期,指出对上与对下是两套角色;⑨ 新增 §9.12 复刻完成判据(12 条可验证判据)。本次只改本文件
2026-10-28 v1.4 屏板链路口径更正 + 逐字节复刻规格(新增 §5.16、§9.13) ① 口径更正:v1.3 及更早把参考写成"板载 LCD + 按键"、把本产品远端推流说成"等价替代",两处都错。参考源码中主机侧 5 个碰硬件的函数(KeyGet / WriteScreenByByte / LCD_LED_Update / getRs485Key / anyNewKey)全树只有声明没有实现,按键轮询函数名为 Key_Rs485_Process()(注释"轮询从485传来的按键值"),屏板插槽号 CN_SLOT_DISP = 0(注释"显示板插槽号固定为0")——参考的屏和键同样在独立板件上、同样靠链路传输,本产品与之同构而非替代;§2.4.1 X3 由「本地人机」改为「就地屏板(板件本体)」,并补口径更正说明段;② §2.5.2 补第 20 项「远端屏与按键链路」(状态 🔶),能力计数 19 → 20 项、🔶 9 → 10 项,§2.5.7 差异归因同步(X3 不再计为"已用等价方案替代");③ 新增 §5.16 远端屏与按键链路(FR-HMI):两条链路对照(RS-485 屏板通道 / TCP 7003 总线)、帧格式逐字节、CRC 覆盖范围、接收定界算法、INIT 应答 29 B 逐字段偏移表、键值位掩码语义、bNeedFlash 续传与拒绝语义(-1 / -2)、按键状态机与合并优先级、三个定时器(500 ms / 1 分钟 / 200 ms)、发送状态机、0x55/0xaa 刷新互斥、任务参数(prio 111 / 栈 0x35000);④ §5.16.9 给出 10 项与参考的差异,其中 5 项为客户端可见的报文口径差(INIT 8 B vs 29 B 为最大一条);⑤ §6.2 按参考源码重写:更正 INIT 应答长度(原写 8 B)、KEEPLIVE 改为不应答(原写"原样回显")、补最长帧 9800 B / 收发缓冲 10240 B / 按键码补 F1·F2 与位掩码可组合说明;⑥ 新增 §9.13 屏板链路复刻任务规划:10 条语义短语任务 + 三批划分 + 唯一破坏性变更警示(INIT 长度变更必须与客户端同批发版);⑦ §9.1.2 补「屏板链路对齐」行、§9.12 补完成判据、§10.3 补现场验收第 13 项。本次只改本文件
2026-10-28 v1.5 补串口屏板通道(显示信息不只走网络) ① 口径再更正:v1.4 把串口通道写成"链路 A,随 RS-485 簇冻结",等于把它降级成可选——错。参考的架构是一份显存、两个出口:串口屏板通道是主通道(LCD_LED_Update(显存 3200 B, LED 4 B) 变化驱动 + WriteScreenByByte 500 ms 兜底),TCP 7003 是镜像;上行同理(getRs485Key() 物理键号 1~10 为主,g_tRemoteKey 为镜像,两者在 Key_Read() 汇合且本地优先)。§5.16 标题改为「屏板链路:串口主通道 + 网络镜像」并重写开篇;② §5.16.1 重写为「一份显存、两个出口」:显存物理基址 CN_VIDEO_ADDRESS_BASE = 0xC1F00000(非 cache 区)、三条下行路径与两条上行路径的归属任务 / 调用 / 载荷 / 节拍对照表;③ 新增 §5.16.2「本产品的串口通道(待建)」:V0.1 串口资源盘点(USART1 调试占用 / UART4 被冻结 RS-485 占用 / UART5、USART2、USART3 空闲),默认选 USART3(PB10/PB11),若屏板为 RS-485 半双工则改 UART4 并先解冻该簇;④ 新增 §5.16.3「参考实现的屏板侧接口一览」,并明确列出交付源码推不出的四项(波特率与数据格式 / 帧头与校验 / 半双工方向控制 / 3200 B 是否分片与应答)——在拿到实测前不得声称"按参考协议实现";⑤ §5.16.9 差异表由 10 行扩到 14 行,新增「串口屏板通道整条缺失」「双出口并发缺失」「面板指示灯语义不同」「背光对比度」四项,并注明第 11/12 条是整条链路缺失而非报文细节;⑥ §5.16.10 判据由 7 条扩到 12 条,新增串口侧 5 条(键号注入 / 500 ms 内出帧 / 双通道并发不丢帧不串帧 / 拔插恢复 / 背光);⑦ §9.13 任务由 10 条扩到 13 条:原「RS-485 屏板通道」一条拆为「串口通道物理层定版 / 串口下行显存 / 串口上行按键 / 双通道并发回归」四条,批次表第三批改为独立立项、不随 §5.10 冻结,并补前置阻塞(需屏板实物验收;拿不到固件或抓包时不得把猜测定成契约);⑧ §5.16.8 tTimerLCD 行由"此路不实现"改为"串口通道周期兜底节拍(待建)",§2.5.2 第 20 项、§9.1.2、§9.12、§10.3 同步。本次只改本文件
2026-10-28 v1.6 屏板源码到手:串口通道协议定版 + 状态灯下行 ① 屏板固件已获得(D:\Code\DTU Code\DTU-LCD,STM32F103ZE + UC1698U 160×160 单色 + 20 路状态指示灯 + 7 个物理按键),v1.5 列的"四项未知"全部消解;② §5.16.2 重写为「串口通道:物理层与帧格式(屏板源码实测)」:700000 8N1(APB1 42 MHz 分频零误差、BRR = 0x3C0)、软件 DE、角色反转(屏板是 Modbus 主站、主机是从站 0x01)、帧 A 6 B 召唤(01 03 type key CRC_H CRC_L,KEY_CMD=0 / RT_CMD=1,CRC-16/MODBUS 只覆盖前 4 B、高字节在前)、帧 B 4208 B 图像应答(3200 显存 + 4 B 状态灯 + 4 B info + 998 B 填充 + 2 B CRC,覆盖 [0, 4205])、时序 275 ms / 200 ms / 5 次超时、200 ms 预算下 4208 B 约 60.1 ms(占 30 %)、主机端口默认 USART3 + 另配 DE GPIO(不必解冻 UART4);③ §5.16.3 重写为「屏板侧行为:状态灯 / 按键 / 背光 / LOGO」,新增状态灯下行:info[0..3] 为 32 位小端位掩码、ID 0 = 电源灯硬件常亮、ID 119 对应 bit119,给出 20 路 LED 引脚表,并指出"位 → 业务状态映射表参考源码没有、须由本产品自定";键值 KEY_TYPE 表(0 无键 / 1 ENTER / 2 UP / 3 DOWN / 4 ESC / 5 ADD / 6 DEC / 7 LEFT / 8 RIGHT / 9 RESET / 10 FACTORY),并指出与参考主机 getRs485Key() 的 9 / 10 语义冲突(参考是 F1 与 F1+ENT)、key_configs[] 仅 7 项且无 ADD/DEC 入口;背光自管、LOGO(Flash 0x0803F000、魔数 0x89 0x45)、屏板健壮性(CRC 错 ≥3 仅清计数不自愈、≈5000 s 自复位、DMA 接收问题未解决);④ §5.16.9 差异表第 8 / 11 / 12 / 13 / 14 行按屏板实测重写,并新增"来自屏板固件的新增约束"5 条;⑤ §5.16.10 判据由 12 条扩到 15 条(275 ms 召唤 / ≤200 ms 回 4208 B、显存逐字节、7 键、状态灯逐位、双通道并发、自复位容忍、拔插恢复、LOGO 下发);⑥ §9.13 任务由 13 条改为 15 条:第 10 条由"物理层定版"改为"串口物理层落地"(参数已定)、新增第 12 条"状态灯位映射表"与第 15 条"LOGO 下发流程"、第 14 条并入"自复位容忍",批次表第三批改 10~15 并注明不必解冻 UART4,删除"拿不到固件不得定契约"告警(已消解),保留"4208 vs 3208 待台架复核";⑦ §5.8 补屏板 20 路指示灯与主板 6 路 LED 是两套独立输出;§5.6 FR-UI-1 改为"双出口推流";§6.2 口径注改为"串口通道是 Modbus RTU 风格裸帧、不能共用组帧代码";§2.4.1 X3、§2.5.2 第 20 项、§5.16.1、§5.16.8 tTimerLCD 行、§9.1.2、§9.12、§10.3 第 13 项同步。本次只改本文件
2026-10-28 UI 现状同步(不 bump 版本号) ① 绑定叶数 22→28、未绑 11→5(记录 5 页与运行报告页落地绑页,§8.2 / §8.3 / §9.2);② 像素黄金 53→60 页(新增 7 张,含运行报告第 2 页);③ 字库当前态改 218 唯一字 / 313 字形(122/217、179/274、185/280 均为历史快照,§8.5);④ FR-SOE-3 由「展示层待补」转「软件面已落地,真机判据待台架」(§5.14);⑤ §2.4 立项未排去掉已交付的「记录 5 页」、§9.1 差距表 UI 记录页行改写现状与去向。真机判据登记 docs/任务规划/登记簿.md §7;模拟器结构性照不到的部分见 docs/测试说明/模拟器差距清单.md §2.3。
2026-10-28 v1.7 单色口径:删除多色协议,INIT 由 29 B 改 16 B 用户裁定"屏幕板都是单色的,多色协议可以删除、不必对齐"。核查后确认这不是让步,而是删死字段:① 三处源码证据——RemoDispBus.h:46 CN_RDISP_TYPE_MONO = TRUE → CN_RDISP_LCD_TYPE = CN_MODE_GREY_MONO、CN_RDISP_MEMSIZE = (X>>3)*Y(链路显存本就是 1 bpp);RDisp_Form_InitInf 里 CN_RGB_RED/GREEN/BLUE 是编译期常量而非逐帧数据;RDisp_LcdColor_To_Mono() 对 CN_MODE_GREY_MONO 直接 return TRUE 不转换,真正干活的 RDisp_Lcd16B_To_Mono()(RGB565→单色)挂在 CN_MODE_COLOR_16B 下本构建永不进入(死代码);② §5.16.5 INIT 应答表由 29 B 重写为 16 B(宽 2 + 高 2 + 显存 4 + 8 键值表),删掉 1 B 颜色位 + 12 B RGB,并补"为什么是 16 B"的证据块;③ §6.2 命令集 INIT 行同步改 16 B 并加"单色口径"注(颜色位与 RGB 整段删除、RDisp_LcdColor_To_Mono() 不存在);④ §5.16.6 第 6 条注改为"该函数在参考单色构建下就是空转",避免误以为本产品漏了一步转换;⑤ §5.16.9 第 1 行由"补 21 B"改为"补 8 B 键值表 → 16 B,颜色 13 B 不对齐";"新增约束"补"单色"一条;末尾警示改为 16 B vs 29 B 不可互换(从偏移 4 起含义即不同,客户端不得复用参考 29 B 解析器截前 16 B);⑥ §5.16.10 判据第 1 条改 16 B 且"不得出现颜色位或 RGB";⑦ §9.13 第 2 条改"INIT 应答补足 16 字节 / 不加颜色位与 RGB"、第 9 条客户端按 16 B 解析、破坏性变更警示改 16 B(后 8 B 而非后 21 B)并补"不可与参考 29 B 互换";⑧ §2.4.1 补"多色显示不在本表内"——参考与本产品都是单色链路,删的是死字段,不属于"决定不做"的能力;§2.5.2 第 20 项、§9.1.2、§9.12、§10.3 第 13 项同步;⑨ §8.1 色深行补"无灰度、无彩色,7003 INIT 颜色字段已删",渲染行改为"串口屏板通道(主)+ TCP 7003(镜像)双出口"。本次只改本文件
2026-10-28 v1.8 端口重排:屏板占 USART1,日志迁 RS-232 通道 用户裁定"把现在的日志 UART 让给屏幕,RS-232 通道后面用来输出日志"。这条裁定把 v1.6/v1.7 的头号阻塞直接消掉了:① §5.16.2 新增「端口裁定」块——屏板改走 USART1(PA9/PA10,MCU 直出 TTL、不经任何收发器),因此 U15 = TP8485E-SR 只有 250 kbps 这件事对屏板链路不再构成约束;日志迁 RS-232 通道(V0.1 板上 RS232#3 = USART2 PD5/PD6 为默认,RS232#1 = UART5 PC12/PD2 为备选,两者都经隔离器 → U13 TPT3232E → CN1);② 纠正分频算法——旧文写"42 000 000 / 700 000 = 60 → USARTDIV = 60.0、BRR = 0x3C0"漏了 16 倍过采样,照此写实际波特率只有 43 750;正确值:USART1(APB2 84 MHz)USARTDIV = 7.5 → BRR = 0x0078,APB1 实例(42 MHz)USARTDIV = 3.75 → BRR = 0x003C,两者误差均为 0;③ §5.16.2「主机侧端口选型」整表重写为「主机侧端口重排」,按 docs/硬件平台/V0.1_网表详细分析报告.md §4.2 的三对 UART 轮换列明 RS485#4 = UART4(DE = PA15)、RS232#1 = UART5、RS232#3 = USART2,并补两条实现约束(console_log.c 里 huart1 5 处 + 自愈函数直写 USART1_IRQn / MX_USART1_UART_Init() 需收口成一处端口宏;新日志口必须 UART_MODE_TX,否则重演 ORE 锁存);④ DE 口径改为「TTL 直连无 DE」,仅"经外部 485 模块接 A/B"时才需处理,且极性由该模块决定;⑤ 主机 RX 口径由"吃下 4208 B"改为"只需 6 B(16 B 缓冲够)",并说明 TTL 直连无自发自收;⑥ §4.2 外设接口表:USART1 行补"端口重排后改作屏板链路 + PA10 目前未接线",新增 USART2(RS-232 #3,日志口)与 UART5(RS-232 #1,备选)两行,UART4 行注明 V0.1 轮换依据;⑦ **§5.16.9「新增约束」**与 §9.12 的 700000 行同步为"USART1 TTL 直连、无 DE";⑧ **§9.13 新增第 16 条「日志口迁移」**并置于第三批首位,批次表注明 16 必须排在 10 之前(两者共用 USART1->DR);第 10 条改为 BRR = 0x0078、无 DE、DMA2_Stream7/2 现成;前置阻塞补两条物理前置(PA10 接线、台架串口线从 USART1 挪到 CN1)。本次只改本文件
2026-10-28 v1.9 撤销"PA10 未接线",ORE 机理改正 用户反馈"PA10 这个端口我接线了,当时分析出这个问题来,我怀疑是错误的"。核查后确认:App/log/console_log.c(文件头与 con_uart_reinit() 注释)与 docs/子系统设计/控制台单写者日志设计说明.md §12 里的"PA10 悬空 / 未接线"是 2026-10-02 的归因推断,不是实测,且与用户确认的接线状态相反。改动:① §4.2 外设接口表 USART1 行删掉"PA10 目前未接线、作屏板链路前必须接上",改为"PA10 双向均已接线";② §5.16.2 原"USART1 的 RX 目前没有接线"警示块整段重写为「旧结论已撤销 + ORE 真正机理」——ORE 的充分条件是RX 使能却从不读 DR(任意一个字节或噪声沿使 RXNE 置位后无人读,下一个事件即锁存 ORE,且只能靠"读 SR 再读 DR"清除 ⇒ 永不自愈),与引脚悬空无关;据此补两条硬要求(屏板链路必须真的消费 DR 并在 HAL_UART_ErrorCallback 里清 ORE 后重挂接收;新日志口设 UART_MODE_TX 仍正确,因为那是从机制上摘掉 RX);③ §9.13 前置阻塞由"两条物理前置"改为"一条物理前置(台架串口线挪位)+ 一条实现纪律(RX 要真读、ORE 要真清)",并写明原"PA10 接线"结论已撤销;第 11 条的验收隐含"拔插 TX 线制造噪声后能自动恢复"。当年那场 ORE 风暴的真因仍待定——接线正常时更常见的是对端波特率不匹配或适配器 TX 在 USB 掉线时浮空,下次复现先量空闲电平与波特率,不要再默认"引脚悬空"。本次只改本文件
2026-10-28 像素黄金口径更正(不 bump 版本号) 正文两处当前态由「60 页」改报「60 张」:判据本体 = simulator/tests/ref/ 入库 shot_*.bin 实数 60 = check_content_pages.py 的 PAGES 条目数 60,其中 2 张是分页页多拍的第 2 屏 ⇒ 张数 ≠ 页数(同一句里「+7 张」与「60 页」并存就是口径混用的后果)。历史行 53 → 60 与更早的 27 / 40 / 47 一律按当日事实冻结,本行只追加。