Files
STM32F4-Base/App/algo/meas.h
T
wandering1 94b0d79026 feat(ui)+chore(docs): UI 补齐清单清空;数据可信销项与「卡」号清退
本笔含两组收尾工作(同一工作区内交错在 6 个共享文档/门禁配置里,
拆开会产生"文档声称的页数与树里黄金数不一致"的中间提交,故合为一笔):

一、UI 补齐(清单清空)
- 新建 6 个内容页模块:ui_page_accident / oper / alarm / start / yk
  复用 ui_w_records 共享组件(分页、空态"无记录"、按实例读盘缓存),
  记录层与五个写入点已由道F task-10 / 道G task-12 落地,本批只补页面;
  ui_page_runreport 为 13 行 2 页只读统计,四个数逐个挂范围标签
  (自电池周期 / 本次开机),boot_ready=0 显 "--" 不显 0。
- 数据面:ui_data_info_t 尾部追加 9 字段,ui_data_feed 用
  boot_stats_get() + iec104_serv_get_stats() 纯搬运;模拟器填确定值假数据
  (差异登记 docs/测试说明/模拟器差距清单.md §2.3 两行)。
- 接线:菜单树 6 叶绑 #page=,绑定叶 22→28、UI_PAGE_MAP_COUNT=28;
  字库 185→218 字 / 280→313 字形;双端注册 uvprojx +30、CMakeLists +6。
- 回归:内容页黄金 53→60(含 runreport_p2 真拍第 2 页),文本断言
  425 正向 / 36 反向;存量 53 张逐字节零漂移;记录 5 页各用独立空目录
  (模拟器把操作留痕写进 cwd 的 sim_oper.log,共用 tmp 会让空态拍不到)。

二、数据可信销项 + 「数据可信」任务卡号整族清退
- 删除已闭环的"已知电压注入验证"行与闭环结论块(证据在
  docs/硬件平台/ADC通道映射说明.md §8.1 与
  docs/测试说明/ADC前端注入验证流程.md §5~§7),§5 标识列改语义短语。
- 卡 0/0b/1~12 共 14 个号全仓 288 站点 / 56 文件清退成语义短语,
  代码注释、测试、门禁配置与文档一并改;换算表入 docs/编号规范.md §9.3。
  这一族是中文前缀,不进 check_ids 语料,刻意不入 id_aliases.json。

验证(实测)
- @build 0 错 0 警:Code=236456 RO=28124 RW=1876 ZI=137084;
  RAM +464 B(RW +304 / ZI +160),RW_IRAM1 62.2% / RW_CCM 87.9%,
  体积同码凭证与 RAM 台账已回填。
- check_menu_rows 8 状态 rc=0(池 5368/5448 常量未动);
  check_content_pages 60 页 rc=0;check_font_charset / registration /
  coding-standard / bom-drift / mojibake / doc-links --all / layer-deps /
  nested-comment 全 rc=0;check_ids --strict 无错误;主机单测
  ui_data 295 / boot_stats 21 / sys_log_mcu 141 / soe 32 / soe_store 27。

未做(不是遗漏)
- 六页真机判据(真记录翻页、掉电保持、清除后归零、boot_count 自增、
  拔 RTC 电池落 RESTARTED、IWDG 复位落 rst_cause、主站连一次 conn_up+1)
  已登记 docs/任务规划/登记簿.md §7;模拟器结构上照不到。
- docs/产品需求/产品需求设计文档.md 属另一条在飞改动,本笔不含;
  其中我已同步 6 处现状数字(28 叶 / 60 页 / 218 字),随该笔入库。
2026-10-28 07:23:16 +08:00

