7c505b2457
用户裁定(2026-11-13):设备本体只需要校正后的参数,不需要自己拟合 标定曲线,故固件侧最小二乘拟合整体移出,拟合的唯一实现留在 PC 侧 test/host/cal_fit.py。 删除的死代码(生产零调用、上一轮 map 里已被 linker 标 Removing): - adc_cal.h:adc_cal_fit() 声明、8 个拒绝码、5 个常量 - adc_cal.c:s_div_round() / s_fit_accum() / adc_cal_fit() 共 224 行 - adc_cal_test.c:tc_00b_fit 226 行(184 -> 150 条) 原样保留的设备侧安全闸: - adc_cal_apply() 折算、adc_cal_set() / adc_cal_set_ratio() 参数合法 带拦截(防工具写坏参数)、adc_cal_flags() / adc_cal_prot_blocked() / adc_cal_rail_ths()。设备不「算」,但必须「用」和「验」。 测试面: - cal_fit.py 转为唯一实现,新增 --selftest:承接原 C 侧金标向量 (r_q16=39322000 / b=12)与 4 条拒绝路径,共 11 条断言;已做变异 测试证明它会红(改坏圆整口径 -> 2 条 FAIL) - cal_two_point.py 删除,两点工具由多点拟合取代 文档口径统一为「求参在 PC、设备只做折算与合法带校验」,6 篇 docs 同步; 执行卡改名 ADC多点标定执行流程.md(正文同步 5 点最小二乘口径)。 cfg 热重载吞段缺陷的解析器契约与 TC-CONFIG-063 机器钉一并入库。 Program Size 不变(Code=256196):删掉的是从未链接进镜像的死代码。 验证:Keil 0 errors 0 warnings;adc_cal 150/150;selftest 11/11; ci_local.py RC=0(static 48/48、manual 三根、size-gate、host-unit 4341/4341);doc-links / mermaid / mojibake 全 0。
93 lines
3.6 KiB
Python
93 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""两点标定写入器:C_SE_NC_1 两段写下发 r/b,C_RD 读回复核。
|
||
|
||
复用台架已验收主站库 test/host/iec104_master.py(不重写协议层)。
|
||
地址(App/algo/run_par.c run_par_104_write):r = 0x8050+slot,
|
||
b = 0x8048+slot;slot UA0/UN3/IA4。执行卡:
|
||
docs/测试说明/专项验证/ADC多点标定执行流程.md §4。
|
||
|
||
用法:
|
||
python test/host/cal_write.py --r 0x8050=995.99 --b 0x8048=-1 \
|
||
--read 0x8050,0x8048 --expect 995.99,-1
|
||
python test/host/cal_write.py --read 0x8050,0x8054 --expect 995.99,29.52
|
||
|
||
写入顺序刻意**先 r 后 b**:b 走 adc_cal_set() 置 VALID 位,而 VALID 要求
|
||
r 已在带——先让 r 就位,语义干净。--b 必须是整数码值。
|
||
PN(否定确认)= 执行段拒绝:看串口 `[ERR] set ch=... rejected` 行。
|
||
输出纯 ASCII,可直接重定向归档为台架证据;exit 0 全过 / 1 有失败 / 2 连接或协议错误。
|
||
"""
|
||
import argparse
|
||
import os
|
||
import sys
|
||
|
||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||
import bench_defaults # noqa: E402
|
||
import iec104_master as m104 # noqa: E402
|
||
|
||
|
||
def parse_pair(text):
|
||
addr_s, val_s = text.split("=", 1)
|
||
return int(addr_s, 0), float(val_s)
|
||
|
||
|
||
def main():
|
||
ap = argparse.ArgumentParser()
|
||
ap.add_argument("--ip", default=bench_defaults.DEVICE_IP)
|
||
ap.add_argument("--port", type=int, default=2404)
|
||
ap.add_argument("--r", action="append", default=[],
|
||
help="0xADDR=FLOAT ratio write (repeatable, issued first)")
|
||
ap.add_argument("--b", action="append", default=[],
|
||
help="0xADDR=INT zero-code write (repeatable, sets VALID)")
|
||
ap.add_argument("--read", default="",
|
||
help="comma-separated IOA list, C_RD readback")
|
||
ap.add_argument("--expect", default="",
|
||
help="comma-separated expected values, same order as --read")
|
||
a = ap.parse_args()
|
||
|
||
reads = [x.strip() for x in a.read.split(",") if x.strip()]
|
||
expects = [float(x) for x in a.expect.split(",")] if a.expect else []
|
||
if not a.r and not a.b and not reads:
|
||
ap.error("need at least one --r / --b / --read")
|
||
|
||
ck = m104.Checks()
|
||
try:
|
||
m = m104.Master(a.ip, a.port)
|
||
except Exception as exc:
|
||
print("CONNECT FAIL: %r" % (exc,))
|
||
return 2
|
||
|
||
try:
|
||
m._send(m104.u_frame(m104.U_STARTDT_ACT), "U STARTDT act")
|
||
ck.add("startdt_con", m.wait_event(
|
||
lambda e: e[0] == "startdt_con", 5.0) is not None)
|
||
|
||
for text in a.r: # 1) ratio first
|
||
addr, val = parse_pair(text)
|
||
m104.se_write(m, ck, addr, val, "r_%04X" % addr)
|
||
|
||
for text in a.b: # 2) zero + VALID
|
||
addr, val = parse_pair(text)
|
||
if abs(val - round(val)) > 1e-6:
|
||
print("WARN b=%s not an integer code, truncated to %.0f"
|
||
% (text, round(val)))
|
||
val = float(round(val))
|
||
m104.se_write(m, ck, addr, val, "b_%04X" % addr)
|
||
|
||
for i, addr_s in enumerate(reads):
|
||
want = expects[i] if i < len(expects) else 0.0
|
||
m104.rd_set(m, ck, int(addr_s, 0), want, "rd_%s" % addr_s)
|
||
finally:
|
||
m.close()
|
||
|
||
bad = [n for n, ok, _ in ck.items if not ok]
|
||
print("SUMMARY %s total=%d fail=%d" %
|
||
("PASS" if not bad else "FAIL", len(ck.items), len(bad)))
|
||
if bad:
|
||
print("FAILED: %s" % ", ".join(bad))
|
||
return 0 if not bad else 1
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|