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

可编程仪器标准命令(英语:Standard Commands for Programmable Instruments,缩写:SCPI)定义了一套用于控制可编程测试测量仪器的标准语法和命令。《百度百科》

本文主要还是依赖仪器厂商提供的数据

首先是仪器型号,M8811数控电源,相关手册:百度文库

winform串口通过SCPI协议与数控电源M8811通信_第1张图片

winform串口通过SCPI协议与数控电源M8811通信_第2张图片

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

winform串口通过SCPI协议与数控电源M8811通信_第3张图片

winform串口通过SCPI协议与数控电源M8811通信_第4张图片

后面的DB9是TTL电平,直接上USB转TTL即可,不能上标准的RS232,因为电平问题

可能是我的串口线有问题,实际接线的时候1~5是反过来的,我也是量GND与VCC电压发现的

winform串口通过SCPI协议与数控电源M8811通信_第5张图片

看手册,别的可以忽略,直接看《第六章 SCPI通信协议》

我们需要一个串口调试工具,网上下的都不好用,于是自己做一个

winform串口通过SCPI协议与数控电源M8811通信_第6张图片

比较简单,代码如下

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();
        }
    }
}
用工具测试一下手册上提供的命令,调试正常,于是再建一个工程

winform串口通过SCPI协议与数控电源M8811通信_第7张图片

可以显示电压电流和设置电压电流,为了方便还是写一个类吧

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



你可能感兴趣的:(winform串口通过SCPI协议与数控电源M8811通信)