4. 变量与数据作用域
在 TestStand 中,变量作用域决定了“谁看得见、谁改得动、活多久”。很多序列调试失败并不是逻辑写错,而是把数据放错了作用域:本应只属于某次执行的临时值被写进了文件全局变量,导致下一次运行被污染;或者本应跨序列共享的配置被塞进序列局部变量,结果另一个序列根本读不到。理解四类变量的生命周期与可见范围,是设计跨步骤、跨序列数据传递方案的前提。
四类变量的定位与生命周期
序列局部变量(Sequence Local)定义在单个序列内部,只有该序列的步骤能访问。它的生命周期与序列的一次执行绑定:序列被调用时创建,执行结束时销毁。它适合存放只在本序列内部流转的中间量,例如循环计数、临时计算结果、某一步骤产生的句柄。它的优点是隔离性好,不会干扰其他序列;缺点是出了这个序列就“看不见”,无法直接用于跨序列传递。
文件全局变量(File Global)定义在序列文件(.seq)层级,该文件内所有序列都能读写。生命周期与序列文件被加载到内存的时间一致,而不是与某次执行绑定。它适合存放“同一文件内多个序列共享、且需要在多次执行之间保留”的数据,例如本文件内通用的配置项、缓存、状态标志。需要注意:如果 TestStand 同时加载了多个序列文件,每个文件各有自己独立的文件全局变量空间,同名变量互不影响。
站全局变量(Station Global)定义在 Station 层级,作用于当前测试站上运行的所有序列文件。它的生命周期最长,通常随 TestStand 引擎/站配置持久化,重启后仍可保留(取决于是否保存到站配置)。它适合存放整站级别的资源信息,例如仪器地址、工位编号、操作员权限、标定系数。正因为影响面大,修改站全局变量要格外谨慎,避免一个序列的写入影响其他并行执行的序列。
运行时变量(Run-Time)是 TestStand 引擎在运行时维护的一类变量,典型如 RunState、RunState.Root、RunState.Sequence、RunState.TestSockets 等。它们反映当前执行上下文,例如当前序列、当前步骤、循环索引、测试插座状态。运行时变量通常由引擎管理,序列通过表达式读取,用于获取“当前正在发生什么”,而不是用来长期保存业务数据。
跨步骤传递:优先用序列局部变量
同一个序列内,步骤之间传递数据最自然的方式就是序列局部变量。例如一个序列先执行“打开仪器”步骤,把返回的仪器句柄存入局部变量 Locals.InstrHandle,后续“设置量程”“读取测量值”步骤再引用它。这样做的关键点是:局部变量随序列执行创建,不会残留到下一次运行,天然避免了脏数据。
在 TestStand 中,步骤间传递还可以借助 Step.Result 与 Step.DataSource。例如某一步骤的返回值可以通过 Step.Result.Numeric 被后续步骤读取,但这种方式耦合了步骤顺序,一旦插入或删除步骤就容易断链。更稳妥的做法是在步骤的 Post-Expression 或后续步骤的 Pre-Expression 中显式赋值给局部变量,让数据流清晰可查。
跨序列传递:参数优先,全局变量兜底
跨序列传递数据时,最推荐的是参数传递。在 Sequence Call 步骤中,通过“Specify Module”选择被调序列,然后在 Parameters 选项卡中把调用方的表达式映射到被调序列的参数。被调序列在 Sequence Properties 的 Parameters 中声明形参,并在内部用 Parameters.xxx 引用。这样数据流向明确、接口清晰,被调序列不依赖外部全局状态,复用性最好。
当数据是“多个序列都要用、且不适合层层传参”的共享配置时,才考虑文件全局变量。例如同一 .seq 文件内,多个测试序列都需要读取同一个“测试限值表”,可以把它放在文件全局变量中,由初始化序列写入一次,其他序列读取。此时要约定:谁负责写、什么时候写、写完是否要复位。建议在文件全局变量命名上加上用途前缀,如 FG_Config_、FG_Cache_,便于识别。
站全局变量适合真正整站级别的数据,例如当前工位号、仪器资源地址、操作员 ID。它不应被用作“方便传递”的捷径,因为并行执行时多个序列可能同时读写,产生竞争。若必须使用,应尽量只读、或在初始化阶段集中写入。
运行时变量的正确用法
运行时变量不是用来存业务数据的,而是用来“问引擎当前状态”。例如在步骤中通过 RunState.Sequence.Name 获取当前序列名,通过 RunState.LoopIndex 获取当前循环索引,通过 RunState.TestSockets.MyIndex 获取当前测试插座编号。这些值由引擎维护,序列只读使用。把它们误当作可写存储,会导致执行上下文混乱。
一个可落地的传递方案示例
假设有一个测试流程:主序列 MainSequence 负责初始化,调用 InitInstrument 打开仪器,再调用 RunTest 执行测量,最后调用 CloseInstrument 关闭。数据传递方案可以这样设计:
InitInstrument通过参数返回仪器句柄,主序列把它存入序列局部变量Locals.InstrHandle。- 主序列调用
RunTest时,把Locals.InstrHandle作为参数传入,RunTest内部用Parameters.Handle接收。 - 测试限值这类跨序列共享配置,放在文件全局变量
FG_Config_Limits中,由主序列初始化时写入一次。 - 工位号、操作员 ID 这类整站信息,放在站全局变量
SG_StationID、SG_Operator中,只读使用。 - 循环索引、当前序列名等,直接读
RunState,不另存变量。
这样设计后,数据流向清晰:局部变量管“本次执行内的中间量”,文件全局变量管“本文件共享配置”,站全局变量管“整站资源”,运行时变量管“当前上下文”。跨序列调用优先走参数,全局变量只做兜底和共享配置,既保证了模块化,又避免了作用域滥用带来的隐蔽缺陷。