#!/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())