安捷伦Signal Generators Programming Guide 记录

目录

Signal Generators Programming Guide 记录

Interfaces

GPIB

 数据传输很快,因为GPIB以字节为单位处理信息数据传输速率高达8Mbps。GPIB在物理上受到位置和仪器/系统与计算机之间的距离;电缆仅限于每个装置的平均长度为两米,总长度为20米。

将信号发生器配置为通过GPIB进行通信:

LAN

 因为使用LAN处理数据包,数据传输速度很快。 计算机和信号发生器之间的单根电缆距离限制为100米。

 ESG、PSG和E8663B设计用于连接10Base-T局域网(10M速率双绞线缆)

以下协议可用于通过LAN与信号发生器通信:

VXI-11 (recommended)

Sockets

TELNET

FTP

将信号发生器配置为通过LAN进行通信:

USB(Keysight MXG Only)

 后面板Mini-B 5针连接器是一个设备USB,可用于连接控制器进行远程操作。

 Type-A型前面板连接器是一个主机USB,可用于连接鼠标、键盘或USB 1.1/2.0闪存驱动器。

 USB 2.0的64 MBps通信速度快于GPIB(用于数据传输,>1 KB)或RS-232接口。

PS:
ESG和PSG的辅助接口连接器与ANSI/EIA232兼容(RS-232)串行连接,但建议使用GPIB和LAN进行更快的测量和下载文件。

IO Libraries and Programming Languages

 IO库是编程语言用于发送仪器命令并接收仪器数据。
 在你通信和控制信号发生器之前,您必须有一个IO库安装在您的计算机上。

VISA Configuration (Automatic)

  1. Run the VISA Assistant program:

  2. Start > All Programs > Keysight IO Libraries Suite > Keysight Connection
    Expert > Tools > Visa Assistant >.

  3. Click on the interface you want to use for sending commands to the signal generator.

  4. Click the Formatted I/O tab.

  5. Select SCPI in the Instr. Lang. section.

 You can enter SCPI commands in the text box and send the command using
the viPrintf button.

Using VISA Configuration (Manual)

 使用Keysight IO Libraries Suite 15.0执行以下步骤以使用连接专家和VISA手动配置接口。

  1. Run the Keysight Connection Expert program: Start > All Programs > Keysight IO Libraries Suite > Keysight Connection Expert >.

  2. On the tool bar select the Add Interface button.

  3. Click LAN Interface in the Available interface types text box.

  4. Click the ADD button.

  5. Verify that the Auto (automatically detect protocol) bubble is checked. Click O.K. to use the default settings.

  6. Click LAN(TCPIPO) in the Instrument I/O on this PC text box.

  7. On the tool bar select the Add Instrument button.

  8. Click the Add Address button in the Add LAN Instruments window.

  9. Enter the hostname of the instrument or select the Use IP Address check box and enter the IP address.

10.Click OK.

Selecting IO Libraries for GPIB

 VISA是一个IO库,用于开发IO应用程序和符合行业标准的仪表驱动程序。建议将VISA库用于对信号发生器进行编程。NI-VISA和Keysight VISA库与VISA和具有相同的命令、语法和功能。差异在于较低级别的IO库;分别为NI-488.2和SICL。最好将Keysight VISA库与Keysight GPIB一起使用接口卡或带有NI PCI-GPIB接口的NI-VISA卡片。

 Keysight SICL可以在没有VISA覆盖的情况下使用。

 NI-488.2可以在没有VISA覆盖的情况下使用。

Selecting IO Libraries for LAN

 TELNET和FTP协议不需要在你的电脑上安装IO库。但是,要编写程序来控制您的信号发生器,必须在您的计算机上安装一个IO库,并且计算机配置为使用LAN接口进行仪器控制。

Programming Languages

 连同用于编程指令(SCPI)和IO的标准命令库函数,您可以使用编程语言远程控制信号发生器。常见的编程语言包括:

C/C++
C#
MATLAB
HP Basic
LabView
Java
Visual Basic
PERL
Keysight VEE

Configuring the Display for Remote Command Setups (ESG/PSG)

在这里插入图片描述

Error Messages

 如果信号发生器中出现错误情况,错误信息会向SCPI(远程接口)错误队列和前面板显示错误队列报告。这两个队列分别进行查看和管理。

 使用SCPI(远程接口)错误队列访问错误消息时,错误队列响应的错误编号和错误描述部分显示在主机终端上。

在这里插入图片描述

Error Message File

 文件errormessages.pd f中提供了错误消息的完整列表,位于随仪器提供的CD-ROM。在错误消息列表中解释通常包括在每个错误中,以进一步阐明其含义。错误消息以数字形式列出。在存在多个对于相同错误编号的列表,消息按字母顺序排列。

Error Message Types

 事件只生成一种类型的错误。例如,生成查询错误的事件不会生成特定于设备的、执行或命令错误。

查询错误(-499到-400) 表明仪器的输出队列控件检测到所描述的消息交换协议存在问题见IEEE 488.2第6章。此类中的错误在事件状态寄存器中查询错误位(位2)
设置(IEEE 488.2,第11.5.1节)。这些错误对应于IEEE 488.2、6.5中描述的消息交换协议错误。示例:

当没有输出存在或挂起,或者输出队列中的数据已丢失。

设备特定错误(-399到-300、201到703和800到810) 表明设备操作没有正确完成,可能是由于异常硬件或固件条件。这些代码也用于自检响应错误。此类错误在事件状态寄存器中的设备特定错误位(位3)设置(IEEE 488.2,第11.5.1节)。
 SCPI未定义表示正错误( positive )的<error_message>字符串。正错误表示仪器在GPIB系统、仪器固件或硬件、块数据传输期间或校准期间检测到错误。

执行错误(-299到-200) 表明仪器的执行控制块检测到错误。此类中的错误在事件状态寄存器中的执行错误位(第4位)设置(IEEE 488.2,第11.5.1节)
示例:

标题后面的元素被设备评估为超出其合法输入范围,或者与设备的功能不一致,
或由于某些设备条件无法正确执行有效的程序消息。

执行错误在四舍五入和表达式求值操作完成之后报告 。对数字数据元素四舍五入,
例如,未报告为执行错误。

命令错误(–199到–100) 表明仪器的解析器检测到IEEE 488.2语法错误。此类中在事件状态寄存器中的设置命令错误位(第5位)设置(IEEE 488.2,第11.5.1节)。示例:
  解析器检测到IEEE 488.2语法错误(收到了违反IEEE的控制到设备消息488.2标准。可能的违规行为包括违反设备监听格式或设备无法接受其类型。)或者收到无法识别的标头。其中包括不正确的设备特定标头和不正确或未实现的IEEE 488.2通用命令。

Using IO Interfaces

Using GPIB

  GPIB使仪器能够连接在一起,并由计算机控制。GPIB及其相关接口操作在
ANSI/IEEE标准488.1–1987和ANSI/IEEE标准486.2–1992中被定义。通过IEEE网站,http://www.ieee.org,了解有关这些标准的详细信息。

  以下部分包含有关安装GPIB接口卡的信息或用于PC或基于UNIX的系统的NI–GPIB接口卡。

Installing the GPIB Interface

 您可以使用Keysight 82357A USB/GPIB接口转换器将GPIB仪器连接到PC USB端口,消除了GPIB卡的需要。请参阅 http://www.keysight.com/find/gpib

 GPIB接口卡可以安装在计算机中。两个通用GPIB接口卡是Keysight GPIB接口卡和National仪器(NI)PCI–GPIB卡。按照接口卡说明进行操作安装和配置卡。下表列出了一些可用的接口卡。另请参阅Keysight网站,http://www.keysight.com有关GPIB接口卡的详细信息。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Set Up the GPIB Interface

在这里插入图片描述

Verify GPIB Functionality

 为了验证GPIB功能, 使用Keysight IO库提供的VISA助手或National Instruments IO库提供的入门向导。这些实用程序使您能够与信号生成器通信,并通过GPIB验证其操作。运行这些程序的有关信息和说明,请参阅每个实用程序中的“帮助”菜单。

GPIB Interface Terms

作为GPIB网络的一部分的仪器被分类为收听者(listener)、讲话者(talker)或控制器(controller),取决于其在网络中的当前功能。

