feat(104遥测): 卡9改读L2快照+死区运行化2点确认 + 卡11绑频0x401D(道D M5/M6)
卡 9(App/protocol/iec104/iec104_pts.*,「数据可信」,docs/子系统设计/ IEC104上行设计说明.md §3.1/§4 同步): - 数据源换轨:板端默认 YC 源从直读 phasor 改为**整体透传 L2 遥测快照** (meas_get 双区无锁;"新不新、能不能信"只在发布侧判一次,M5-② 落地); iec104_pts_src_t 表尾追加 yc_read_ex(带品质)——旧注入源走 legacy 退路, 品质由返回值推导,行为与卡 9 前**完全一致**(存量假源用例零改动) - 品质映射 s_q_map:MEAS_QDS_* 低字节=线上 QDS 同值直传;CLIPPED→IV (「削顶通道 104 恒 IV」口径不变、从点表绑死 -1 改品质驱动——UB/UC/IB/ IC/IN 五路现绑快照槽,V0.2/N-18 削顶消失后**零改动自动启用**);IV 优先 NT;快照从未发布(开机 <200ms)→ IV|NT;无效信息体清零(旧线上口径保持) - 死区运行化:运行时副本 s_yc_db(ROM 默认 = 点表列,卡 6 额定 0.5% 档不变) + iec104_pts_yc_set_deadband()/iec104_pts_yc_deadband()——卡 10 运行参数段 (8020H)的接线点已留;非法 idx/负值/NaN 拒绝、成功时清该点待确认计数 - COV 遥测腿升级(lead 裁②"卡 9 是消费者"):判定 = 相对**上次上送值**(非 上次读值,防慢漂移吃基准)连续 2 个新测量点越死区才确认上送;回摆入带即 撤销候选;品质翻转当拍直报(含 0x401D 的 IV 进出)。测量点推进:板端按 快照 seq 去重(100ms poll vs 200ms 快照——不去重则同一帧把单点噪声计满 2 点,抗噪语义失效);注入源=每次调用一测点(单测步进自持) 卡 11:YC 表加 src 类型(PTS_SRC_MEAS/FREQ);0x401D 绑快照 freq_hz(与 freq_get 同源);snap.freq_valid==0 → IV 清零(卡 11 DoD 原句) 测试与文档:test/host/iec104 97→127 断言——TC-008 语义更新为 2 点确认; 新 TC-IEC104-025~028(024 号被存量 B7 用例裸标签占用,让号并改用全家长 形态)板端默认源走**真实 L2 链**(ring→phasor→freq→meas,非桩):未发布 NT/值透传/CLIPPED→IV 清零/绑频收敛 ±0.02Hz/未新鲜 IV/死区运行档压旧档/ 回摆撤销/seq 去重同帧不计数/换帧只变品质按集合直报;id_registry 族游标 023→028;IEC104 上行设计说明 §3.1 表+注/§4/§7/§8 第 4 条/变更记录同步。 无新 .c(uvprojx 零改动);PC 主站读回一致与频率 ±0.01Hz 属网络对端验证 ——步骤清单已发 lead 排窗,本轮零台架动作。 gate:@build 0 错 0 警(Code=218128 RO=21624 RW=1272 ZI=132864);增量 vs adeef7d:Flash +348B、RAM(RW+ZI) +48B(低于 96B 预估,链接器并洞), IRAM1 58.5% 不变;iec104Task 栈 worst=1456B margin=1104B(43%) PASS 无抬栈 (stack_report);--all-files 全量实跑:其余钩子全绿(含修掉一处 cppcheck variableScope 后),仅 mem-budget + mem-numbers 两红 = 台账受管区 vs .map 漂移(回填属 lead 单写者区,批 1/道D-1 同口径): gate: only mem-budget/mem-numbers pending lead ledger backfill BOM/CR/U+FFFD/字面量 ASCII 逐文件自查通过(未触碰带 BOM 文件)。
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
/*
|
||||
* 模块名称:IEC 60870-5-104 点表与数据源适配(实现)
|
||||
* 模块功能:实现 iec104_pts.h——YC/YX/YK/定值点表(ROM)、板端默认源
|
||||
* (phasor / prot_elm / prot_set)、COV 快照比对(遥信变位 +
|
||||
* 遥测死区)。点表口径见 iec104_pts.h 文件头与设计文档 §3。
|
||||
* (**L2 遥测快照**(卡 9)/ prot_elm / prot_set)、COV 比对(遥信变位 +
|
||||
* 遥测死区 2 点确认 + 品质变化)。点表口径见 iec104_pts.h 文件头与
|
||||
* 设计文档 §3。
|
||||
* 线程约定:init/bind 建服务前;其余仅 104 服务任务上下文(快照非原子)。
|
||||
* 创建日期:2026-10-12(B4)
|
||||
* 修改记录:
|
||||
@@ -10,47 +11,71 @@
|
||||
* 二次值工程量域(额定 0.5 % 规则),判据依据见
|
||||
* k_yc 表头注释;数值随卡 9 迁运行参数,本表将退化为
|
||||
* ROM 默认载体。
|
||||
* 2026-10-25 DTU 项目组 卡 9/卡 11(「数据可信」,道D):YC 板端源改读
|
||||
* L2 遥测快照(App/algo/meas.h,meas_get 无锁双区);
|
||||
* 削顶五路由快照品质 CLIPPED 驱动线上 IV(不再绑死 -1,
|
||||
* V0.2/N-18 零改动自动启用);0x401d 绑频率源(卡 11);
|
||||
* 死区改运行时副本 + set/get 入口;COV 遥测腿 = 死区
|
||||
* 连续 2 点确认(板端按快照 seq 去重)+ 品质翻转即报。
|
||||
* 单测 = test/host/iec104 TC-IEC104-025~028。
|
||||
*/
|
||||
#include "iec104_pts.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "iec104_asdu.h" /* QDS/DIQ 品质位常量 */
|
||||
#include "phasor.h" /* 板端源:遥测 = 基波有效值 */
|
||||
#include "meas.h" /* 板端源:遥测 = L2 遥测快照(卡 9;品质域位同源) */
|
||||
#include "prot_elm.h" /* 板端源:遥信 = 元件状态 */
|
||||
#include "prot_set.h" /* 板端源:定值 + 闭锁 */
|
||||
#include "adc_input.h" /* adc_semantic_t(phasor 实例按语义绑定) */
|
||||
|
||||
/* ---------------- YC 表(§1.5 点号 4011+;死区 = 二次值工程量域) --------- */
|
||||
/* ---------------- YC 表(§1.5 点号 4011+;死区列 = ROM 默认值) ------------ */
|
||||
/* 源类型(「数据可信」卡 11:YC 表加 src 类型区分相量/频率) */
|
||||
#define PTS_SRC_MEAS 0u /* L2 快照槽 sem(电气量,yc/qds 直读) */
|
||||
#define PTS_SRC_FREQ 1u /* 快照频率(freq_valid 门 → IV) */
|
||||
|
||||
typedef struct {
|
||||
uint32_t ioa;
|
||||
int8_t sem; /* 绑定的 phasor 语义通道(-1 = 无 phasor 源,恒无效) */
|
||||
float deadband; /* 死区(二次值工程量绝对值,「数据可信」卡 6 重定) */
|
||||
int8_t sem; /* 快照 yc 槽 = 语义通道(-1 = 非测量量点,当前仅频率) */
|
||||
float db_default; /* 死区 ROM 默认(运行时生效值 = s_yc_db,卡 10 覆盖) */
|
||||
uint8_t src; /* PTS_SRC_* 源类型 */
|
||||
} pts_yc_def_t;
|
||||
|
||||
/* 死区规则 = 额定二次值的 0.5 %(「数据可信」§2.3 表第 2 行建议规则,卡 6 采纳;
|
||||
* 额定基准 100 V / 1 A 与 App/algo/prot_set.c 头部同源,勿在此另立口径):
|
||||
* 电压类 0.5 % × 100 V = 0.5 V 电流类 0.5 % × 1 A = 0.005 A
|
||||
* 频率点不适用"额定百分比"(额定附近 0.5 Hz 与旧值同量级,维持 0.5 并随
|
||||
* 卡 10 运行参数段可调)。IV 品质点(sem=-1)数值仅为将来启用预留同型。
|
||||
* 卡 10 运行参数段可调)。自卡 9 起本表**只作 ROM 默认载体**:运行时死区 =
|
||||
* s_yc_db 副本;削顶五路不再 sem=-1 绑死,而是绑快照槽、由品质 CLIPPED
|
||||
* 驱动线上 IV——V0.2(N-18)削顶消失后点位零改动自动启用(docs/任务规划/
|
||||
* 数据可信.md §10 的 N-18 行)。
|
||||
* ⚠ 过渡期(eng=0 引脚电压域,卡 12 标定前):上送值本身非二次值,死区
|
||||
* 按本域判定无意义但也不会漏报——104 侧 IV/数据可信度语义由 M5 快照层
|
||||
* (卡 8/9)统一处理,本卡只把"量纲错位"这一处常量债还掉。 */
|
||||
* 数字按本域偏保守(迟报不漏报);标定落地后复核(「数据可信」§2.3 表
|
||||
* 第 2 行)。判定 = 死区连续 2 点确认(卡 9),见 iec104_pts.h COV 说明。 */
|
||||
static const pts_yc_def_t k_yc[] = {
|
||||
{ 0x4011u, (int8_t)ADC_SEM_UA, 0.5f }, /* 1Ua:0.5 % × 100 V */
|
||||
{ 0x4012u, -1, 0.5f }, /* 1Ub:V0.1 削顶 → IV */
|
||||
{ 0x4013u, -1, 0.5f }, /* 1Uc:同上 */
|
||||
{ 0x4014u, (int8_t)ADC_SEM_UN, 0.5f }, /* 1U0(外部零序专用通道) */
|
||||
{ 0x4015u, (int8_t)ADC_SEM_IA, 0.005f }, /* 1Ia:0.5 % × 1 A */
|
||||
{ 0x4016u, -1, 0.005f }, /* 1Ib */
|
||||
{ 0x4017u, -1, 0.005f }, /* 1Ic */
|
||||
{ 0x4018u, -1, 0.005f }, /* 1I0 */
|
||||
{ 0x401Du, -1, 0.5f }, /* 1f:Hz 绝对死区(非额定比)→ IV */
|
||||
{ 0x4011u, (int8_t)ADC_SEM_UA, 0.5f, PTS_SRC_MEAS }, /* 1Ua:0.5 % × 100 V */
|
||||
{ 0x4012u, (int8_t)ADC_SEM_UB, 0.5f, PTS_SRC_MEAS }, /* 1Ub:削顶 → 品质驱动 IV */
|
||||
{ 0x4013u, (int8_t)ADC_SEM_UC, 0.5f, PTS_SRC_MEAS }, /* 1Uc:同上 */
|
||||
{ 0x4014u, (int8_t)ADC_SEM_UN, 0.5f, PTS_SRC_MEAS }, /* 1U0(外部零序专用通道) */
|
||||
{ 0x4015u, (int8_t)ADC_SEM_IA, 0.005f, PTS_SRC_MEAS }, /* 1Ia:0.5 % × 1 A */
|
||||
{ 0x4016u, (int8_t)ADC_SEM_IB, 0.005f, PTS_SRC_MEAS }, /* 1Ib:削顶 → 品质驱动 IV */
|
||||
{ 0x4017u, (int8_t)ADC_SEM_IC, 0.005f, PTS_SRC_MEAS }, /* 1Ic:同上 */
|
||||
{ 0x4018u, (int8_t)ADC_SEM_IN, 0.005f, PTS_SRC_MEAS }, /* 1I0:同上 */
|
||||
{ 0x401Du, -1, 0.5f, PTS_SRC_FREQ }, /* 1f:卡 11 绑频率源,
|
||||
* freq_valid=0 → IV */
|
||||
};
|
||||
#define YC_N ((uint8_t)(sizeof(k_yc) / sizeof(k_yc[0])))
|
||||
|
||||
/* phasor 实例下标缓存(init 时按 sem+harm==1 查表;-1 = 未找到) */
|
||||
static int8_t s_yc_phasor_idx[YC_N];
|
||||
/* ===== 遥测 COV 运行时状态(卡 9;仅 iec104Task 上下文访问,无并发) =====
|
||||
* 判据链:新测量点 → |v − 上次上送值| > 死区?→ 连续 2 点确认 → 置变化位。
|
||||
* 基准 = **上次上送值**(非上次读值——否则慢漂移永不出死区,参考系统同款);
|
||||
* 品质(线上 qds)翻转 = 事件:不参与 2 点计数、当拍直报。 */
|
||||
static float s_yc_db[YC_N]; /* 死区运行时副本(ROM 默认 = k_yc 列) */
|
||||
static float s_yc_rep[YC_N]; /* 上次上送值(建线/确认上送时更新) */
|
||||
static uint8_t s_yc_repq[YC_N]; /* 上次上送的线上 qds */
|
||||
static uint8_t s_yc_cnf[YC_N]; /* 越死区连续计数(1 = 待确认;2 = 确认) */
|
||||
static uint32_t s_yc_seq; /* COV 已消费到的快照 seq(板端源测点去重) */
|
||||
static uint8_t s_yc_seqmode; /* 1 = 板端默认源(测点 = meas 换帧) */
|
||||
|
||||
/* ---------------- YX 表(IOA = 1..33;双点 = 开关位置类) ------------------ */
|
||||
#define YX_N 33u
|
||||
@@ -61,63 +86,65 @@ static int8_t s_yc_phasor_idx[YC_N];
|
||||
| (1uLL << 17u) | (1uLL << 22u) | (1uLL << 30u)))
|
||||
|
||||
/* ---------------- 数据源(默认 = 板端;bind_src 可整体替换) -------------- */
|
||||
static int s_src_yc_read(uint8_t idx, float *out);
|
||||
static int s_src_yc_read_ex(uint8_t idx, float *out, uint16_t *qds);
|
||||
static uint64_t s_src_yx_bits(void);
|
||||
static uint64_t s_src_yx_valid(void);
|
||||
static int s_src_yk_exec(uint32_t ioa, uint8_t dpc, uint8_t select);
|
||||
static int s_src_set_read(uint32_t addr, float *out);
|
||||
static int s_src_set_write(uint32_t addr, float v, uint8_t select);
|
||||
|
||||
/* 板端默认源:遥测走**带品质**的 ex 通道(legacy yc_read 槽置 NULL——
|
||||
* s_yc_point 优先 ex;注入源两种槽位均可,见 iec104_pts.h) */
|
||||
static const iec104_pts_src_t k_default_src = {
|
||||
s_src_yc_read, s_src_yx_bits, s_src_yx_valid,
|
||||
s_src_yk_exec, s_src_set_read, s_src_set_write
|
||||
NULL, s_src_yx_bits, s_src_yx_valid,
|
||||
s_src_yk_exec, s_src_set_read, s_src_set_write, s_src_yc_read_ex
|
||||
};
|
||||
static const iec104_pts_src_t *s_src;
|
||||
|
||||
/* ---------------- COV 快照 ---------------- */
|
||||
static float s_yc_last[YC_N];
|
||||
static uint16_t s_yc_have; /* bit i = 已有上次快照 */
|
||||
/* ---------------- COV 快照(遥信侧;遥测侧状态见上方 s_yc_* 块) --------- */
|
||||
static uint16_t s_yc_have; /* bit i = 已建立上送基线 */
|
||||
static uint64_t s_yx_last;
|
||||
static uint8_t s_yx_snap_ok;
|
||||
|
||||
/* ============================ 公开接口 ================================== */
|
||||
|
||||
/*
|
||||
* 函数功能:初始化点表模块(扫 phasor 基波实例映射、恢复默认源、清快照)
|
||||
* 函数功能:初始化点表模块(死区装 ROM 默认、清 COV/快照状态、恢复默认源)
|
||||
* 限定条件:内核启动前或 104 服务启动前,调一次
|
||||
* 函数说明:卡 9 起不再扫 phasor 实例(数据源 = 快照,槽位 = 语义通道,编译期
|
||||
* 直接可定);重复调用 = 全状态复位(单测 reset 依赖此语义)。
|
||||
*/
|
||||
void iec104_pts_init(void) {
|
||||
uint8_t i;
|
||||
uint8_t n;
|
||||
|
||||
(void)memset(s_yc_phasor_idx, -1, sizeof(s_yc_phasor_idx));
|
||||
n = phasor_inst_count();
|
||||
for (i = 0u; i < YC_N; i++) {
|
||||
uint8_t j;
|
||||
|
||||
if (k_yc[i].sem < 0) {
|
||||
continue;
|
||||
}
|
||||
for (j = 0u; j < n; j++) {
|
||||
const phasor_inst_t *inst = phasor_inst(j);
|
||||
|
||||
if ((inst != NULL) && ((uint8_t)inst->sem == (uint8_t)k_yc[i].sem)
|
||||
&& (inst->harm == 1u)) {
|
||||
s_yc_phasor_idx[i] = (int8_t)j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s_yc_db[i] = k_yc[i].db_default;
|
||||
}
|
||||
s_src = &k_default_src;
|
||||
s_yc_have = 0u;
|
||||
(void)memset(s_yc_rep, 0, sizeof(s_yc_rep));
|
||||
(void)memset(s_yc_repq, 0, sizeof(s_yc_repq));
|
||||
(void)memset(s_yc_cnf, 0, sizeof(s_yc_cnf));
|
||||
s_yc_have = 0u;
|
||||
s_yc_seq = 0u;
|
||||
s_yc_seqmode = 1u;
|
||||
s_src = &k_default_src;
|
||||
s_yx_snap_ok = 0u;
|
||||
s_yx_last = 0u;
|
||||
s_yx_last = 0u;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:替换数据源(NULL = 恢复板端默认源;单测注入假源)
|
||||
* 函数说明:注入源同时把 COV 测点口径切为**每次调用一测点**(假源无快照节拍,
|
||||
* 步进由调用方控制);默认源 = 测点按 meas 换帧(seq 去重)。换源
|
||||
* 不重建基线(基线状态统一由 init 复位,防跨源半截确认序列)。
|
||||
*/
|
||||
void iec104_pts_bind_src(const iec104_pts_src_t *src) {
|
||||
s_src = (src != NULL) ? src : &k_default_src;
|
||||
if (src != NULL) {
|
||||
s_src = src;
|
||||
s_yc_seqmode = 0u;
|
||||
} else {
|
||||
s_src = &k_default_src;
|
||||
s_yc_seqmode = 1u;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -135,35 +162,105 @@ uint32_t iec104_pts_yc_ioa(uint8_t idx) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:读遥测(值 + 品质 descriptor;源 -2 → NT,其余失败 → IV)
|
||||
* 返 回 值:0 有效 / -1 无效
|
||||
* 函数功能:品质域位映射(uint16 meas 域 → uint8 线上 QDS,卡 9)
|
||||
* 入口参数:q16 - 源侧品质(低字节与线上同值;高字节为 MEAS_QDS_CLIPPED 域内位)
|
||||
* 返 回 值:线上 QDS 字节 uint8_t
|
||||
* 函数说明:CLIPPED(硬件削顶,104 无对应位)映射为 IV——「削顶通道 104 恒
|
||||
* IV」口径(docs/任务规划/数据可信.md §8 风险表末行)改由快照品质
|
||||
* 驱动,不再靠点表绑死 -1;OV/NT/IV 透传,其余高位丢弃。
|
||||
*/
|
||||
int iec104_pts_yc_read(uint8_t idx, float *v, uint8_t *qds) {
|
||||
int rc;
|
||||
static uint8_t s_q_map(uint16_t q16) {
|
||||
uint8_t w = (uint8_t)(q16 & (uint16_t)(IEC104_QDS_OV | IEC104_QDS_NT
|
||||
| IEC104_QDS_IV));
|
||||
|
||||
if (v != NULL) {
|
||||
*v = 0.0f;
|
||||
if ((q16 & (uint16_t)MEAS_QDS_CLIPPED) != 0u) {
|
||||
w |= (uint8_t)IEC104_QDS_IV;
|
||||
}
|
||||
if ((idx >= YC_N) || (s_src == NULL) || (s_src->yc_read == NULL)) {
|
||||
if (qds != NULL) {
|
||||
*qds = IEC104_QDS_IV;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:读单点遥测(统一源通道 + 品质归一,yc_read 与 COV 共用唯一读径)
|
||||
* 入口参数:idx - YC 表下标 v/q - 输出(值 / 线上 qds;调用方保证非空)
|
||||
* 返 回 值:0 有效;-1 IV(含 CLIPPED 映射);-2 NT(未就绪) int
|
||||
* 函数说明:ex 源在场 → 品质由源给(板端 = 快照槽位透传);否则退 legacy
|
||||
* yc_read,品质从返回值推导(-1→IV / -2→NT / 0→无位)——旧注入源
|
||||
* 行为与卡 9 前**完全一致**(单测假源零改动)。判定顺序 IV > NT:
|
||||
* 开机首帧 qds=IV|NT 按无效处理(NT 只留给纯暂态)。任何无效 →
|
||||
* 信息体清零(线上口径:主站只信品质)。
|
||||
*/
|
||||
static int s_yc_point(uint8_t idx, float *v, uint8_t *q) {
|
||||
int rc;
|
||||
uint16_t q16 = 0u;
|
||||
|
||||
if ((idx >= YC_N) || (s_src == NULL)
|
||||
|| ((s_src->yc_read == NULL) && (s_src->yc_read_ex == NULL))) {
|
||||
*v = 0.0f;
|
||||
*q = (uint8_t)IEC104_QDS_IV;
|
||||
return -1;
|
||||
}
|
||||
rc = s_src->yc_read(idx, v);
|
||||
if (rc == 0) {
|
||||
if (qds != NULL) {
|
||||
*qds = 0u;
|
||||
}
|
||||
return 0;
|
||||
if (s_src->yc_read_ex != NULL) {
|
||||
rc = s_src->yc_read_ex(idx, v, &q16);
|
||||
} else {
|
||||
rc = s_src->yc_read(idx, v);
|
||||
q16 = (rc == -2) ? (uint16_t)MEAS_QDS_NT
|
||||
: ((rc != 0) ? (uint16_t)MEAS_QDS_IV : 0u);
|
||||
}
|
||||
if (v != NULL) {
|
||||
(void)rc; /* 有效性由归一后的 q 终裁(IV/NT 即无效),源返回值不直通 */
|
||||
*q = s_q_map(q16);
|
||||
rc = ((*q & (uint8_t)IEC104_QDS_IV) != 0u) ? -1
|
||||
: (((*q & (uint8_t)IEC104_QDS_NT) != 0u) ? -2 : 0);
|
||||
if (rc != 0) {
|
||||
*v = 0.0f;
|
||||
}
|
||||
if (qds != NULL) {
|
||||
*qds = (rc == -2) ? IEC104_QDS_NT : IEC104_QDS_IV;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:读遥测(值 + 线上品质位;无效值清零,判据见 s_yc_point)
|
||||
* 返 回 值:0 有效 / -1 无效(NT 亦无效,品质位与 IV 区分) int
|
||||
*/
|
||||
int iec104_pts_yc_read(uint8_t idx, float *v, uint8_t *qds) {
|
||||
float val = 0.0f;
|
||||
uint8_t q = (uint8_t)IEC104_QDS_IV;
|
||||
|
||||
(void)s_yc_point(idx, &val, &q);
|
||||
if (v != NULL) {
|
||||
*v = val;
|
||||
}
|
||||
return -1;
|
||||
if (qds != NULL) {
|
||||
*qds = q;
|
||||
}
|
||||
return (q == 0u) ? 0 : -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:写死区运行时值(「数据可信」卡 9;卡 10 运行参数段的落点入口)
|
||||
* 入口参数:idx - YC 表下标 db - 工程量绝对死区(≥0) float
|
||||
* 返 回 值:0 成功;-1 越界/负值/NaN(RAM 不动) int
|
||||
* 限定条件:**iec104Task 上下文**(配置属主 = defaultTask,卡 10 接线时经
|
||||
* 104 任务落地本调用,勿跨任务直调——本表状态无锁)
|
||||
* 函数说明:成功时清零该点待确认计数——跨死区档位不保留半截确认序列;
|
||||
* 不隐式重建基线(上送基准延续,新死区即刻生效)。
|
||||
*/
|
||||
int iec104_pts_yc_set_deadband(uint8_t idx, float db) {
|
||||
if ((idx >= YC_N) || !(db >= 0.0f) || !(db < 1000000.0f)) {
|
||||
return -1; /* NaN 被 !(db>=0) 捕获(比较式写法,防 lint 报恒真) */
|
||||
}
|
||||
s_yc_db[idx] = db;
|
||||
s_yc_cnf[idx] = 0u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:读当前生效死区
|
||||
* 入口参数:idx - YC 表下标
|
||||
* 返 回 值:运行时死区;idx 越界返 0.0 float
|
||||
* 限定条件:任意上下文(单字 float 读,Cortex-M 原子)
|
||||
* 函数说明:UI 回显 / 卡 10 读写往返校验用;ROM 默认查点表,勿在此反推。
|
||||
*/
|
||||
float iec104_pts_yc_deadband(uint8_t idx) {
|
||||
return (idx < YC_N) ? s_yc_db[idx] : 0.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -238,28 +335,72 @@ void iec104_pts_cov_check(iec104_pts_cov_t *cov) {
|
||||
s_yx_snap_ok = 1u;
|
||||
}
|
||||
|
||||
/* YC:死区比对(仅对"本次有效 且 上次有快照"的点判定) */
|
||||
if ((s_src != NULL) && (s_src->yc_read != NULL)) {
|
||||
uint8_t i;
|
||||
/* YC(卡 9):测点推进 = 板端源按快照换帧(100 ms poll vs 200 ms 快照,
|
||||
* 不去重则同一帧计两次 → "连续 2 点确认"退化成"连续 2 次轮询",单帧
|
||||
* 噪声即可被确认,抗噪语义失效);注入源 = 每次调用一测点。
|
||||
* 判定 = 死区连续 2 点确认 + 品质翻转直报(口径全文 → iec104_pts.h)。 */
|
||||
if ((s_src != NULL)
|
||||
&& ((s_src->yc_read != NULL) || (s_src->yc_read_ex != NULL))) {
|
||||
uint8_t step = 1u;
|
||||
|
||||
for (i = 0u; i < YC_N; i++) {
|
||||
float v;
|
||||
if (s_yc_seqmode != 0u) {
|
||||
uint32_t sq = meas_seq();
|
||||
|
||||
if (s_src->yc_read(i, &v) != 0) {
|
||||
continue;
|
||||
if (sq == s_yc_seq) {
|
||||
step = 0u; /* 未换帧:本 poll 不算新测量点 */
|
||||
} else {
|
||||
s_yc_seq = sq;
|
||||
}
|
||||
if (((s_yc_have >> i) & 1u) != 0u) {
|
||||
float d = v - s_yc_last[i];
|
||||
}
|
||||
if (step != 0u) {
|
||||
uint8_t i;
|
||||
|
||||
if (d < 0.0f) {
|
||||
d = -d;
|
||||
for (i = 0u; i < YC_N; i++) {
|
||||
float v;
|
||||
uint8_t q;
|
||||
int rc = s_yc_point(i, &v, &q);
|
||||
|
||||
if (((s_yc_have >> i) & 1u) == 0u) {
|
||||
if (rc == 0) { /* 首个有效读数只建线不上报(初值归总召) */
|
||||
s_yc_have |= (uint16_t)(1u << i);
|
||||
s_yc_rep[i] = v;
|
||||
s_yc_repq[i] = q;
|
||||
s_yc_cnf[i] = 0u;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (d > k_yc[i].deadband) {
|
||||
if (q != s_yc_repq[i]) {
|
||||
/* 品质翻转 = 事件直报(含 0x401d 的 IV 进出,卡 11) */
|
||||
local.yc_changed |= (uint16_t)(1u << i);
|
||||
s_yc_repq[i] = q;
|
||||
s_yc_cnf[i] = 0u;
|
||||
if (rc == 0) {
|
||||
s_yc_rep[i] = v;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (rc != 0) {
|
||||
s_yc_cnf[i] = 0u; /* 无效期间不计数(品质未变 = 状态延续) */
|
||||
continue;
|
||||
}
|
||||
{
|
||||
float d = v - s_yc_rep[i];
|
||||
|
||||
if (d < 0.0f) {
|
||||
d = -d;
|
||||
}
|
||||
if (d > s_yc_db[i]) {
|
||||
s_yc_cnf[i]++;
|
||||
if (s_yc_cnf[i] >= 2u) { /* 连续 2 越 → 确认:报 + 移基准 */
|
||||
local.yc_changed |= (uint16_t)(1u << i);
|
||||
s_yc_rep[i] = v;
|
||||
s_yc_cnf[i] = 0u;
|
||||
}
|
||||
} else {
|
||||
s_yc_cnf[i] = 0u; /* 回摆入死区 → 撤销候选(抗噪核心) */
|
||||
}
|
||||
}
|
||||
}
|
||||
s_yc_last[i] = v;
|
||||
s_yc_have |= (uint16_t)(1u << i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,24 +445,44 @@ int iec104_pts_set_write(uint32_t addr, float v, uint8_t select) {
|
||||
/* ============================ 板端默认源 ================================= */
|
||||
|
||||
/*
|
||||
* 函数功能:板端默认源 - 遥测 = 基波相量有效值(fAmSQ)
|
||||
* 返 回 值:0 / -1 无 phasor 源(削顶通道/频率未实现)/ -2 未满一周波(NT)
|
||||
* 函数功能:板端默认源 - 遥测 = L2 遥测快照直读(「数据可信」卡 9/卡 11)
|
||||
* 入口参数:idx - YC 表下标 out/qds - 值 + uint16 域品质(MEAS_QDS_*)
|
||||
* 返 回 值:0 / -1 越界或频率未新鲜(IV)/ -2 快照从未发布(NT) int
|
||||
* 限定条件:iec104Task 上下文(meas_get 为双区无锁读,App/algo/meas.h)
|
||||
* 函数说明:**不做任何本地判断**——电气路值/品质整体透传快照槽(削顶路快照
|
||||
* 已置 CLIPPED,s_q_map 映上线 IV;开机首帧 IV|NT 由 s_yc_point 按
|
||||
* IV 处理),"新不新、能不能信"全在发布侧一处决定(卡 8 设计意图,
|
||||
* 两处判断必打架)。频率路(PTS_SRC_FREQ):snap.freq_valid==0 →
|
||||
* IV(卡 11 DoD 原句);有效时值 = snap.freq_hz,与 freq_get() 同源。
|
||||
*/
|
||||
static int s_src_yc_read(uint8_t idx, float *out) {
|
||||
phasor_t p;
|
||||
int8_t pi;
|
||||
static int s_src_yc_read_ex(uint8_t idx, float *out, uint16_t *qds) {
|
||||
meas_snap_t snap;
|
||||
|
||||
if ((idx >= YC_N) || (out == NULL)) {
|
||||
if ((idx >= YC_N) || (out == NULL) || (qds == NULL)) {
|
||||
return -1;
|
||||
}
|
||||
pi = s_yc_phasor_idx[idx];
|
||||
if (pi < 0) {
|
||||
return -1; /* 无 phasor 源(削顶通道/频率未实现) */
|
||||
if (meas_get(&snap) != 0) {
|
||||
*out = 0.0f; /* 从未发布(开机 <200 ms)= 暂态 */
|
||||
*qds = (uint16_t)(MEAS_QDS_IV | MEAS_QDS_NT);
|
||||
return -2;
|
||||
}
|
||||
if (phasor_get((uint8_t)pi, &p) != 0) {
|
||||
return -2; /* 未满一周波:未就绪(NT) */
|
||||
if (k_yc[idx].src == (uint8_t)PTS_SRC_FREQ) {
|
||||
if (snap.freq_valid == 0u) {
|
||||
*out = 0.0f;
|
||||
*qds = (uint16_t)MEAS_QDS_IV;
|
||||
return -1;
|
||||
}
|
||||
*out = snap.freq_hz;
|
||||
*qds = 0u;
|
||||
return 0;
|
||||
}
|
||||
*out = p.fAmSQ; /* 有效值口径(系数已折算) */
|
||||
if (k_yc[idx].sem < 0) {
|
||||
*out = 0.0f; /* 理论不可达:现无未绑测量量点 */
|
||||
*qds = (uint16_t)MEAS_QDS_IV;
|
||||
return -1;
|
||||
}
|
||||
*out = snap.yc[(uint8_t)k_yc[idx].sem];
|
||||
*qds = snap.qds[(uint8_t)k_yc[idx].sem];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
* phasor/prot_elm/prot_set 真实源;主机单测绑假源 → 协议栈全链
|
||||
* (asdu+pts+link)可离线跑(登记簿 A-4 约束 1)。
|
||||
* 点表口径(docs/算法/继电保护功能复现规划.md §1.5,验收 = 省电科院点表):
|
||||
* - YC:IOA 0x4011~0x4018 + 0x401d(频率),短浮点、系数 1;
|
||||
* ⚠ V0.1 有效通道仅 UA/UN/IA(TPAFE 三路,§1.6)——其余点**存在但置 IV**
|
||||
* (无效位),频率随 L1-7 落地前同样置 IV;
|
||||
* - YC:IOA 0x4011~0x4018 + 0x401d(频率),短浮点、系数 1;数据源 =
|
||||
* L2 遥测快照(App/algo/meas.h,「数据可信」卡 9/11):电气 8 路绑快照槽,
|
||||
* 有效性由快照品质驱动——V0.1 削顶路(docs/算法/继电保护功能复现规划.md
|
||||
* §1.6)快照置 CLIPPED → 本层映射为线上 IV(V0.2/N-18 后自动启用,绑定零
|
||||
* 改动,见 docs/任务规划/数据可信.md §10 行 N-18);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)——
|
||||
@@ -21,6 +24,11 @@
|
||||
* 按未知 IOA(COT 14 + EVI)应答,登记为待办(设计文档)。
|
||||
* 线程约定:init/bind 内核启动前或建服务前;cov_check/read 仅 104 服务任务上下文。
|
||||
* 创建日期:2026-10-12(B4)
|
||||
* 修改记录:
|
||||
* 2026-10-25 DTU 项目组 卡 9/卡 11(「数据可信」,道D):YC 数据源 = L2 遥测
|
||||
* 快照(削顶路由品质驱动 IV);死区改运行时副本 +
|
||||
* set/get 入口;COV 遥测腿 = 死区 2 点确认(seq 去重)
|
||||
* + 品质变化即报;0x401d 绑频率源(freq_valid → IV)。
|
||||
*/
|
||||
#ifndef IEC104_PTS_H
|
||||
#define IEC104_PTS_H
|
||||
@@ -42,6 +50,11 @@ typedef struct {
|
||||
int (*set_read)(uint32_t addr, float *out);
|
||||
/* 定值写:select=1 预置校验(范围)/ 0 执行写入。返回 0 / -1 越界或未知 */
|
||||
int (*set_write)(uint32_t addr, float v, uint8_t select);
|
||||
/* 遥测读(带品质,卡 9 追加于表尾——旧源 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 输出) ---------------- */
|
||||
@@ -65,8 +78,15 @@ 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 等)。返回 0/无效-1 */
|
||||
/* 读 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);
|
||||
/* 死区运行时写(「数据可信」卡 9;卡 10 运行参数段的落点入口):
|
||||
* db = 工程量绝对值 ≥0;越界/负值/NaN → -1 且 RAM 不动;成功时清零该点
|
||||
* 待确认计数(跨死区基线不残留半截确认)。仅 104 服务任务上下文调用。 */
|
||||
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);
|
||||
@@ -77,10 +97,19 @@ void iec104_pts_yx_read(uint8_t idx, uint8_t *out);
|
||||
|
||||
/* ---------------- COV(每 poll 一次) ---------------- */
|
||||
/*
|
||||
* 函数功能:读全表快照并与上次比对(变位 + 死区),输出变化集
|
||||
* 函数功能:读全表并与上次比对(遥信变位 + 遥测死区 2 点确认 + 品质变化),
|
||||
* 输出变化集
|
||||
* 入口参数:cov - 输出(可为 NULL = 只刷快照不取变化)
|
||||
* 函数说明:首次调用只建快照、变化集全 0(突发由初始化/总召覆盖)。
|
||||
* 死区 = 点表内置绝对值(§1.5 运行参数 8020H 段本期取内置默认)。
|
||||
* 函数说明:遥测判据(「数据可信」卡 9,对标参考系统 CalfYcMea 死区 2 点确认,
|
||||
* 短板评测口径):**连续 2 个新测量点** |v - 上次上送值| > 死区才置变化位
|
||||
* (单点尖峰不确认——噪声回摆即撤销候选);品质位(线上 qds)相对上次
|
||||
* 上送值翻转 → 当拍直接置位(不等 2 点,有效性变化必须即时可见,
|
||||
* 含 0x401d 的 IV 进出)。死区 = 运行时副本(ROM 默认 = 点表列,
|
||||
* iec104_pts_yc_set_deadband() 覆盖——卡 10 运行参数段的接线点)。
|
||||
* 测量点定义:板端默认源 = **快照换帧**(meas seq 前进;100 ms poll 对
|
||||
* 200 ms 快照,同一帧重复比对会计数两次 → seq 去重是确认语义成立的
|
||||
* 前提);注入源(单测假源)= 每次调用一测点。首次读到有效值只建基线
|
||||
* 不上报(突发由总召覆盖)。
|
||||
*/
|
||||
void iec104_pts_cov_check(iec104_pts_cov_t *cov);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user