138 lines
8.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称:遥测快照发布层(L2 派生·发布侧,「数据可信」§4.5)
* 模块功能:每 **200 ms** 从 L2 层取一次基波有效值 + 品质,产出一份全仓唯一的
* 遥测快照(meas_snap_t,布局权威 = docs/任务规划/数据可信.md §4.5),
* 让 104 与 UI **共用同一份上游**——"什么时候算新值、品质怎么判"只此
* 一处决定(M5 遥测链的地基;104 侧消费见「数据可信」104 改读快照,UI 侧 ui_data_feed 属
* 「UI 扩展」波次,两者都只是本快照的读者)。
* 值口径(批 2「遥测快照发布」的 A-lite 裁决,2026-10-25):**基波有效值瞬时透传**
* (同拍 phasor 使用区口径,系数已在 L1.5 折算进帧值——现单位 = ADC
* 引脚电压 V,二次值语义等 adc_cal_flags() 出 VALID,见
* docs/算法/采集与算法层设计说明.md §10 红线③);**不做** 4 点平均 /
* 谐波方和根——docs/任务规划/数据可信.md §4.5 明示"200 ms 是上送节拍
* 不是平均窗,再平均引入滞后";谐波 k-bin 轨(docs/算法/继电保护功能
* 复现规划.md 遥测谐波轨(可选))将来扩展时只许在本结构**尾部追加**或留在发布侧
*(保护功能清单见 docs/算法/继电保护功能复现规划.md)
* 内部状态,既有字段序不得变更。
* TEMP 通道(「数据可信」决策 5:不参与线性标定):yc = 最新一拍原始
* 帧值透传,qds 恒置 NT——值在场但非交流量语义,UI 按「数据可信」§4.2
* 三态表显示占位符,104 无对应点。
* 并发(docs/任务规划/数据可信.md §4.5 原文口径):沿用 phasor 的
* **双区 + 单字节活跃索引翻转**(双区指针原子交换 同型,不是新机制)——写侧填满
* 计算区后一次 store 翻转,读者先取索引再整体拷贝,全程无锁;
* seq 只增,消费者据此判"是否换帧"。
* 本层**纯算法**:不碰寄存器、不碰 RTOS、不自己取数(窗自 sample_ring、
* 频率/品质由调用方注入)→ 主机侧免桩单测 test/host/meas/(L0.5)。
* 发布纪律:唯一发布者 = adcTask(在 phasor_run()/freq_run() 之后 200 ms 分频
* 调 meas_tick())。评审判据 = 全仓 meas_tick 调用点数 == 1(「数据可信」
* §8 风险表"快照双写"行);其余任务/模块**只读**。
* 适用平台:STM32F407ZGTx(Cortex-M4F,硬件 FPU)
* 作者:DTU 项目组
* 创建日期:2026-10-25(道D 遥测快照发布)
* 修改记录:
* v1.0 2026-10-25 DTU 项目组 创建:200 ms 遥测快照 + 双区无锁读
*/
#ifndef MEAS_H
#define MEAS_H
#include <stdint.h>
#include "adc_input.h" /* adc_semantic_t / ADC_SEM_COUNT:yc/qds 下标 = 语义通道 */
#ifdef __cplusplus
extern "C" {
#endif
/* 上送节拍(ms):adc_task 按本宏对 1 kHz 拍做**经过时间**分频(非拍计数——
* idle/skip 拍会把拍计数口径拉得比名义值长),落点见 App/task/adc_task.c */
#define MEAS_PERIOD_MS 200u
/* 每点品质位(uint16)。**低字节与线上 104 QDS 字节同值**(OV/NT/IV,数值
* 口径同 App/protocol/iec104/iec104_asdu.h 的 IEC104_QDS_*)——但本层**不得**
* include 协议层头(分层方向:算法层在协议层之下,反向依赖禁止),故在此自
* 定义同值常量;104 侧消费(104 改读快照)直接截低字节上送,一致性由本目录单测与
* test/host/iec104/ 既有断言双向钉住。高字节为 meas 域扩展位(线上不直接
* 出现,由消费者映射): */
#define MEAS_QDS_OV (0x0001u) /* 溢出(留位,本项不产出——判据待运行参数化) */
#define MEAS_QDS_NT (0x0020u) /* 非当前值:未就绪 / 语义未处理(TEMP) */
#define MEAS_QDS_IV (0x0080u) /* 无效:该路取窗失败,无有效读数 */
#define MEAS_QDS_CLIPPED (0x0100u) /* 硬件削顶(adc_cal_flags 位图直通,
* 「数据可信」§4.2 三态表;AC 量不可信,
* 消费者应映射为品质无效,如 104 改读快照侧的 IV) */
/* 遥测快照(docs/任务规划/数据可信.md §4.5 权威布局;实测 72 B,2×72 ≈ 144 B
* 双区 = 本项 DoD 预算口径,由 test/host/meas/ 的布局钉死用例锁字段偏移——
* 改字段 = 破协议,须同步 104 改读快照 / UI) */
typedef struct {
uint32_t seq; /* 只增;消费者据此判断是否换帧 */
uint32_t tick_ms; /* 发布拍时基(osKernelGetTickCount 原值) */
uint8_t valid; /* 整帧有效:本拍 8 电气路取窗全部成功 */
uint8_t rsv[3]; /* 对齐填充,恒 0 */
float yc[ADC_SEM_COUNT]; /* 工程量(引脚电压 V 域;二次值等 VALID 标定) */
uint16_t qds[ADC_SEM_COUNT]; /* 每点品质 MEAS_QDS_*(值本身不因品质清零) */
uint8_t freq_valid; /* 频率读数新鲜度(freq_valid() 注入) */
float freq_hz; /* 频率读数(freq_last() 注入,未收敛为 0) */
} meas_snap_t;
/*
* 函数功能:遥测快照层初始化(清双区 / 索引 / 序号 / 就绪标志)
* 入口参数:无
* 返 回 值:0 - 成功 int
* 限定条件:内核启动前或任务上下文皆可(纯 .bss 状态,无 RTOS 依赖);
* 本仓落点 = adc_task_init()(每开机一次,幂等可重复调)
* 函数说明:init 后 meas_get() 返 -2、meas_seq() 返 0,直到首次 meas_tick()
* 发布——消费者据 -2 走"未就绪"分支,不读半初始化数据。
*/
int meas_init(void);
/*
* 函数功能:一拍遥测发布(200 ms 分频由调用方把关,本函数被调即发布一帧)
* 入口参数:tick_ms - 本拍时基(毫秒) uint32_t
* freq_valid_in - 频率读数新鲜度(freq_valid() 值) uint8_t
* freq_hz_in - 频率读数(freq_last() 值;从未收敛为 0.0) float
* clip_mask - 削顶通道位图(bit s = 语义通道 s;来源唯一 =
* adc_cal_flags() 的 ADC_CAL_F_CLIPPED,编排方注入,
* 本层不链 adc_cal——可用性属主在折算侧) uint32_t
* 返 回 值:无
* 限定条件:**仅 adcTask 上下文、全仓唯一调用点**(发布纪律见文件头);
* 须在 sample_ring_push_frame()/phasor_run() 之后调用,本拍窗才含最新点
* 函数说明:8 电气路逐路取"以本拍为终止的一周波"做基波 DFT(复用 phasor_calc
* 纯函数核,与 phasor 使用区同窗同核 → 同拍同值,见单测钉死),
* 任一路窗不足 → 该路 yc=0 + qds=IV|NT、整帧 valid=0(不产出半新半旧
* 混合帧;与 phasor_run 的差异:phasor 宁可不切区,meas **照常发布**
* 让品质位可见——消费者需要节拍性的品质刷新,seq 亦随之只增)。
* TEMP = 最新一点透传 + NT(见文件头)。末尾单字节翻转使用区,
* 读者无锁。
*/
void meas_tick(uint32_t tick_ms, uint8_t freq_valid_in, float freq_hz_in,
uint32_t clip_mask);
/*
* 函数功能:读当前使用区快照(无锁整体拷贝)
* 入口参数:out - 输出快照;失败(含 -2 未就绪)时**清零填充**,调用方可安全读
* 返 回 值:0 - 成功;-1 - 参数错;-2 - 从未发布过(out 已清零,seq=0) int
* 限定条件:任意上下文(任务级读者:iec104Task / uiTask / protectTask)
* 函数说明:先取一次使用区索引再索引拷贝——拷贝期间写者最多改"**非使用区**",
* 本帧无撕裂(双区不变量,同 phasor_get 口径;写者两帧间隔 200 ms
* 远大于 72 B 拷贝耗时,读者被压超 200 ms 的竞态窗口按 §4.5 设计接受)。
* 判"新不新"用 seq:与上次不同则换帧。
*/
int meas_get(meas_snap_t *out);
/*
* 函数功能:读已发布帧数(只增)
* 入口参数:无
* 返 回 值:seq(0 = 从未发布;单字 32 位读,Cortex-M 原子) uint32_t
* 限定条件:任意上下文
* 函数说明:轻量观测入口(104 周期上送可先比 seq 省 72 B 拷贝);
* 与 meas_get 之间无原子性配对要求(读者以 get 返回的 seq 为准)。
*/
uint32_t meas_seq(void);
#ifdef __cplusplus
}
#endif
#endif /* MEAS_H */