listener监听器是一种能够接收数据或来自其他仪器的命令。几种仪器在GPIB网络中可以同时成为监听器
talker讲话器是一种能够传输数据的设备。到为了避免混淆,GPIB系统只允许一个设备一次成为一个积极的谈话者。
controller控制器,通常是计算机,可以指定讲话者以及听众(包括其自身)获取信息转移。一次只能有一个设备处于活动状态控制器

GPIB Programming Interface Examples

 本节中讨论的编程示例部分摘自“Programming Examples”中的程序,

Before Using the GPIB Examples

 如果使用Keysight GPIB接口卡,则Keysight VISA库应与Keysight SICL一起安装。如果National Instruments PCI–GPIB使用接口卡,NI–VISA库和NI–488.2库应该安装。请参阅“Selecting IO Libraries for GPIB”查询GPIB接口卡详细信息。

 HP Basic将信号发生器的地址定为719。GPIB卡的地址为7和19处的信号发生器。其他的GPIB地址指示符库通常是GPIB0或GPIB1。

Interface Check Using NI–488.2 and C++

 使用NI–488.2库验证GPIB连接和接口功能。有关此程序的全文,请参阅“Interface Check Using NI-488.2 and C++”细节。

#include "stdafx.h"
#include <iostream>
#include "windows.h"
#include "Decl-32.h"
using namespace std;

int GPIB0= 0; // Board handle
Addr4882_t Address[31]; // Declares an array of type Addr4882_t

int main(void)
{
	int sig; // Declares a device descriptorvariable
	
	sig = ibdev(0, 19, 0, 13, 1, 0); // Aquires a device descriptor
	ibclr(sig); 		//Sends device clear message to signal generator
	
	ibwrt(sig, "*RST", 4); // Places the signal generatorinto a defined state

Using LAN

 ESG,PSG和E8663B设计用于连接10Base-T局域网。

 信号发生器可以通过100Base-T LAN接口或10Base-T LAN接口使用多种LAN接口协议之一连接LAN的计算机进行远程编程。局域网允许仪器连接在一起并由基于局域网的计算机控制。LAN及其相关的接口操作在IEEE 802.2标准中定义。

 有关为局域网配置信号发生器的更多信息,请参阅信号发生器的User’s Guide

信号发生器支持以下LAN接口协议:

— VXI–11

— Sockets LAN

— Telephone Network (TELNET)

— File Transfer Protocol (FTP)

— LXI

 VXI-11和套接字LAN用于使用LAN接口进行一般编程,TELNET用于交互式,一次一个命令仪器控制,FTP用于文件传输。LXI用于通过使用精确时间协议的LAN事件与多个仪器进行通信。

Setting Up the LAN Interface

 对于LAN操作,信号发生器必须连接到LAN,并且IP地址必须手动或通过使用DHCP客户端服务设置。
在这里插入图片描述

Manual Configuration(手动配置)

Hostname软键仅在LAN配置手动DHCP设置为手动时可用。要从不同的LAN子网远程访问信号发生器,您还必须输入子网掩码和默认网关。
在这里插入图片描述

DHCP Configuration(DHCP配置)

 如果DHCP服务器使用动态DNS将主机名与分配的IP地址链接起来,则可以使用主机名代替IP地址。否则主机名不可用。

在这里插入图片描述

Setting up Private LAN

 您可以使用交叉电缆将Keysight MXG、ESG或PSG直接连接到PC。要执行此操作,您应该选择设置PC和信号发生器仅在最后一位不同 (示例: PC’s IP: 1.1.1.1
and Signal generator’s IP: 1.1.1.2); 或者您可以使用DHCP功能或自动IP功能(如果您的电脑支持)。欲了解更多信息,请访问 www.keylight.com,搜索 Connectivity Guide (E2094–90009) 。或者在Keysight Connection Expert的help中查看 Connection Guide

Verifying LAN Functionality

 使用 ping 指令验证计算机和信号发生器 远程文件服务器 之间的通信链路。

在MS–DOS命令提示符或Windows环境中,键入:

ping -n 10 <hostname or IP address>

其中<主机名或IP地址>是仪器的名称或IP地址,10是回波请求的数量。在命令提示符下键入ping以获取ping命令的详细信息。

 PS:如果您在信号发生器上的LAN连接遇到问题,请验证后面板LAN连接器绿色LED是否打开,有关LAN连接故障排除的更多信息,请参阅Keysight IO库中的帮助。

 按下并释放LAN Reset(局域网复位)硬键一次,将仪器复位至出厂默认条件,默认IP地址为169.254.9.16。如果网络上有一个DHCP服务器,N5161A/62A将获得一个IP地址从它开始。如果网络上没有DHCP服务器,则仪器将切换到自动IP模式并分配默认IP地址为169.254.9.16

这相当于发送以下SCPI命令:

:SYSTem:COMMunicate:LAN:DEFaults
:SYSTem:COMMunicate:LAN:RESTart

 按下LAN Reset(局域网复位)硬键5秒钟(直到LAN指示灯闪烁)将仪器重置为手动设置的条件。

 如果有多个N5161A/62A仪器在同一台仪器上运行网络,一个仪器将使用默认的IP地址值其他仪器将随机选择IP地址值。如果您尚未手动设置N5161A/62A仪器的IP地址(并且您需要知道地址),请依次打开每个N5161A/62A仪器以设置默认IP地址。

局域网Ping响应
DOS或Windows的正常响应如果指定了10个回显请求,则对ping命令的正常响应将是总共收到9或10个数据包。
错误消息如果出现错误消息,请检查命令语法,然后继续故障排除。如果语法正确,请使用网络解决错误消息文档或咨询网络管理员。如果出现未知主机错误消息,请尝试使用IP地址替代主机名。
没有回应如果ping没有响应,则没有接收到任何数据包。检查键入的地址或主机名是否与分配给系统LAN安装程序中信号发生器的IP地址或主机名匹配。沿工作站和信号发生器之间的路线Ping每个节点。如果信号发生器仍然对ping没有响应,则应怀疑是硬件问题。检查信号发生器局域网连接器指示灯。验证主机名未与DHCP寻址一起使用。
间歇性响应如果您收到1到8个数据包,则可能是网络出现问题。在带有交换机和网桥的网络中,最初的几个ping信号可能会丢失,直到这些设备“了解”主机的位置。此外,由于收到的数据包数量取决于您的流量和完整性,因此您的网络的数量可能不同。
使用交互式IO

 使用Keysight IO Libraries套件中提供的VISA Assistant实用程序通过LAN接口验证仪器通信。

使用VISA助手
 使用Keysight IO Library版本M及更早版本提供的VISA助手通过LAN接口与信号发生器进行通信。但是,您必须手动配置VISA LAN客户端。请参阅帮助有关配置和运行VISA Assistant程序的说明的菜单。

  1. Run the IO Config program.
  2. Click on TCPIP0 in the Available Interface Types text box.
  3. Click the Configure button. Then Click OK to use the default settings.
  4. Click on TCPIP0 in the Configured Interfaces text box.
  5. Click Edit…
  6. Click the Edit VISA Config… button.
  7. Click the Add device button.
  8. Enter the TCPIP address of the signal generator. Leave the Device text box
    empty.
  9. Click the OK button in this form and all subsequent forms to exit the IO Config program. If You Have Problems

如果有问题:

  1. Verify the signal generator’s IP address is valid and that no other instrument is using the IP address.
  2. Switch between manual LAN configuration and DHCP using the front panel LAN Config softkey and run the ping program using the different IP addresses.
Using Sockets LAN

 套接字局域网是一种用于通过使用传输控制协议/互联网协议的局域网接口(TCP/IP)。套接字是用于计算机网络的基本技术并允许应用程序使用内置的标准机制进行通信网络硬件和操作系统。该方法访问信号发生器上的端口,从该端口可以建立与网络计算机的双向通信。

 套接字局域网可以被描述为一个互联网地址,它结合了网络之间互连的协议(IP)和一个设备端口号,并代表两个软件之间的单个连接。可以使用与计算机操作系统一起打包的代码库访问套接字。套接字库的两个常见版本是用于UNIX系统的Berkeley套接字库和用于Microsoft操作系统的Winsock。

 信号发生器也与兼容其他标准套接字API。可以使用SCPI控制信号发生器输出到程序中建立的套接字连接的命令。
 在使用套接字局域网之前,必须选择信号发生器的要使用的套接字端口号:

标准模式。在端口5025上可用。使用此端口进行简单操作编程。
TELNET模式。telnet SCPI服务在端口5023上可用。

 为了向后兼容,在E8663B、ESG和PSG上,信号发生器还接受对端口7777处的Telnet SCPI服务和端口7778处的套接字SCPI服务的引用。

Using Telnet LAN

 Telnet提供了一种通过局域网与信号发生器通信的方法。Telnet客户端在连接LAN的计算机上运行,将在信号生成器上创建登录会话。在计算机和信号发生器之间建立的连接,在命令行上生成带有SCPI>提示的用户交互界面显示屏。

 使用Telnet协议向信号生成器发送命令类似通过GPIB与信号发生器通信。 您与信号发生器建立连接,然后发送或接收信息使用SCPI命令。沟通是互动的:一次一个命令。

Programming Examples

Using the Programming Interface Examples

 信号发生器远程控制的编程示例使用GPIB、LAN和RS-232接口,并演示使用不同的IO库和编程语言。本章中的许多例子程序是交互式的;将提示用户执行某些操作或验证信号发生器的操作或功能。实例程序是用以下语言编写的:

HP Basic
C#
C/C++
Microsoft Visual Basic 6.0
Java
MATLAB
Perl

 示例程序将信号发生器设置为远程模式;前面板键,Keysight MXG Local/Esc/Cancel 或ESG、PSG Local 按键除外,其余被禁用。按下Keysight MXG Local/Esc/Cancel 或ESG、PSG Local 按键恢复到手动操作。3

 要根据远程操作引起的更改更新信号发生器的前面板,请启用信号发生器的远程更新功能。

远程更新功能会降低测试执行速度。为了更快的测试执行,禁用“远程更新”功能

Programming Examples Development Environment

C/C++示例是使用与IBM兼容的个人计算机编写的计算机(PC),配置如下:

— Pentium processor

— Windows NT 4.0 operating system or later

— C/C++ programming language with the Microsoft Visual C++ 6.0 IDE

— National Instruments PCI-GPIB interface card or Keysight GPIB
interface card

— National Instruments VISA Library or Keysight VISA library

— COM1 or COM2 serial port available

— LAN interface card

Running C++ Programs

使用Microsoft VisualC++6.0运行示例程序时,请在项目中包含以下文件。

使用VISA库时:

— add the visa32.lib file to the Resource Files
— add the visa.h file to the Header Files

使用NI-488.2库时:

— add the GPIB-32.OBJ file to the Resource Files

— add the windows.h file to the Header Files

— add the Deci-32.h file to the Header Files

Running C# Examples

你必须有 .NET 框架安装在您的计算机上。您还必须在计算机上安装Keysight IO库。

LAN Programming Interface Examples

 本节中的局域网编程示例演示了 VXI-11 和 Sockets 局域网来控制信号发生器。要使用这些编程示例,您必须更改对IP地址和主机名的引用以匹配信号发生器的IP地址和主机名。

VXI-11 Programming

 信号发生器支持VXI-11仪器标准通过LAN接口进行通信。 Keysight IO 库支持VXI-11标准,并且必须在使用VXI-11协议之前安装在您的计算机上。

 VXI-11示例使用TCPIP0作为板地址。

VXI-11与GPIB程序配合使用

 使用VISA库的GPIB编程示例,可以很容易地通过改变地址串来使用LAN VXI-11协议。比如说,将“GPIB::19::INSTR”地址字符串更改为“TCPIP::hostname::INSTR”,其中hostname是信号发生器的IP地址或主机名。VXI-11协议具有与GPIB相同的功能。

PS:要通过LAN接口与信号发生器通信必须启用VXI-11 SCPI服务。

VXI-11 Programming Using SICL and C++

 以下程序使用VXI-11协议和SICL来控制信号发生器。在运行此代码之前,您必须使用Keysight IO库的IO配置单元设置接口。

vxisicl.cpp执行以下操作功能:

— sets signal generator to 1 GHz CW frequency

— queries signal generator for an ID string

— error checking

//*****************************************************************
//
// PROGRAM NAME:vxisicl.cpp
//
// PROGRAM DESCRIPTION:Sample test program using SICL and the VXI-11 protocol
//
// NOTE: You must have the Keysight IO Libraries installed to run this program.
//
// This example uses the VXI-11 protocol to set the signal generator for a 1 gHz CW 
// frequency. The signal generator is queried for operation complete and then queried
// for its ID string. The frequency and ID string are then printed to the display.
//
// IMPORTANT: Enter in your signal generators hostname in the instrumentName
//declaration
// where the "xxxxx" appears.
//
//*****************************************************************
#include "stdafx.h"
#include <sicl.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
	INST id; // Device session id
	int opcResponse; // Variable for response flag
	char instrumentName[] = "xxxxx"; // Put your instrument's hostname here
	char instNameBuf[256];			// Variable to hold instrument name
	char buf[256];					// Variable for id string
	ionerror(I_ERROR_EXIT);			// Register SICL error handler
	
	// Open SICL instrument handle using VXI-11 protocol
	sprintf(instNameBuf, "lan[%s]:inst0", instrumentName);
	id = iopen(instNameBuf);		// Open instrument session
	itimeout(id, 1000);				// Set 1 second timeout for operations
	printf("Setting frequency to 1 Ghz...\n");
	iprintf(id, "freq 1 GHz\n");	// Set frequency to 1 GHz
	printf("Waiting for source to settle...\n");
	iprintf(id, "*opc?\n");			// Query for operation complete
	iscanf(id, "%d", &opcResponse); // Operation complete flag
	if (opcResponse != 1)			// If operation fails, prompt user
	{
		printf("Bad response to 'OPC?'\n");
		iclose(id);
		exit(1);
	}
	iprintf(id, "FREQ?\n");			// Query the frequency
	iscanf(id, "%t", &buf);			// Read the signal generator frequency
	printf("\n");					// Print the frequency to the display
	printf("Frequency of signal generator is %s\n", buf);
	ipromptf(id, "*IDN?\n", "%t", buf);// Query for id string
	printf("Instrument ID: %s\n", buf);// Print id string to display
	iclose(id);							// Close the session
	return 0;
}
VXI-11 Programming Using VISA and C++

 以下程序使用VXI-11协议和VISA库进行控制信号发生器。信号发生器设置为–5 dBm功率电平,并且查询其ID字符串。在运行此代码之前,必须设置接口使用Keysight IO Libraries IO Config 单元。vxivisa.cpp执行以下功能:

