1、概述html
本文描述采用C#语言访问控制Tektronix TBS 2000B 系列示波器。接口协议采用NI-VISA。git
最近一个项目须要和一款示波器进行通讯,须要对示波器进行一些简单控制并获取到波形数据。通过一段时间研究,大体了解了相关操做,由于发现相关资料不是不少,因此把我了解的相关知识和你们分享一下。文末将提供本文涉及的相关文档、代码、安装程序的下载地址。编程
正常状况下,咱们若是须要和一个设备进行通讯,首先须要知道PC经过什么方式和设备进行链接,通讯协议是什么。因为工做须要和不少设备进行过链接,经常使用的链接方式主要有:网络链接、串口链接、USB接口链接等;通讯协议都是自定义的协议文本。 原本觉得这个项目首先得须要搞清楚示波器的通讯协议,而后才能进行下一步开发,在官方网站下载了一些编程资料,发现该设备是能够经过VISA进行链接的,那什么是VISA呢?VISA是由National Instruments公司牵头,联合一些设备制造厂商共同指定的一个通用设备链接标准,无论设备经过何种方式进行链接,只要符合VISA规范就能够经过该标准协议进行链接,而NI-VISA就是NI公司实现的一个协议,经过这个协议接口,咱们不用直接和设备进行通讯,只须要经过NI-VISA提供的接口就能够访问设备,而经常使用的接口很是简单,主要就是OPEN、WRITE、READ等几个命令。符合规范的设备都会公开一份SCPI指令集的文档,只要仔细阅读该文档就能够实现设备的控制。在整个项目过程当中,我仅仅经过几个官方网站下载的文档就完成项目开发,几乎没有什么障碍,在此不得不感慨咱们的制造业和发达国家相比确实有很大差距,咱们就缺乏这样标准性的东西,什么事情都得从底层作起,很不科学。要是那些巨头们肯作一些这方面的工做就太好了,比作什么买菜、卖鱼的APP有意义得多了。浏览器
示波器经过网络接口和PC进行链接网络
配置示波器IP和PC在同一个网段,例如:192.168.11.11,在设置时注意IP内不要有0,而后在PC上先ping一下,看可否ping通。ide
若是能ping通就在浏览器输入http://192.168.11.11看可否打开示波器主页,确认SCPI指令能够运行。网站
运行NI-VISA Runtime安装程序,选中运行时基础包和.NET支持包。 ui
.NET支持包选.NET 4.0-4.5.1 Runtime Support(IVI),不选.NET XX Runtime Support(NS),NS的包是老版本。this
安装完成后造成两个包:Ivi.Visa和NationalInstruments.Visaspa
其中Ivi.Visa有两个版本:
32位位置:C:\Program Files (x86)\IVI Foundation\VISA\Microsoft.NET\Framework32\v2.0.50727\VISA.NET Shared Components 5.8.0
64位位置:C:\Program Files\IVI Foundation\VISA\Microsoft.NET\Framework64\v2.0.50727\VISA.NET Shared Components 5.8.0
NationalInstruments.Visa位置:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\NationalInstruments.Visa\v4.0_17.0.0.0__2eaa5af0834e221d
新建VS工程,按上述地址添加Ivi.Visa和NationalInstruments.Visa两个引用。Ivi.Visa的库根据须要能够选32位或64位。
程序运行须要在目标机器安装运行时,因此引用的库不须要复制到项目文件夹。
已经有网友把VISA接口得调用进行了封装,我直接使用了相关代码,几乎一字未改,相关代码请查阅:https://www.cnblogs.com/cncc/p/7866899.html
链接代码:
string IP = this.txtIP.Text.Trim(); string IpRegex = @"^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$"; if (!Regex.IsMatch(IP, IpRegex)) { MessageBox.Show("IP地址不正确!"); return; } if (!PortUltility.OpenIPAddress(IP, out string fullAddress)) { MessageBox.Show("未找到设备!"); return; } try { _portOperatorBase = new LANPortOperator(fullAddress); } catch (Exception ex) { MessageBox.Show($"初始化设备失败:{ex.Message}"); return; } try { _portOperatorBase.Timeout = 2000; _portOperatorBase.Open(); } catch (Exception ex) { MessageBox.Show($"链接设备失败:{ex.Message}"); return; } EnabledControls(true); MessageBox.Show("链接成功!");
写指令一共有两种,一种不须要返回数据、一种须要返回数据,下发了须要返回数据的指令后才能进行读取指令,不然就会读取失败。
读写指令以下:
private void btnWrite_Click(object sender, EventArgs e) { string CmdStr = this.txtCommand.Text.Trim(); try { _portOperatorBase.WriteLine(CmdStr); ShowLog($"[Write][{CmdStr}][Success]"); } catch { ShowLog($"[Write][{CmdStr}][ERROR]"); } } private void btnReadString_Click(object sender, EventArgs e) { try { var result = _portOperatorBase.Read(); ShowLog($"[Read][{result}][{result.Length}]"); } catch (IOTimeoutException) { ShowLog($"[Read][ERROR:Timeout]"); } catch (Exception ex) { ShowLog($"[Read][Exception:{ex.Message}]"); } }
核心代码就这么多,剩下的就根据须要查询SCPI指令表就能够了。
如下指令仅适用于Tektronix TBS 2000B系列示波器。
(一) 基本指令 1. 身份 WRITE:*IDN? READ: (二) 设置 1. 默认设置 RECAll:SETUp FACtory 2. 通道控制 Select:CH<x> ON/OFF 3. 水平位置与比例 HORizontal:POSition? HORizontal:POSition 10 HORizontal:SCAle? 400 单位是秒 HORizontal:SCAle 0.2 4. 垂直位置与比例 CH1:POSition? CH1:POSition 1 CH1:SCAle? CH1:SCAle 2.5 5. 触发 模式 TRIGger:A:MODe? NORMAL 触发类型 TRIGger:A:TYPe? EDGE 触发源 TRIGger:A:EDGE:SOUrce CH1 耦合: TRIGger:A:EDGE:COUPling g {DC|HFRej|LFRej|NOISErej} 斜率 TRIGger:A:EDGE:SLOpe {RISe|FALL} 触发电平(当前) TRIGger:A:LEVel? 2.0800 TRIGger:A:LEVel 3.5 触发电平(指定通道) TRIGger:A:LEVel:CH1? 2.0800 TRIGger:A:LEVel :CH1 3.5 (三) 控制 1. 设置/查询工做类型 ACQuire:STOPAfter SEQuence ACQuire:STOPAfter RUNSTOP 查询:ACQuire:STOPAfter? 返回最后一次设置的工做类型 2. 设置/查询运行状态 ACQuire:STATE? 0:Run或Single 1:Stop 设置:ACQuire:STATE ON/OFF 3. 查询触发状态 TRIGger:STATE? READY:等待触发 SAVE:已经触发 (四) 读取数据 1. 设置数据来源(通道) DATA:SOURCE CH1 2. 设置/读取记录宽度 HORizontal:RECOrdlength? 2000 3. 读取波形数据宽度(仅读取,触发完成后有效) WFMOutpre:RECOrdlength? 2000 4. 设置传输数据窗口 DATa:STARt 1 最小为1 DATa:STOP 2000 DATa:WIDth? 单个数据宽度(字节数)默认为1,能够修改成2字节,但高位始终为0 5. 数据读取 CURVe? Read(Bytes):返回指定长度的字节数据【LENGTH= N+(STOP-STARt+1)+1】 数据为:帧头(N字节)+数据(STOP-STARt+1字节)+帧尾(1字节)。 帧头为:#(1字节)+数据长度的长度(1字节)+数据长度(1~9字节) 帧尾为:\n 数据每一个字节表示一个波形高度值,采用补码方式,即第一个位表示符号,范围从-128~127
相关文档、代码下载:https://gitee.com/seabluescn/tksamples.git