2. TestStand系统架构与资源管理模型

TestStand 的工程能力并不是由单一程序完成的,而是由一组职责明确的组件协同构成。理解这套架构,是后续做序列开发、部署和资源管理的前提。可以把 TestStand 的运行时体系理解为三层:最底层是TestStand 引擎,中间层是面向开发者的序列编辑器与部署工具,最上层是面向系统集成的资源管理器与资源映射机制。引擎负责执行,编辑器负责编写,部署工具负责搬运,资源管理负责让序列在不同工位上都能找到正确的仪器与文件。

一、TestStand 引擎:执行的核心

TestStand 引擎(Engine)是一个独立的执行内核,它不依赖图形界面即可运行。序列编辑器、操作员界面(Operator Interface)、部署后的测试站,本质上都是通过 ActiveX/COM 或 .NET API 去调用同一个引擎。引擎负责的事情包括:加载序列文件、解析步骤、管理执行流程(顺序、分支、循环、跳转)、维护变量作用域、调用代码模块(LabVIEW、C/C++ DLL、.NET 程序集、Python 等)、记录测试结果并生成报告。

引擎的关键特性是多执行线程。一个测试站可以同时运行多个执行(Execution),每个执行拥有独立的变量空间和调用栈。例如并行测试两个 UUT 时,会创建两个执行实例,它们共享 Station Globals 的只读部分,但各自维护自己的局部变量。这一点直接决定了资源映射的设计方式:如果两个执行同时访问同一台仪器,就必须通过资源管理器做互斥或分派,否则会出现仪器争用。

二、序列编辑器与部署工具

序列编辑器(Sequence Editor)是开发阶段的主要工作台,用于创建序列文件(.seq)、编辑步骤、配置变量、调试单步执行。它本身也是引擎的一个宿主,因此编辑器里能跑通的序列,部署后行为应当一致——前提是资源映射和路径配置正确。

部署工具(Deployment Utility)解决的是“从开发机搬到测试站”的问题。它会把序列文件、代码模块、依赖的 DLL、配置文件、驱动等打包成一个部署包,并生成部署清单。部署时常见的坑是绝对路径失效:开发机上代码模块放在 D:\Projects\...,测试站上可能根本没有 D 盘。因此部署工具支持把路径改为相对路径或使用搜索路径(Search Paths),配合 Station Globals 中的路径变量,才能让序列在目标机上正确加载。

三、资源管理器与资源映射机制

资源管理器(Resource Manager)是 TestStand 中用于统一管理“外部资源”的机制,这里的资源包括仪器(VISA 资源名、IVI 逻辑名)、文件、数据库连接、代码模块等。它的核心思想是:序列中不写死物理资源,而是引用一个逻辑名称,由资源映射在运行时把逻辑名称解析为当前工位实际的物理资源。

资源映射通常通过 Station Globals 中的变量或配置文件实现。例如在 Station Globals 里定义一个 StationGlobals.Instruments.DMM,值为 GPIB0::15::INSTR;序列步骤中引用这个变量而不是直接写地址。当同一套序列部署到另一台使用 GPIB0::22::INSTR 的工位时,只需修改该工位的 Station Globals,序列本身无需改动。这就是资源映射带来的可移植性。

Station Globals 是“站级全局变量”,作用域覆盖整个测试站的所有序列和执行。它适合存放工位相关的配置:仪器地址、文件根目录、操作员权限、校准系数等。与序列文件内的 File Globals 不同,Station Globals 不随序列文件走,而是随测试站走。

四、Station Globals 与资源映射的配合

实际工程中,推荐的做法是把 Station Globals 组织成树状结构,按功能分组,例如 StationGlobals.Paths、StationGlobals.Instruments、StationGlobals.Limits。资源映射则通过一个“逻辑名 → 物理资源”的对照表来完成。下面给出一个可直接参考的配置示例:

StationGlobals
├─ Paths
│   ├─ SequenceRoot = "C:\TestStand\Sequences"
│   ├─ ReportDir    = "C:\TestStand\Reports"
│   └─ LogDir       = "C:\TestStand\Logs"
├─ Instruments
│   ├─ DMM_LogicalName = "DMM_MAIN"
│   ├─ DMM_Address     = "GPIB0::15::INSTR"
│   ├─ PSU_LogicalName = "PSU_MAIN"
│   └─ PSU_Address     = "TCPIP0::192.168.1.50::inst0::INSTR"
└─ Limits
    ├─ VoltageMin = 4.75
    └─ VoltageMax = 5.25

序列步骤中通过 StationGlobals.Instruments.DMM_Address 获取实际地址,再传给 VISA 打开函数。这样,当工位更换仪器时,只改 Station Globals 即可。需要注意的是,Station Globals 的修改在引擎运行期间是全局可见的,因此对它的写入要考虑并发安全;一般建议在测试开始前完成配置,运行中只读。

五、架构协同关系

把上述组件放在一起看,它们的关系可以用一张结构图清晰表达:引擎是执行中心,编辑器与部署工具是开发侧入口,Station Globals 是配置数据的载体,资源映射是连接逻辑名与物理资源的桥梁,最终由引擎在运行时完成解析与调用。

序列编辑器 编写 .seq / 调试 部署工具 打包 / 路径重映射 TestStand 引擎 加载序列 / 执行流程 多执行线程 / 结果记录 Station Globals Paths / Instruments Limits / 站级配置 资源映射 逻辑名 → 物理资源 DMM_MAIN → GPIB0::15 物理仪器 / 文件 DMM / PSU / 报告目录 读取配置 解析 调用 运行时请求资源 引擎执行序列时,通过 Station Globals 与资源映射把逻辑名解析为当前工位的物理资源

从图中可以看到,序列编辑器与部署工具把序列和依赖送到引擎;引擎在执行时读取 Station Globals 中的配置,再通过资源映射把逻辑名解析为物理资源,最终调用仪器或访问文件。整条链路中,唯一与具体工位绑定的就是 Station Globals 和资源映射表,序列文件本身保持工位无关,这正是 TestStand 资源管理模型的核心价值。

六、实践中的判断依据

判断资源管理是否配置正确,可以看三个现象:第一,序列在开发机上运行正常,部署到测试站后不报“找不到文件”或“无效资源名”;第二,更换仪器地址时只改 Station Globals,序列无需重新编辑;第三,并行执行多个 UUT 时,仪器访问不冲突、结果不串扰。如果出现资源争用,应检查是否对共享仪器做了互斥,或是否把本应独立的资源错误地放进了全局变量。