-将信号发生器设置为–5 dBm功率电平
-查询信号生成器以获取ID字符串
-错误检查

//*****************************************************************
// PROGRAM FILE NAME:vxivisa.cpp
// Sample test program using the VISA libraries and the VXI-11 protocol
//
// NOTE: You must have the Keysight Libraries installed on your computer to run
// this program
//
// PROGRAM DESCRIPTION:This example uses the VXI-11 protocol and VISA to query
// the signal generator for its ID string. The ID string is then printed to the
// screen. Next the signal generator is set for a -5 dBm power level and then
// queried for the power level. The power level is printed to the screen.
//
// IMPORTANT: Set up the LAN Client using the IO Config utility
//
//*****************************************************************
#include <visa.h>
#include <stdio.h>
#include "StdAfx.h"
#include <stdlib.h>
#include <conio.h>
#define MAX_COUNT 200
int main (void)
{
	ViStatus status;			// Declares a type ViStatus variable
	ViSession defaultRM, instr;// Declares a type ViSession variable
	ViUInt32 retCount;			// Return count for string I/O
	ViChar buffer[MAX_COUNT];	// Buffer for string I/O
	status = viOpenDefaultRM(&defaultRM); // Initialize thesystem
	// Open communication with Serial
	// Port 2
	status = viOpen(defaultRM, "TPCIP0::19::INSTR", VI_NULL,VI_NULL, &instr);
	if(status){ 			// If problems then prompt user
		printf("Could not open ViSession!\n");
		printf("Check instruments and connections\n");
		printf("\n");
		exit(0);}
	// Set timeout for 5 seconds
	viSetAttribute(instr, VI_ATTR_TMO_VALUE, 5000);
	// Ask for sig gen ID string
	status = viWrite(instr, (ViBuf)"*IDN?\n", 6, &retCount);
	// Read the sig gen response
	status = viRead(instr, (ViBuf)buffer, MAX_COUNT, &retCount);
	buffer[retCount]= '\0'; // Indicate the end of the string
	printf("Signal Generator ID = "); // Print header for ID
	printf(buffer);					 // Print the ID string
	printf("\n");					 // Print carriage return
	// Flush the read buffer
	// Set sig gen power to-5dbm
	status = viWrite(instr, (ViBuf)"POW:AMPL -5dbm\n", 15,&retCount);
	// Query the power level
	status = viWrite(instr, (ViBuf)"POW?\n",5,&retCount);
	// Read the power level
	status = viRead(instr, (ViBuf)buffer, MAX_COUNT, &retCount);
	buffer[retCount]= '\0';	 		// Indicate the end of the string
	printf("Power level = ");		 // Print header to the screen
	printf(buffer); // Print the queried power level
	printf("\n");
	status = viClose(instr); 		// Close down the system
	status = viClose(defaultRM);
	return 0;
}
Sockets LAN Programming and C

 由两个文件组成;lanio.c和getopt.c。lanio.c文件有两个主功能;int main() 和一个int main1()。

 int main() 函数允许从命令行与信号生成器交互通信。程序从命令行读取信号发生器的主机名,然后是SCPI命令。然后它使用端口5025打开信号发生器的套接字,并发送命令。如果该命令是查询指令,则程序会向信号发生器查询响应,并打印响应。
