2. SCPI基础回顾
在深入探讨SCPI脚本的批量执行、重试机制与日志追踪之前,必须夯实SCPI(Standard Commands for Programmable Instruments,可编程仪器标准命令)的基础。SCPI并非一种编程语言,而是一种基于ASCII字符的仪器控制协议,它定义了仪器与控制器之间通信的语法、命令结构和数据格式。理解SCPI的语法规则、典型应用场景及其与底层I/O库(VISA)和上层驱动模型(IVI)的关系,是编写健壮、可维护自动化测试脚本的前提。本章将系统梳理这些核心概念,为后续章节的脚本工程化实践奠定坚实的语言基础。
上图清晰地展示了SCPI、VISA与IVI在仪器控制体系中的分层关系。SCPI位于最上层,直接面向测试工程师,提供语义化的命令;VISA作为中间层,屏蔽了GPIB、USB、LAN等物理总线的差异;IVI则进一步封装,提供跨厂商的类驱动接口。下面我们将逐一深入剖析。
2.1 SCPI命令语法:从助记符到语义单元
核心原理:树形命令结构与复合头
SCPI命令采用树形层次结构,类似于文件系统的目录。命令由助记符(Mnemonic)组成,多个助记符通过冒号(:)分隔,形成从根到叶的路径。例如,:MEASure:VOLTage:DC? 表示“测量直流电压”这一操作。助记符有两种形式:长格式(如 MEASure)和短格式(如 MEAS)。短格式通常取长格式的前四个字母,若前四个字母相同则取前三个,但必须保证唯一性。实际编程中,为了代码可读性,建议统一使用长格式或短格式,避免混用。
命令头之后可以跟随参数,参数与命令头之间用空格分隔。查询命令以问号(?)结尾,用于向仪器请求数据。例如:
:MEAS:VOLT:DC? 1.0, 0.001 ; 查询1V量程、0.001V分辨率的直流电压
:SOUR:FREQ 1MHz ; 设置信号源频率为1MHz
:OUTP ON ; 打开输出
判断方法与操作流程:解析命令的五个要素
在编写脚本时,解析一条SCPI命令需要关注五个要素:命令头(路径)、参数个数、参数类型(数值、布尔、字符串)、单位前缀(如MHZ、MV、DBM)以及返回格式。一个常见的错误是忽略单位前缀。SCPI允许在数值后附加单位,但仪器内部会将其转换为基准单位。例如,:SOUR:FREQ 1.5GHz 与 :SOUR:FREQ 1.5E9 等效。
| 命令示例 | 命令头 | 参数 | 返回 | 说明 |
|---|---|---|---|---|
| :MEAS:VOLT:DC? 10, 0.001 | :MEAS:VOLT:DC? | 10(量程), 0.001(分辨率) | 浮点数 | 测量直流电压 |
| :SOUR:FREQ 1MHz | :SOUR:FREQ | 1MHz(频率) | 无 | 设置频率 |
| :OUTP:STAT? | :OUTP:STAT? | 无 | ON/OFF | 查询输出状态 |
| :SYST:ERR? | :SYST:ERR? | 无 | 错误码, "描述" | 读取错误队列 |
案例拆解:用示波器测量上升时间
假设我们需要用示波器测量一个时钟信号的上升时间。传统手动操作需要按多个按键,而SCPI只需三条命令:
:TIM:SCAL 1E-6 ; 设置时基为1us/div
:MEAS:RIS? CH1 ; 测量CH1的上升时间
:SYST:ERR? ; 检查是否有错误
这里的关键在于,:MEAS:RIS? 返回的是一个浮点数,但若仪器未正确触发,可能返回 9.9E37(表示无效值)。因此,脚本中必须对返回值进行范围判断,而非仅判断是否为空。
:SYST:ERR? 的查询。当命令语法错误或参数超限时,仪器不会主动报错,而是将错误码存入队列。若不及时读取,错误队列会溢出,导致后续命令被丢弃。建议在每条命令后或批量操作后查询一次错误队列。
2.2 常见仪器控制场景:从单机测量到系统同步
核心原理:四大典型场景
SCPI的应用场景可归纳为四类:配置与初始化(如设置电压、电流、量程)、数据采集(如读取测量值、波形数据)、状态查询(如检查仪器忙/闲、错误状态)以及触发与同步(如等待触发事件、设置仪器间同步)。在批量测试中,配置与采集往往交替进行,而触发同步则是保证测试时序的关键。
操作流程:一个典型的电源-万用表测试序列
- 初始化:复位仪器(
*RST),清除状态(*CLS)。 - 配置电源:设置电压5V,限流1A,使能输出。
- 配置万用表:设置为直流电压测量模式,量程10V。
- 触发测量:发送
:READ?或:MEAS?命令。 - 读取数据:解析返回的ASCII字符串为浮点数。
- 收尾:关闭输出,查询错误队列。
*RST
*CLS
:SOUR:VOLT 5.0
:SOUR:CURR 1.0
:OUTP ON
:MEAS:VOLT:DC? 10, 0.001
:OUTP OFF
:SYST:ERR?
案例拆解:多仪器同步触发
在射频测试中,常需要信号源和频谱仪同步工作。假设信号源输出脉冲,频谱仪需要在外触发信号到来时开始扫描。SCPI实现如下:
信号源::OUTP:TRIG ON ; 开启触发输出
频谱仪::TRIG:SOUR EXT ; 设置外触发
:INIT:CONT OFF ; 关闭连续测量
:INIT ; 启动单次测量,等待触发
这里的关键在于,:INIT 命令会立即返回,仪器在后台等待触发。脚本需要轮询 :STAT:OPER:COND? 或使用 *OPC? 来确认测量完成。若忽略同步等待,直接读取数据,将得到无效值。
*OPC?(操作完成查询)代替固定延时。固定延时不仅浪费测试时间,而且在仪器负载变化时可能导致时序错误。*OPC? 会阻塞直到所有挂起操作完成,返回1。
2.3 与VISA/IVI的关系:分层架构与职责边界
核心原理:VISA是“手臂”,IVI是“大脑”
VISA(Virtual Instrument Software Architecture)是底层I/O库,负责建立控制器与仪器之间的物理连接。它提供了统一的API,支持GPIB、USB、LAN(VXI-11或HiSLIP)、串口等接口。VISA的核心概念是资源(Resource)和会话(Session)。资源是仪器的地址描述,如 TCPIP0::192.168.1.100::INSTR;会话是打开资源后返回的操作句柄。
IVI(Interchangeable Virtual Instruments)则构建在VISA之上,提供了更高层的仪器类驱动。它将SCPI命令封装为属性(Property)和方法(Method)。例如,使用IVI控制万用表,只需设置 DMM.MeasurementFunction = DCVolts,而无需关心底层是哪个品牌的仪器。IVI还支持状态缓存(Cache)和仪器仿真(Simulation),极大提升了代码复用性和调试效率。
对比分析:何时选择SCPI直写,何时选择IVI
| 维度 | 直接使用SCPI | 使用IVI驱动 |
|---|---|---|
| 开发效率 | 低,需查阅仪器手册 | 高,类驱动统一接口 |
| 代码可移植性 | 差,更换仪器需重写 | 好,支持互换 |
| 执行性能 | 高,无额外封装 | 略低,有属性解析开销 |
| 调试便利性 | 依赖VISA日志 | 支持仿真与跟踪 |
| 适用场景 | 单机测试、性能敏感 | 系统集成、多厂商设备 |
案例拆解:从SCPI到IVI的迁移
假设我们有一个测试系统,原使用Keysight万用表,现需更换为Keithley万用表。直接使用SCPI的代码需要修改所有测量命令。而使用IVI,只需在初始化时指定驱动名称:
// 使用IVI C# 示例
IviDmm dmm = new IviDmm("KeithleyDMM");
dmm.MeasurementFunction = IviDmmMeasurementFunction.DCVolts;
dmm.Range = 10.0;
double reading = dmm.ReadMeasurement();
这段代码在更换仪器时,只需将 "KeithleyDMM" 改为 "KeysightDMM",其余逻辑完全不变。但需要注意的是,IVI驱动内部仍会生成SCPI命令,因此理解SCPI语法有助于排查IVI调用中的异常。
GPIB0::1::INSTR,而USB设备为 USB0::0x2A8D::0x5101::MY12345::INSTR。在脚本中硬编码这些字符串会降低可移植性,建议通过 viFindRsrc 动态搜索仪器。