winform串口通过SCPI协议与数控电源M8811通信

2019-07-13 21:51发布

可编程仪器标准命令(英语:Standard Commands for Programmable Instruments,缩写:SCPI)定义了一套用于控制可编程测试测量仪器的标准语法和命令。《百度百科》 本文主要还是依赖仪器厂商提供的数据 首先是仪器型号,M8811数控电源,相关手册:百度文库

首先连接通信线,鉴于原厂的数据线很贵,于是只能自己解决,根据手册可以发现

后面的DB9是TTL电平,直接上USB转TTL即可,不能上标准的RS232,因为电平问题 可能是我的串口线有问题,实际接线的时候1~5是反过来的,我也是量GND与VCC电压发现的
看手册,别的可以忽略,直接看《第六章 SCPI通信协议》 我们需要一个串口调试工具,网上下的都不好用,于是自己做一个
比较简单,代码如下 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO.Ports; namespace DigitalPower { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { getAllPortName(); } private void getAllPortName() { string[] spNames = SerialPort.GetPortNames(); cbPort.Items.Clear(); foreach (var v in spNames) cbPort.Items.Add(v); if (cbPort.Items.Count > 0) cbPort.SelectedIndex = 0; } private void btRefresh_Click(object sender, EventArgs e) { getAllPortName(); } private void btOpen_Click(object sender, EventArgs e) { if (btOpen.Text == "打开") { try { serialPort1.PortName = cbPort.SelectedItem.ToString(); serialPort1.Open(); btOpen.Text = "关闭"; btSend.Enabled = true; } catch { MessageBox.Show("无法打开端口!"); } } else { try { serialPort1.Close(); btOpen.Text = "打开"; btSend.Enabled = false; } catch { MessageBox.Show("无法关闭端口!"); } } } private void btSend_Click(object sender, EventArgs e) { serialPort1.WriteLine(tbSend.Text); } private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { string str = serialPort1.ReadExisting(); this.Invoke(new MethodInvoker(delegate { lbDisaplay.Items.Add(str); lbDisaplay.SelectedIndex = lbDisaplay.Items.Count - 1; })); } private void btClear_Click(object sender, EventArgs e) { lbDisaplay.Items.Clear(); } } } 用工具测试一下手册上提供的命令,调试正常,于是再建一个工程
可以显示电压电流和设置电压电流,为了方便还是写一个类吧 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO.Ports; using System.Threading; namespace DPtest { class DPM88 { SerialPort sp = new SerialPort(); public DPM88() { sp.DataBits = 8; sp.Parity = Parity.None; sp.StopBits = StopBits.One; sp.ReadBufferSize = 4096; sp.ReadTimeout = 50; sp.ReceivedBytesThreshold = 1; } int waitTime = 50; public bool OpenDevice(int baudrate) { bool ret = false; if (sp.IsOpen) sp.Close(); string[] spNames = SerialPort.GetPortNames(); foreach (var v in spNames) { try { sp.PortName = v; sp.BaudRate = baudrate; sp.Open(); sp.WriteLine("*IDN?"); long tgTime = DateTime.Now.Ticks + 10000 * waitTime; while (sp.BytesToRead <= 0 && tgTime > DateTime.Now.Ticks) Thread.Sleep(1); if (sp.BytesToRead > 0) { sp.DiscardInBuffer(); ret = true; sp.WriteLine("SYST:REM"); break; } } catch { } } return ret; } public void SetVoltage(double voltage) { string str = voltage.ToString("0.0000"); sp.WriteLine("VOLT " + str); } public void SetCurrent(double current) { string str = current.ToString("0.0000"); sp.WriteLine("CURR " + str); } public double GetSetVoltage() { double vol = 0; vol = GetDoubleCmd("VOLT?"); return vol; } public double GetSetCurrent() { double cur = 0; cur = GetDoubleCmd("CURR?"); return cur; } public double GetOutVoltage() { double vol = 0; vol = GetDoubleCmd("MEAS:VOLT?"); return vol; } public double GetOutCurrent() { double cur = 0; cur = GetDoubleCmd("MEAS:CURR?"); return cur; } private double GetDoubleCmd(string cmd) { double ret = 0; sp.WriteLine(cmd); long tgTime = DateTime.Now.Ticks + 10000 * waitTime; while (sp.BytesToRead <= 0 && tgTime > DateTime.Now.Ticks) Thread.Sleep(1); if (sp.BytesToRead > 0) { try { string str = sp.ReadLine(); ret = Convert.ToDouble(str); } catch { } } return ret; } public void SetOutput(bool open) { if (open) sp.WriteLine("OUTPU 1"); else sp.WriteLine("OUTPU 0"); } public bool GetOutput() { sp.WriteLine("OUTP?"); bool ret = false; long tgTime = DateTime.Now.Ticks + 10000 * waitTime; while (sp.BytesToRead <= 0 && tgTime > DateTime.Now.Ticks) Thread.Sleep(1); if (sp.BytesToRead > 0) { try { string str = sp.ReadLine(); if (str == "1") ret = true; else ret = false; } catch { } } return ret; } public void ClosePort() { try { sp.Close(); } catch { } } } }
于是界面如下 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace DPtest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } DPM88 dpm = new DPM88(); private void btOpenPort_Click(object sender, EventArgs e) { if (btOpenPort.Text == "打开端口") { if (dpm.OpenDevice(38400) == true) { btOpenPort.Text = "关闭端口"; portOpenFlag = true; timer1.Start(); } else { MessageBox.Show("无法打开设备!"); } } else { portOpenFlag = false; timer1.Stop(); dpm.ClosePort(); btOpenPort.Text = "打开端口"; } } bool portOpenFlag = false; private void timer1_Tick(object sender, EventArgs e) { if (portOpenFlag) { lbVoltage.Text = dpm.GetOutVoltage().ToString("0.0000") + "V"; lbCurrent.Text = dpm.GetOutCurrent().ToString("0.0000") + "A"; if (dpm.GetOutput()) pictureBox1.BackColor = Color.Red; else pictureBox1.BackColor = this.BackColor; } } private void btSetVoltage_Click(object sender, EventArgs e) { try { double d = Convert.ToDouble(tbSetVoltage.Text); dpm.SetVoltage(d); } catch { } } private void btSetCurrent_Click(object sender, EventArgs e) { try { double d = Convert.ToDouble(tbSetCurrent.Text); dpm.SetCurrent(d); } catch { } } private void btOnOff_Click(object sender, EventArgs e) { if (btOnOff.Text == "打开输出") { dpm.SetOutput(true); btOnOff.Text = "关闭输出"; } else { dpm.SetOutput(false); btOnOff.Text = "打开输出"; } } } }
总结:其实SCPI协议不难,只要看好手册即可 两个工程代码,写的不好,欢迎指正 http://download.csdn.net/download/lv_fu/9660570