int main 1() 重命名为 int main() 后,将向信号发生器输出一系列命令。您可以将格式用作模板,然后添加自己的代码。

Sockets on Windows
 在Windows中,必须使用例程 send() 和 recv(),因为 fread() 和 fwrite() 可能不适用于套接字。以下步骤概述了在Microsoft Visual C++6.0环境中运行交互式程序:

PS:lanio.cpp文件中的 int main() 函数将允许发送命令以逐行格式发送到信号发生器;用户在SCPI中键入命令。单击“从生成”菜单中的“全部重新生成”。然后单击执行Lanio.exe。

1.将lanio.c重命名为lanio.cpp,将getopt.c重命名为getopt.cpp并添加它们 到Visual C++项目的Source文件夹。
2.单击“Build ”菜单中的“Rebuild All”。然后单击执行Lanio.exe 调试窗口将出现,并提示“按任意键继续”。这表明程序已经编译,可以用来向信号发生器发送命令。
3.单击 Start,单击Programs,然后单击Command Prompt。命令将出现提示窗口。
4.在命令提示符下,cd到包含lanio.exe文件的目录然后转到Debug文件夹。例如C:\SocketIO\Lanio\Debug。
5.cd到lanio.exe文件所在的目录后,在命令提示符下输入以下命令:

cpp lanio xxxxx “*IDN?”
示例: C: \SocketIO\Lanio\Debug>Lanio
xxxxx“*IDN?”其中xxxxx是信号生成器的主机名。使用此格式从命令提示符以逐行格式向信号发生器输出SCPI命令。
6.在命令提示符下键入exit退出程序。

Programming Using main1() Function
 int main 1() 函数将以程序格式输出一系列命令。如果您想使用一系列命令运行程序,那么执行以下操作:

1.在lanio. cpp程序的 main 1() 函数的openSocket函数中输入信号生成器的主机名。
2.将lanio. cpp int main 1() 函数重命名为 int main() ,将原始 int main() 函数重命名为int main 1() 。
3.从“Build ”菜单中选择“Rebuild All”。然后选择执行Lanio.exe

在这里插入图片描述

Queries for Lan Using Sockets

lanio.c和getopt.c执行以下功能:

-建立到端口5025的TCP/IP连接
-生成的文件描述符用于使用常规套接字I/O机制与仪器“对话”
-将所需的主机名映射到内部表单
-错误检查
-查询信号生成器以获取ID
-将信号发生器的频率设置为2.5 GHz
-将信号发生器的电源设置为-5 dBm
-从参数向量中获取选项字母并检查文件结尾(EOF)

/******************************************************************
* $Header: lanio.c 04/24/01
* $Revision: 1.1 $
* $Date: 10/24/01
* PROGRAM NAME: lanio.c
*
* $Description: Functions to talk to an Keysight signal generator
* via TCP/IP. Uses command-line arguments.
*
* A TCP/IP connection to port 5025 is established and
* the resultant file descriptor is used to "talk" to the
* instrument using regular socket I/O mechanisms.
$
*
* Examples:
*
* Query the signal generator frequency:
* lanio xx.xxx.xx.x 'FREQ?'
*
* Query the signal generator power level:
* lanio xx.xxx.xx.x 'POW?'
*
* Check for errors (gets one error):
* lanio xx.xxx.xx.x 'syst:err?'
*
* Send a list of commands from a file, and number them:
* cat scpi_cmds | lanio -n xx.xxx.xx.x
*
*******************************************************************
*
* This program compiles and runs under
* - HP-UX 10.20 (UNIX), using HP cc or gcc:
* + cc -Aa -O -o lanio lanio.c
* + gcc -Wall -O -o lanio lanio.c
*
* - Windows 95, using Microsoft Visual C++ 4.0 Standard Edition
* - Windows NT 3.51, using Microsoft Visual C++ 4.0
* + Be sure to add WSOCK32.LIB to your list of libraries!
* + Compile both lanio.c and getopt.c
* + Consider re-naming the files to lanio.cpp and getopt.cpp
*
* Considerations:
* - On UNIX systems, file I/O can be used on network sockets.
* This makes programming very convenient, since routines like
* getc(), fgets(), fscanf() and fprintf() can be used. These
* routines typically use the lower level read() and write() calls.
*
* - In the Windows environment, file operations such as read(),
write(), and close() cannot be assumed to work correctly when applied to
* sockets. Instead, the functions send() and recv() MUST be used.
******************************************************************/
/* Support both Win32 and HP-UX UNIX environment */
#ifdef _WIN32 /* Visual C++ 6.0 will define this */
	# define WINSOCK
#endif
#ifndef WINSOCK
	# ifndef _HPUX_SOURCE
		# define _HPUX_SOURCE
	# endif
#endif

#include <stdio.h> /* for fprintf and NULL */
#include <string.h> /* for memcpy and memset */
#include <stdlib.h> /* for malloc(), atol() */
#include <errno.h> /* for strerror */

#ifdef WINSOCK
	#include <windows.h>
	# ifndef _WINSOCKAPI_
		# include <winsock.h> // BSD-style socket functions
	# endif
#else /* UNIX with BSD sockets */
	# include <sys/socket.h> /* for connect and socket*/
	# include <netinet/in.h> /* for sockaddr_in */
	# include <netdb.h> /* for gethostbyname */
	# define SOCKET_ERROR (-1)
	# define INVALID_SOCKET (-1)
	typedef int SOCKET;
#endif /* WINSOCK */

#ifdef WINSOCK
	/* Declared in getopt.c. See example programs disk. */
	extern char *optarg;
	extern int optind;
	extern int getopt(int argc, char * const argv[], const char*optstring);
#else
	# include <unistd.h> /* for getopt(3C) */
#endif

#define COMMAND_ERROR (1)
#define NO_CMD_ERROR (0)
#define SCPI_PORT 5025
#define INPUT_BUF_SIZE (64*1024)

/******************************************************************
* Display usage
******************************************************************/
static void usage(char *basename)
{
	fprintf(stderr,"Usage: %s [-nqu] <hostname> [<command>]\n",basename);
	fprintf(stderr," %s [-nqu] <hostname> < stdin\n",basename);
	fprintf(stderr," -n, number output lines\n");
	fprintf(stderr," -q, quiet; do NOT echo lines\n");
	fprintf(stderr," -e, show messages in error queue whendone\n");
}
#ifdef WINSOCK

