Files
STM32F4-Base/App/protocol/iec104/iec104_pts.h
T
wandering1 593c5d0c84 refactor(编号): 采集链分层 L1/L1.5/L2/L2.5/L3/L4/L5 → 语义名(批次 1)
用户裁定(2026-10-28):L1/L1.5/L2/L2.5/L3 这套层号「谁能看懂」,改用语义名。
映射(同一批定稿,含 L4/L5):
  L1   → 语义取数与有效性
  L1.5 → 标定折算
  L2   → 全周傅氏相量
  L2.5 → 测频与遥测快照
  L3   → 保护判据
  L4   → 出口与记录
  L5   → 动作留痕

实测规模:384 站点 / 62 文件(App/algo、App/task、test/host 六个套件、docs/算法、
产品需求、架构总览、启动顺序、ADC 采样节拍、IEC104 上行、采集短板评测、内存管理、
AGENTS.md、README.md、docs/README.md、.pre-commit-config.yaml 与 scripts 里的注释)。

改法(不是全局替换,逐模式有上下文规则):
- 先吃同位语再落裸词:L1 有效性校验 → 语义取数与有效性校验、L2 相量层 → 全周傅氏
  相量层、L3 保护 → 保护判据、L2.5 遥测快照 → 测频与遥测快照,避免「保护判据保护判据」
  这类重复(第一版就是这么坏掉的,已整体回滚重做)。
- .c/.h 只改注释:先把字符串字面量切出去(引号数为奇数的跨行注释按整行处理),
  C 字符串里的 L2-in ring 之类原样保留——AGENTS 铁律「字符串字面量必须纯 ASCII」。
- 层内条目号(L1-3 / L2-3 这类)**本批不动**,属批次 2;另外三族(UI 菜单层级
  L0~L3、链路延迟分段 L1~L8、CubeMX 防丢失三层)也不动,属批次 3。
- 顺手修的措辞:范围写法 L1~L3 → 「分层(语义取数与有效性 → 保护判据)」、
  CI 段「不含 L1/L2/L3」→「不含采集链分层」、目录地图里同一处并列表述。

验证:@build 0 错 0 警(Code=236456,与改前逐字节同尺寸——纯注释改动);
内存布局配图已按新脚本重生成(自检通过);doc-links --all --sections-strict 通过
(195 文档);mojibake / bom-guard / coding-standard / 新编号门禁自查 全 rc=0;
git diff --check 干净。
2026-10-28 13:04:02 +08:00