int init_winsock(void)
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD(1, 1);
	wVersionRequested = MAKEWORD(2, 0);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) {
		/* Tell the user that we couldn't find a useable */
		/* winsock.dll. */
		fprintf(stderr, "Cannot initialize Winsock 1.1.\n");
		return -1;
	}
	return 0;
}
int close_winsock(void)
{
	WSACleanup();
	return 0;
}
#endif /* WINSOCK */
/******************************************************************
*
> $Function: openSocket$
*
* $Description: open a TCP/IP socket connection to the instrument
$
*
* $Parameters: $
* (const char *) hostname . . . . Network name of instrument.
* This can be in dotted decimal notation.
* (int) portNumber . . . . . . . The TCP/IP port to talk to.
* Use 5025 for the SCPI port.
*
* $Return: (int) . . . . . . . . A file descriptor similar to open(1).$
*
* $Errors: returns -1 if anything goes wrong $
*
******************************************************************/
SOCKET openSocket(const char *hostname, int portNumber)
{
	struct hostent *hostPtr;
	struct sockaddr_in peeraddr_in;
	SOCKET s;
	memset(&peeraddr_in, 0, sizeof(struct sockaddr_in));
	/***********************************************/
	/* map the desired host name to internal form. */
	/***********************************************/
	hostPtr = gethostbyname(hostname);
	if (hostPtr == NULL)
	{
		fprintf(stderr,"unable to resolve hostname '%s'\n",hostname);
		return INVALID_SOCKET;
	}
	/*******************/
	/* create a socket */
	/*******************/
	s = socket(AF_INET, SOCK_STREAM, 0);
	if (s == INVALID_SOCKET)
	{
		fprintf(stderr,"unable to create socket to '%s': %s\n",hostname,strerror(errno));
		return INVALID_SOCKET;
}
	memcpy(&peeraddr_in.sin_addr.s_addr, hostPtr->h_addr,hostPtr->h_length);
	peeraddr_in.sin_family = AF_INET;
	peeraddr_in.sin_port = htons((unsigned short)portNumber);
	if (connect(s, (const struct sockaddr*)&peeraddr_in,sizeof(struct sockaddr_in)) == SOCKET_ERROR)
	{
		fprintf(stderr,"unable to create socket to '%s': %s\n",hostname,strerror(errno));
		return INVALID_SOCKET;
	}

	return s;
}
/******************************************************************
*
> $Function: commandInstrument$
*
* $Description: send a SCPI command to the instrument.$
*
* $Parameters: $
* (FILE *) . . . . . . . . . file pointer associated with TCP/IP socket.
* (const char *command) . . SCPI command string.
* $Return: (char *) . . . . . . a pointer to the result string.
*
* $Errors: returns 0 if send fails $
*
******************************************************************/
int commandInstrument(SOCKET sock,
const char *command)
{
	int count;
	/* fprintf(stderr, "Sending \"%s\".\n", command); */
	if (strchr(command, '\n') == NULL) {
		fprintf(stderr, "Warning: missing newline on command %s.\n",command);
	}
	count = send(sock, command, strlen(command), 0);
	if (count == SOCKET_ERROR) {
	return COMMAND_ERROR;
	}
	return NO_CMD_ERROR;
}

/******************************************************************
* recv_line(): similar to fgets(), but uses recv()
******************************************************************/
char * recv_line(SOCKET sock, char * result, int maxLength)
{
#ifdef WINSOCK
	int cur_length = 0;
	int count;
	char * ptr = result;
	int err = 1;
	while (cur_length < maxLength) {
		/* Get a byte into ptr */
		count = recv(sock, ptr, 1, 0);
		/* If no chars to read, stop. */
		if (count < 1) {
			break;
		}
		cur_length += count;
		/* If we hit a newline, stop. */
		if (*ptr == '\n') {
			ptr++;
			err = 0;
			break;
		}
		ptr++;
	}
	*ptr = '\0';
	if (err) {
		return NULL;
	} 
	else {
	return result;
	}
#else
/******************************************************************
* Simpler UNIX version, using file I/O. recv() version works
too.
* This demonstrates how to use file I/O on sockets, in UNIX.
******************************************************************/
	FILE * instFile;
	instFile = fdopen(sock, "r+");
	if (instFile == NULL)
	{
		fprintf(stderr, "Unable to create FILE * structure : %s\n",
		strerror(errno));
		exit(2);
	}
	return fgets(result, maxLength, instFile);
#endif
}

/******************************************************************
*
> $Function: queryInstrument$
*
* $Description: send a SCPI command to the instrument, return a response.$
*
* $Parameters: $
* (FILE *) . . . . . . . . . file pointer associated with TCP/IP socket.
* (const char *command) . . SCPI command string.
* (char *result) . . . . . . where to put the result.
* (size_t) maxLength . . . . maximum size of result array in bytes.
*
* $Return: (long) . . . . . . . The number of bytes in result buffer.
*
* $Errors: returns 0 if anything goes wrong. $
*
******************************************************************/
long queryInstrument(SOCKET sock,const char *command, char *result, size_t maxLength)
{
	long ch;
	char tmp_buf[8];
	long resultBytes = 0;
	int command_err;
	int count;
/*********************************************************
* Send command to signal generator
*********************************************************/
	command_err = commandInstrument(sock, command);
	if (command_err) return COMMAND_ERROR;
/*********************************************************
* Read response from signal generator
********************************************************/
	count = recv(sock, tmp_buf, 1, 0); /* read 1 char */
	ch = tmp_buf[0];
	if ((count < 1) || (ch == EOF) || (ch == '\n'))
	{
		*result = '\0'; /* null terminate result for ascii */
		return 0;
	}
/* use a do-while so we can break out */
	do
	{
		if (ch == '#')
		{
			/* binary data encountered - figure out what it is */
			long numDigits;
			long numBytes = 0;
			/* char length[10]; */
			count = recv(sock, tmp_buf, 1, 0); /* read 1 char */
			ch = tmp_buf[0];
			if ((count < 1) || (ch == EOF)) break; /* End of file */
			if (ch < '0' || ch > '9') break; /* unexpected char */
			numDigits = ch - '0';
			if (numDigits)
			{
				/* read numDigits bytes into result string. */
				count = recv(sock, result, (int)numDigits, 0);
				result[count] = 0; /* null terminate */
				numBytes = atol(result);
			}
			
			if (numBytes)
			{
				resultBytes = 0;
				/* Loop until we get all the bytes we requested. */
				/* Each call seems to return up to 1457 bytes, on HP-UX 9.05 */
				do {
					int rcount;
					rcount = recv(sock, result, (int)numBytes, 0);
					resultBytes += rcount;
					result += rcount; /* Advance pointer */
				} while ( resultBytes < numBytes );
/************************************************************
* For LAN dumps, there is always an extra trailing newline
* Since there is no EOI line. For ASCII dumps this is
* great but for binary dumps, it is not needed.
***********************************************************/
				if (resultBytes == numBytes)
				{
					char junk;
					count = recv(sock, &junk, 1, 0);
				}
			}
			else
			{
				/* indefinite block ... dump til we can an extra line feed */
				do
				{
					if (recv_line(sock, result, maxLength) == NULL)break;
					if (strlen(result)==1 && *result == '\n') break;
					resultBytes += strlen(result);
					result += strlen(result);
				} while (1);
			}
		}
		else
		{
			/* ASCII response (not a binary block) */
			*result = (char)ch;
			if (recv_line(sock, result+1, maxLength-1) == NULL)return 0;
			/* REMOVE trailing newline, if present. And terminate string. */
			resultBytes = strlen(result);
			if (result[resultBytes-1] == '\n') resultBytes -= 1;
			result[resultBytes] = '\0';
		}
	} while (0);
	return resultBytes;
}


/******************************************************************
*
> $Function: showErrors$
*
* $Description: Query the SCPI error queue, until empty. Print results. $
*
* $Return: (void)
*
******************************************************************/
void showErrors(SOCKET sock)
{
	const char * command = "SYST:ERR?\n";
	char result_str[256];
	do {
		queryInstrument(sock, command, result_str,sizeof(result_str)-1);
/******************************************************************
* Typical result_str:
* -221,"Settings conflict; Frequency span reduced."
* +0,"No error"
* Don't bother decoding.
******************************************************************/
	if (strncmp(result_str, "+0,", 3) == 0) {
		/* Matched +0,"No error" */
		break;
	}
	puts(result_str);
	} while (1);
}
/******************************************************************
*
> $Function: isQuery$
*
* $Description: Test current SCPI command to see if it a query. $
*
* $Return: (unsigned char) . . . non-zero if command is a query. 0 if not.
*
******************************************************************/
unsigned char isQuery( char* cmd )
{
	unsigned char q = 0 ;
	char *query ;
/*********************************************************/
/* if the command has a '?' in it, use queryInstrument. */
/* otherwise, simply send the command. */
/* Actually, we must be a more specific so that */
/* marker value querys are treated as commands. */
/* Example: SENS:FREQ:CENT (CALC1:MARK1:X?) */
/*********************************************************/
	if ( (query = strchr(cmd,'?')) != NULL)
	{
/* Make sure we don't have a marker value query, or
* any command with a '?' followed by a ')' character.
* This kind of command is not a query from our point of
view.
* The signal generator does the query internally, and uses
the result.
*/
		query++ ; /* bump past '?' */
		while (*query)
		{
			if (*query == ' ') /* attempt to ignore white spc */
				query++ ;
			else break ;
		}
		if ( *query != ')' )
		{
			q = 1 ;
		}
	}
	return q ;
}

主函数

/******************************************************************
*
> $Function: main$
*
* $Description: Read command line arguments, and talk to signal generator.
Send query results to stdout. $
*
* $Return: (int) . . . non-zero if an error occurs
*
******************************************************************/
int main(int argc, char *argv[])
{
	SOCKET instSock;
	char *charBuf = (char *) malloc(INPUT_BUF_SIZE);
	char *basename;
	int chr;
	char command[1024];
	char *destination;
	unsigned char quiet = 0;
	unsigned char show_errs = 0;
	int number = 0;
	
	basename = strrchr(argv[0], '/');
	if (basename != NULL)basename++ ;
	else basename = argv[0];
	
	while ( ( chr = getopt(argc,argv,"qune")) != EOF )
	switch (chr)
	{
		case 'q': quiet = 1; break;
		case 'n': number = 1; break ;
		case 'e': show_errs = 1; break ;
		case 'u':
		case '?': usage(basename); exit(1) ;
	}
	/* now look for hostname and optional <command>*/
	if (optind < argc)
	{
		destination = argv[optind++] ;
		strcpy(command, "");
		if (optind < argc)
		{
			while (optind < argc) {
				/* <hostname> <command> provided; only one command string */
				strcat(command, argv[optind++]);
				if (optind < argc) {
					strcat(command, " ");
				} 
				else {
					strcat(command, "\n");
				}
			}
		}
		else
		{
			/*Only <hostname> provided; input on <stdin> */
			strcpy(command, "");
			if (optind > argc)
			{
				usage(basename);
				exit(1);
			}
		}
	}
	else
	{
		/* no hostname! */
		usage(basename);
		exit(1);
	}	
/******************************************************
/* open a socket connection to the instrument
/******************************************************/
#ifdef WINSOCK
	if (init_winsock() != 0) {
		exit(1);
	}
#endif /* WINSOCK */		
	instSock = openSocket(destination, SCPI_PORT);
	if (instSock == INVALID_SOCKET) {
		fprintf(stderr, "Unable to open socket.\n");
		return 1;
	}
	/* fprintf(stderr, "Socket opened.\n"); */
	if (strlen(command) > 0)
	{
/*******************************************************
/* if the command has a '?' in it, use queryInstrument. */
/* otherwise, simply send the command. */
/*******************************************************/
		if ( isQuery(command) )
		{
			long bufBytes;
			bufBytes = queryInstrument(instSock, command,charBuf, INPUT_BUF_SIZE);
			if (!quiet)
			{
				fwrite(charBuf, bufBytes, 1, stdout);
				fwrite("\n", 1, 1, stdout) ;
				fflush(stdout);
			}
		}
		else
		{
			commandInstrument(instSock, command);
		}
	}
	else
	{
		/* read a line from <stdin> */
		while ( gets(charBuf) != NULL )
		{
			if ( !strlen(charBuf) )continue ;
			if ( *charBuf == '#' || *charBuf == '!' )continue ;
			strcat(charBuf, "\n");
			if (!quiet)
			{
				if (number)
				{
					char num[10];
					sprintf(num,"%d: ",number);
					fwrite(num, strlen(num), 1, stdout);
				}
				fwrite(charBuf, strlen(charBuf), 1, stdout) ;
				fflush(stdout);
			}
			if ( isQuery(charBuf) )
			{
				long bufBytes;
				/* Put the query response into the same buffer as the*/
				/* command string appended after the null terminator.*/
				bufBytes = queryInstrument(instSock, charBuf,charBuf + strlen(charBuf)+ 1,INPUT_BUF_SIZE-strlen(charBuf) );
				if (!quiet)
				{
					fwrite(" ", 2, 1, stdout) ;
					fwrite(charBuf + strlen(charBuf)+1, bufBytes, 1,stdout);
					fwrite("\n", 1, 1, stdout) ;
					fflush(stdout);
				}
			}
			else
			{
				commandInstrument(instSock, charBuf);
			}
			if (number) number++;
		}
	}
	if (show_errs) {
		showErrors(instSock);
	}
#ifdef WINSOCK
	closesocket(instSock);
	close_winsock();
#else
	close(instSock);
#endif /* WINSOCK */
	return 0;
}
/* End of lanio.cpp *
	

Programming the Status Register System

Overview

 在远程操作期间,您可能需要监控信号发生器的状态以了解错误情况或状态更改。您可以使用信号发生器的状态寄存器系统来监控错误条件或条件更改。通常,错误队列比状态寄存器更容易使用,但状态寄存器提供了一些错误队列中没有的附加信息。

 信号发生器的状态寄存器系统提供了两个主要优势:

您可以使用标准操作状态组条件寄存器的稳定位来监控信号发生器的稳定。
您可以使用服务请求(SRQ)中断技术来避免状态轮询,从而提供速度优势

 信号发生器的仪器状态系统提供完整的SCPI兼容数据结构,用于使用寄存器模型报告仪器状态。

 状态系统的SCPI寄存器模型具有按层次顺序排列的多个寄存器。低优先级状态寄存器使用汇总位将其数据传播到高优先级寄存器。状态字节寄存器位于层次结构的顶部,包含较低级别寄存器的状态信息。底层寄存器监视特定的事件或条件。

 较低级别的状态寄存器根据其功能进行分组。例如,数据可疑频率状态组由五个寄存器组成。本章将组称为寄存器,以避免冗长的描述。例如,标准操作状态组的条件寄存器可以称为标准操作状态寄存器。

 状态寄存器系统使用IEEE 488.2命令(以*开头的命令)访问高级摘要寄存器(请参阅SCPI命令)引用)。使用 STATus 命令访问低层寄存器。

Overall Status Byte Register Systems

E8257D/67D and E8663B/63D: Overall Status Byte Register System (1 of 2)
在这里插入图片描述
E8257D/67D and E8663B/63D: Overall Status Byte Register System (2 of 2)

在这里插入图片描述

Status Register Bit Values

 寄存器中的每一位都由基于其在寄存器中的位置的十进制值表示(参见表4-1)。

1.要启用寄存器中的特定位,请使用SCPI命令发送其值。
2.若要启用多个位,请发送要启用的所有位的和。
3.要验证寄存器中设置的位,请查询寄存器。

Example: Enable a Register

 启用标准事件状态组的事件寄存器的0位和6位:

1.将第0位(1)的十进制值和第6位(64)的十进制值相加,得到一个65的十进制值。
2.使用命令发送总和:*ESE 65。

Example: Query a Register

 要查询一个条件的寄存器,发送一个SCPI查询命令。例如,如果你想查询标准操作状态组的条件寄存器,发送命令:

STATus:OPERation:CONDition?

如果在这个寄存器中设置了第7位、第3位和第2位(bits = 1),那么查询将返回十进制值140。取值为位7、位3、位2的十进制值:128 + 8 + 4 = 140。

在这里插入图片描述

Accessing Status Register Information

1.确定哪个寄存器包含报告该条件的位。寄存器的位置和名称请见Overall Status Byte Register Systems。
2.发送读取该寄存器的唯一SCPI查询。
3.检查对应位以查看条件是否已更改。

Determining What to Monitor

 您可以监控以下情况:

1.当前信号发生器硬件和固件状态
2.是否发生了特定的情况(位)

1.监控当前信号发生器硬件和固件状态

 要监视信号发生器的运行状态,可以查询条件寄存器。这些寄存器表示信号发生器的当前状态,并实时更新。当某个特定位监视的条件为真时,该位设置为1。当条件变为false时,位重置为0。

2.监控某个条件(位)是否发生了变化

 转换寄存器决定应将哪个位转换(条件更改)记录为事件。转换可以是正的到负的,负的到正的,或者两者都有。要监视某个条件,在相关的正寄存器和负寄存器中启用与该条件相关的位。

 一旦您通过转换寄存器启用了一个位,信号发生器就会监视它的状态是否发生变化。如果条件发生了这种变化,事件寄存器中相应的位将被设置为1。当一个位在事件寄存器中变为true(设置为1)时,它将保持设置,直到事件寄存器被读取或清除。因此,即使某个条件不再存在,也可以在事件寄存器中查询该条件。

 要清除事件寄存器,请查询其内容或发送清除所有事件寄存器的*CLS命令。

3.监测条件(位)变化
 一旦你启用了一个位,信号发生器就会监测它的状态变化。转换寄存器被预设为正转换(从0到1的变化)。可以改变这一点,以便在所选位从真变为假(负转换)或发生任何一种转换时检测所选位。

Deciding How to Monitor

 您可以使用下面描述的两种方法中的任何一种来访问状态寄存器中的信息(这两种方法都允许您监视一个或多个条件)。

1.The polling method

  在轮询方法中,信号发生器具有被动作用。只有当控制器提出正确的问题时,它才会告诉控制器条件已经改变。这是通过一个不断发送查询的程序循环来完成的。

 如果您不需要在更改发生时就知道更改,那么轮询方法可以很好地工作。在以下情况下使用轮询:

1.当您使用编程语言/开发环境或IO接口,不支持SRQ中断。
2.当您想要编写一个简单的、单一用途的程序,并且不希望增加设置SRQ处理程序的复杂性时。

2.服务请求(SRQ)方法

  在SRQ方法中(在下一节中描述),信号发生器发挥更积极的作用。它会在没有控制器请求的情况下告诉控制器发生了条件变化。使用SRQ方法使用轮询方法检测更改, 其中程序必须重复读取寄存器。

  如果您必须立即知道条件何时发生变化,请使用SRQ方法。请在以下情况下使用SRQ方法:

1.当您需要及时通知更改时。
2.当您监控多个支持SRQ的设备时。
3.当您需要让控制器在等待时执行其他操作时。
4.当您无法承受轮询固有的性能损失时。

使用SRQ方法

  编程语言、I/O接口和编程环境必须支持SRQ中断。(例如:BASIC或VISA与GPIB和局域网下的VXI-11)。使用此方法,您必须执行以下操作:

1.确定监控哪个条件位。
2.发送命令以启用监视条件的位(转换寄存器)。
3.发送命令以启用报告条件的汇总位(事件启用寄存器)。
4.发送命令以启用状态字节寄存器来监视条件。
5.使控制器能够响应业务请求。

  当SRQ发生时,控制器会立即响应。因此,控制器原本用于监控条件的时间(如在循环方法中)可以用于执行其他任务。应用程序决定控制器如何响应SRQ。

  当一个条件改变并且该条件已启用时,将设置状态字节寄存器中的请求服务总结(RQS)位。 为了让控制器响应变化,需要为将触发SRQ的位启用服务请求启用寄存器。

生成服务请求

服务请求启用寄存器 允许您选择状态字节寄存器中将触发服务请求的位。发送*SRE 命令,其中是您想要启用的位的十进制值的和。

  例如,要在状态字节寄存器上启用第7位(以便每当标准操作状态寄存器上报位设置为1时, 生成服务请求)发送命令*SRE 128。

  查询命令SRE?返回之前使用SRE命令启用的位之和的十进制值。

  使用 *STB? 命令查询状态字节寄存器。响应将是设置为1的位的十进制和。例如,如果设置了第7位和第3位,小数和将是136(第7位= 128位,第3位= 8)。

PS:多个状态字节寄存器位可以断言一个SRQ,但是一次只能设置一个RQS位。在查询或串行轮询时,断言SRQ的所有位都将作为状态字节的一部分读取。

 SRQ进程将SRQ设置为true并将状态字节的RQS位设置为1。这两个动作都是通知控制器响应信号发生器服务。断言SRQ通知控制器总线上的某些设备需要服务。设置RQS位允许控制器确定哪个信号发生器需要服务。

如果以下两个条件都为真,则启动此过程:

服务请求启用寄存器的相应位也设置为1.
信号发生器没有待定的服务请求。

 从信号发生器的SRQ进程启动到控制器读取状态字节寄存器之间,服务请求被认为是待定的。

 如果一个程序允许控制器检测和响应服务请求,当SRQ为真时,它应该指示控制器执行串行轮询。总线上的每个设备都返回其状态字节寄存器的内容以响应此轮询。RQS (request service summary)位为1的设备即为请求服务的设备。

PS:当你用串行轮询读取信号发生器的状态字节寄存器时,RQS位被重置为0。寄存器中的其他位不受影响。

 如果状态寄存器在扫描结束或测量结束时配置为SRQ,并且模式设置为连续,则重新启动测量(INIT命令)可能会导致测量位脉冲低。当您没有实际达到“扫描结束”或测量条件时,这将导致SRQ。为了避免这种情况,请采取以下措施:

1.发送命令 INITiate:CONTinuous OFF.
2.设置/启用状态寄存器
3.重新启动测量(发送INIT)。

Status Register SCPI Commands

 大多数信号发生器条件的监测是在最高级别上使用下面列出的IEEE 488.2常用命令完成的。您可以使用 STATus 子系统 中的命令设置和查询各个状态寄存器。

*CLS (clear status)通过清空错误队列和清除所有事件寄存器来清除状态字节寄存器。
*ESE, *ESE? (event status enable)设置和查询标准事件启用寄存器中的位,该寄存器是标准事件状态组的一部分。
*ESR? (event status register)查询和清除标准事件状态寄存器,它是标准事件状态组的一部分。
*OPC, *OPC? (operation complete)当所有命令完成时,将标准事件状态寄存器中的位#0设置为1。查询停止处理任何新命令,直到当前处理完成,然后返回1。
*PSC, *PSC? (power-on state clear)设置开机状态,以便清除服务请求启用寄存器,标准事件状态启用寄存器和设备特定事件启用寄存器。查询从*PSC命令返回标志设置。
*SRE, *SRE? (service request enable)设置和查询服务请求启用寄存器的值。
*STB? (status byte)查询状态字节寄存器的值而不擦除其内容。
:STATus:PRESet预设所有转换过滤器、非IEEE 488.2启用寄存器和错误/事件队列启用寄存器。

Effects of :STATus:PRESet

在这里插入图片描述
在这里插入图片描述

Status Byte Group

 状态字节组包括状态字节寄存器和服务请求启用寄存器。

在这里插入图片描述

Status Byte Register
BitDescription
0,1Unused.这些位总是设为0
2Error/Event Queue Summary Bit. 1表示SCPI错误队列不是空的。SCPI错误队列包含至少一条错误消息。
3Data Questionable Status Summary Bit. 1表示设置了数据可疑汇总位。然后可以读取数据可疑事件寄存器,以确定导致该位被设置的特定条件。
4**Message Available.**此位位置的1表示信号发生器已在输出队列中准备好数据。没有为该位提供输入的较低状态组。
5Standard Event Status Summary Bit. 此位位置的1表示已设置标准事件上报位。然后可以读取标准事件状态寄存器以确定导致设置此位的特定事件。
6Request Service (RQS) Summary Bit. 1表示信号发生器至少有一个需要服务的原因。 该位也称为主摘要状态位(MSS)。状态字节中的各个位与它们对应的服务请求启用寄存器单独进行ANDed, 然后每个单独的位值都被ORed并输入到该位。
7Standard Operation Status Summary Bit. 该位位置的1表示标准操作状态组的汇总位已设置。 然后可以读取标准操作事件寄存器以确定导致设置此位的特定条件。

在这里插入图片描述

Service Request Enable Register

 服务请求启用寄存器允许您选择状态中的位字节寄存器触发一个服务请求。

*SRE 是除第6位外您要启用的位的十进制值的和。Bit 6 不能在这个寄存器上启用。
Example:若要使位7和位5在对应的状态组注册上报位设置为1时触发业务请求,请发送 SRE 160(128 + 32) 命令。
Query:*SRE?
Response:先前使用*SRE 命令启用的位的十进制值的和

Status Groups

 标准操作状态组和数据可疑状态组由下面列出的寄存器组成。标准事件状态组与之类似,但没有负转换过滤器或正转换过滤器或条件寄存器。

Register描述
Condition Register条件寄存器持续监测信号发生器的硬件和固件状态。条件寄存器没有锁存或缓冲;它是实时更新。
Negative Transition Filter负转换过滤器指定条件寄存器中的位,当条件位从1变为0时,这些位将在事件寄存器中设置相应的位。
Positive Transition Filter正转换过滤器指定条件寄存器中的位,当条件位从0变为1时,这些位将在事件寄存器中设置相应的位。
Event Register事件寄存器按照正转换过滤器和负转换过滤器指定的方式锁住来自条件寄存器的转换事件。一旦事件寄存器中的位被设置,它们将保持设置状态,直到通过查询寄存器内容或发送 *CLS 命令清除。
Event Enable Register使能寄存器指定事件寄存器中生成汇总位的位。信号发生器在逻辑上AND事件中的相应位,并启用寄存器和OR所有结果位以产生汇总位。 状态字节寄存器反过来使用汇总位。

 状态组是一组相关的寄存器,其内容经过编程以产生状态摘要位。在每个状态组中,条件寄存器中的相应位被负转换滤波器和正转换滤波器过滤并存储在事件寄存器中。事件寄存器的内容在逻辑上与启用寄存器的内容进行ANDed,结果在逻辑上进行ORed以在状态字节寄存器中生成状态摘要位。

Standard Event Status Group(标准事件状态组)

 标准事件状态组用于确定在状态字节寄存器中设置第5位的特定事件。该组由标准事件状态寄存器(事件寄存器)和标准事件状态启用寄存器组成。
在这里插入图片描述

BitDescription
0Operation Complete. 1表示在执行*OPC命令之后完成了所有待处理的信号发生器操作。
1Request Control. 这个位总是设置为0。(信号发生器不会请求控制。)
2Query Error. 该位位置的1表示发生了查询错误。 查询错误的仪器错误编号从−499到−400。
3Device Dependent Error. 该位的1表示发生了设备相关的错误。设备相关的错误有仪器错误号从−399到−300和1到32767。
4Execution Error. 该位的1表示发生了执行错误。执行错误的仪表错误编号为−299 ~−200。
5Command Error. 该位的1表示命令出错。命令错误的仪表错误编号为−199 ~−100。
6User Request Key (Local). 1表示按过Local键。即使信号发生器处于本地锁定模式,这也是正确的。
7Power On. 该位位置的1表示信号发生器已关闭,然后打开。

在这里插入图片描述

Standard Event Status Enable Register(标准事件状态使能寄存器)

标准事件状态使能寄存器允许您选择标准事件状态寄存器中的哪些位上报,将对应上报位(状态字节寄存器的第5位)设置为1。

在这里插入图片描述

Standard Operation Status Group(标准操作状态组)

 此状态组中的一些位不适用于E4428C, E8257D,E8267D、E8663B、E8663D、E8663D、N5161A/62A/81A/82A/83A、并在查询时返回0。

Keysight MXG SCPI命令:STAT:OPER:SUPP, 可以抑制此状态组的管理,并从切换时间中节省50 us。

 操作状态组用于确定设置位的特定事件、状态字节寄存器中的7。该组由标准操作条件寄存器标准操作转换过滤器(负和正)标准操作事件寄存器标准操作事件使能寄存器组成。

在这里插入图片描述

Standard Operation Condition Register(标准操作条件寄存器)

标准操作条件寄存器持续监控信号发生器的硬件和固件状态。条件寄存器是只读的。

在这里插入图片描述
在这里插入图片描述

Standard Operation Transition Filters (negative and positive)(标准操作传输滤波)

 标准操作转换筛选器指定条件寄存器中哪些类型的位状态变化将在事件寄存器中设置相应的位。变化可以是正的(0到1)或负的(1到0)。
在这里插入图片描述

Standard Operation Event Register(标准操作事件寄存器)

 标准操作事件寄存器按照转换过滤器指定的方式锁住来自条件寄存器的转换事件。事件寄存器是破坏性只读的。从事件寄存器读取数据将清除该寄存器的内容。
在这里插入图片描述

Standard Operation Event Enable Register(标准操作事件使能寄存器)

标准操作事件启用寄存器允许您选择标准操作事件寄存器中的哪些位设置上报位(状态字节寄存器的第7位)。

在这里插入图片描述

Baseband Operation Status Group(基带操作状态组)

 该状态组不适用于E4428C、E8257D、E8663B和E8663B、E8663D,如果查询,则返回0。
 该状态组不适用于N5161A/62A/81A/82A/83A。(如果查询,信号发生器将不响应。)

基带操作状态组用于确定在标准操作状态组中设置位10的特定事件。该组由基带操作条件寄存器基带操作转换过滤器(负和正)基带操作事件寄存器基带操作事件使能寄存器组成。

在这里插入图片描述

Baseband Operation Condition Register(基带操作条件寄存器)

 基带操作条件寄存器持续监测信号发生器的硬件和固件状态。条件寄存器是只读的。

在这里插入图片描述

Baseband Operation Transition Filters (negative and positive)(基带操作转换过滤器)

基带操作转换过滤器指定条件寄存器中哪些类型的位状态变化将在事件寄存器中设置相应的位。变化可以是正的(0到1)或负的(1到0)。
在这里插入图片描述

Baseband Operation Event Register(基带操作事件寄存器)

基带操作事件寄存器按照转换过滤器指定的方式锁住来自条件寄存器的转换事件。基带操作事件寄存器是破坏性只读的。从事件寄存器读取数据将清除该寄存器的内容。

在这里插入图片描述

Baseband Operation Event Enable Register(基带操作事件使能寄存器)

基带操作事件使能寄存器允许您选择基带操作事件寄存器中的哪些位可以设置上报位(状态字节寄存器的第7位)。
在这里插入图片描述

Data Questionable Status Group(数据可疑状态组)

 数据可疑状态组用于确定特定的事件。
 此状态组中的一些位不适用于E4428C, E8257D,E8267D、E8663B、E8663D、N5161A/62A/81A/82A/83A,查询时返回0。其他位改变了状态内容。

Data Questionable Power Status Group(数据可疑电源状态组)

Data Questionable Frequency Status Group(数据可疑频率状态组)

Data Questionable Modulation Status Group(数据可疑调制状态组)

Data Questionable Calibration Status Group(数据可疑校准状态组)

Data Questionable BERT Status Group(数据可疑BERT状态组)

Creating and Downloading User–Data Files

 创建和下载用户数据的要求和流程。

Overview

 用户数据是由用户创建并存储在信号发生器中的各种数据类型的通用术语。这包括以下数据(文件)类型:

Bit此文件类型允许用户下载有效负载数据,以用于流或帧信号。它让用户确定信号发生器在文件中使用了多少位。
Binary此文件类型提供用于流或帧信号的有效负载数据。它与位文件类型的不同之处在于您不能指定一组位的数量。相反,信号发生器将文件中的所有位用于流数据,并将填充帧的所有位用于帧数据。如果没有足够的比特来填充一个帧,信号发生器将截断数据并从头开始重复文件。
PRAM使用此文件类型,用户提供有效载荷数据以及位以控制信号属性,例如突发。此文件类型仅适用于实时自定义和TDMA调制格式
FIR Filter此文件类型存储用户创建的自定义过滤器。
State这种文件类型允许用户存储信号发生器设置,这些设置可以被收回。这为在不同信号设置之间切换时重新配置信号发生器提供了一种快速方法。
User Flatness Correction此文件类型允许用户存储频率的振幅校正。

在创建和下载文件之前,您需要考虑文件大小和剩余信号发生器内存的数量

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
LabVIEW状态机是一种常用的编程工具,用于管理软件系统中的控制流程。它采用有限状态自动机的概念,将整个系统划分为不同的状态,通过状态之间的转换来描述系统的行为。 在LabVIEW中,状态机通过使用状态图、状态迁移和状态事件来实现。状态图是状态机的核心,用于表示系统中所有可能的状态以及状态之间的转换。每个状态代表系统中某个特定的行为和状态;状态之间的转换表示系统从一个状态切换到另一个状态的条件。 在状态机中,状态迁移是状态之间的转换规则。它定义了系统如何从一个状态切换到另一个状态,以及切换的触发条件。例如,当系统满足某个特定条件时,状态机将从一个状态切换到另一个状态。 状态事件是触发状态迁移的事件,它可以是用户的输入、传感器的信号等。当状态机接收到某个特定的事件时,它会根据当前的状态和状态迁移规则来判断是否需要进行状态切换。 LabVIEW状态机的优点是能够清晰地描述系统的行为,使得程序的结构更加模块化和可维护。通过将系统划分为不同的状态和状态之间的转换,可以降低系统的复杂度,并且能够更好地应对系统的变化和扩展。 总之,LabVIEW状态机是一种有效的编程工具,可以帮助开发者更好地管理系统的控制流程,实现复杂系统的控制和管理。它的使用可以提高程序的可读性、可维护性和可扩展性,是LabVIEW编程中常用的技术。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mapoplus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值