131 lines
8.3 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.
/*
* 模块名称:IEC 60870-5-104 点表与数据源适配(纯逻辑 + 源注入)
* 模块功能:104 点表(遥测 YC / 遥信 YX / 遥控 YK / 定值)的定义、读取与变化检测
* (COV:遥信变位 + 遥测死区)。**数据源经 vtable 注入**:板端绑
* phasor/prot_elm/prot_set 真实源;主机单测绑假源 → 协议栈全链
* (asdu+pts+link)可离线跑(分层约束:协议解析与硬件 I/O 分离)。
* 点表口径(docs/算法/继电保护功能复现规划.md §1.5,验收 = 省电科院点表):
* - YC:IOA 0x4011~0x4018 + 0x401d(频率),短浮点、系数 1;数据源 =
* 测频与遥测快照(App/algo/meas.h,「数据可信」104 改读快照与频率点绑定):电气 8 路绑快照槽,
* 有效性由快照品质驱动——V0.1 削顶路(docs/算法/继电保护功能复现规划.md
* §1.6)快照置 CLIPPED → 本层映射为线上 IV(V0.2 后自动启用,绑定零
* 改动,见 docs/任务规划/数据可信.md §10「双转换器无共同采样触发」行);0x401d 绑频率源,
* freq_valid()==0 → IV;
* - YX:IOA 1~33(§1.5 表(3));双点 = 开关位置类(YX1~4,本期无硬件 → IV),
* 保护动作类 YX15~23 映射 prot_elm 状态,闭锁类 YX31~33 映射 prot_set;
* - YK:IOA 0x6000+(§1.5 表(3));V0.1 无出口硬件(规划 R7)——
* YK11 信号复归(→ prot_elm_request_reset)与 YK12 全局软压板
* (→ PS_GLOBAL_EN 两段式转真,B7)转真执行,其余一律否定确认(COT|PN),如实回;
* - 定值:IOA = prot_set 元数据 comm_addr(0x8820 基址 + 告警段 0x8027~0x802A;
* comm_addr=0 本地项不可寻址),
* 读经 C_RD、写经 C_SE_NC(选择/执行两段,执行段原子写+封存并置脏,
* 持久化 /prot_set.bin 由 defaultTask 执行,B7);
* - 固有参数 8001H~800AH:本期**不实现**(字符串类无法用短浮点上送),
* 按未知 IOA(COT 14 + EVI)应答,登记为待办(设计文档)。
* 线程约定:init/bind 内核启动前或建服务前;cov_check/read 仅 104 服务任务上下文。
* 创建日期:2026-10-12(B4)
* 修改记录:
* 2026-10-25 DTU 项目组 104 改读快照与频率点绑定(「数据可信」,道D):YC 数据源 = 全周傅氏相量遥测
* 快照(削顶路由品质驱动 IV);死区改运行时副本 +
* set/get 入口;COV 遥测腿 = 死区 2 点确认(seq 去重)
* + 品质变化即报;0x401d 绑频率源(freq_valid → IV)。
* 2026-10-25 DTU 项目组 运行参数段:死区真源迁 run_par([run_par] cfg 段 +
* 0x8020~0x8058 读写映射;本层 set/get 为转发壳)。
*/
#ifndef IEC104_PTS_H
#define IEC104_PTS_H
#include <stdint.h>
/* ---------------- 数据源 vtable(NULL 项 = 该能力不可用 → 按无效/拒绝处理) -- */
typedef struct {
/* 遥测读:idx = YC 表下标;out = 工程量浮点。
* 返回 0 有效 / -1 无效(发 IV)/ -2 数据未就绪(发 NT,如相量未满一周波) */
int (*yc_read)(uint8_t idx, float *out);
/* 遥信位图:bit i = YX 表下标 i 的"合/动作"态(双点按 ON 计) */
uint64_t (*yx_bits)(void);
/* 遥信有效位图:bit i = 1 该点有效;0 → 发 IV(无硬件/未实现) */
uint64_t (*yx_valid)(void);
/* 遥控:select=1 选择段 / 0 执行段(dpc 已剥 S 位)。返回 0 接受 / -1 拒绝 */
int (*yk_exec)(uint32_t ioa, uint8_t dpc, uint8_t select);
/* 定值读:addr = 通讯地址;返回 0 存在 / -1 未知地址 */
int (*set_read)(uint32_t addr, float *out);
/* 定值写:select=1 预置校验(范围)/ 0 执行写入。返回 0 / -1 越界或未知 */
int (*set_write)(uint32_t addr, float v, uint8_t select);
/* 遥测读(带品质,104 改读快照时追加于表尾——旧源 NULL = 走 yc_read 退路,品质由
* 返回值推导:-1 → IV、-2 → NT、0 → 无位,行为与旧源完全一致)。
* qds = uint16 域位(App/algo/meas.h MEAS_QDS_*:低字节 = 线上 QDS 同值,
* 高字节 CLIPPED 由本层映射线上 IV);返回 0 / -1 IV / -2 NT */
int (*yc_read_ex)(uint8_t idx, float *out, uint16_t *qds);
} iec104_pts_src_t;
/* ---------------- 变化检测结果(cov_check 输出) ---------------- */
typedef struct {
uint64_t yx_changed; /* bit i = YX 下标 i 变位(相对上次快照) */
uint16_t yc_changed; /* bit i = YC 下标 i 越过死区(相对上次快照) */
} iec104_pts_cov_t;
/*
* 函数功能:点表层初始化(清快照、绑板端默认源)
* 限定条件:内核启动前或 104 服务启动前,调一次
*/
void iec104_pts_init(void);
/*
* 函数功能:覆盖数据源(主机单测注假源)
* 入口参数:src - vtable(浅拷贝,调用方保生命周期);NULL = 恢复板端默认源
*/
void iec104_pts_bind_src(const iec104_pts_src_t *src);
/* ---------------- YC ---------------- */
uint8_t iec104_pts_yc_count(void);
uint32_t iec104_pts_yc_ioa(uint8_t idx);
/* 读 YC:v 有效值(无效时为 0);qds 输出线上品质位(IV/NT/OV,CLIPPED 已映射
* 为 IV)。返回 0/无效-1(NT 亦无效,品质位区分) */
int iec104_pts_yc_read(uint8_t idx, float *v, uint8_t *qds);
/* 死区写(104 改读快照 API;运行参数段起 = 转发 App/algo/run_par.c 真源 + 清本层确认计数):
* db = 工程量绝对值 ≥0(电压 50 V / 电流 1 A / 频率 5 Hz 分档上限);越界/负值/
* NaN → -1 且真源不动;成功时清零该点待确认计数(跨档位不残留半截确认——此壳
* 行为有单测钉住)。仅 104 服务任务上下文调用。落盘 = run_par 脏 → 事件 →
* defaultTask(运行参数段持久化链,docs/子系统设计/IEC104上行设计说明.md §3.4)。 */
int iec104_pts_yc_set_deadband(uint8_t idx, float db);
/* 读当前生效死区(越界 idx 返 0) */
float iec104_pts_yc_deadband(uint8_t idx);
/* ---------------- YX ---------------- */
uint8_t iec104_pts_yx_count(void);
uint32_t iec104_pts_yx_ioa(uint8_t idx);
uint8_t iec104_pts_yx_is_dp(uint8_t idx); /* 1 = 双点(M_DP) */
/* 读 YX:out = DIQ/SIQ 值(含 IV)。 */
void iec104_pts_yx_read(uint8_t idx, uint8_t *out);
/* ---------------- COV(每 poll 一次) ---------------- */
/*
* 函数功能:读全表并与上次比对(遥信变位 + 遥测死区 2 点确认 + 品质变化),
* 输出变化集
* 入口参数:cov - 输出(可为 NULL = 只刷快照不取变化)
* 函数说明:遥测判据(「数据可信」104 改读快照,对标参考系统 CalfYcMea 死区 2 点确认,
* 短板评测口径):**连续 2 个新测量点** |v - 上次上送值| > 死区才置变化位
* (单点尖峰不确认——噪声回摆即撤销候选);品质位(线上 qds)相对上次
* 上送值翻转 → 当拍直接置位(不等 2 点,有效性变化必须即时可见,
* 含 0x401d 的 IV 进出)。死区 = 运行时副本(ROM 默认 = 点表列,
* iec104_pts_yc_set_deadband() 覆盖——运行参数段的接线点)。
* 测量点定义:板端默认源 = **快照换帧**(meas seq 前进;100 ms poll 对
* 200 ms 快照,同一帧重复比对会计数两次 → seq 去重是确认语义成立的
* 前提);注入源(单测假源)= 每次调用一测点。首次读到有效值只建基线
* 不上报(突发由总召覆盖)。
*/
void iec104_pts_cov_check(iec104_pts_cov_t *cov);
/* ---------------- 遥控 ---------------- */
/* 遥控两段式(转发 src->yk_exec;无源 = 一律拒绝)。返回 0 接受 / -1 拒绝 */
int iec104_pts_yk_exec(uint32_t ioa, uint8_t dpc, uint8_t select);
/* ---------------- 定值 ---------------- */
/* 按通讯地址读定值(转发 src->set_read)。返回 0 / -1 未知地址 */
int iec104_pts_set_read(uint32_t addr, float *out);
/* 按通讯地址写定值(两段)。返回 0 / -1 */
int iec104_pts_set_write(uint32_t addr, float v, uint8_t select);
#endif /* IEC104_PTS_H */