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

可编程仪器标准命令(英语: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



  • 16
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
WinForm串口通信是通过在WinForm应用程序中建立串口通讯来实现。首先,需要检查电脑上是否有可用的串口。然后,根据需要修改串口的相关信息,如波特率、数据位、校验位和停止位等。在WinForm窗体中,可以显示串口接收到的实时数据。 例如,可以给打开串口按钮绑定打开串口事件。在事件处理程序中,需要进行串口配置,包括PortName(串口名称)、BaudRate(波特率)、DataBits(数据位)、Parity(校验位)和StopBits(停止位)等五个参数。其中,波特率是以字符串形式呈现的,需要使用Convert.ToInt32()方法将其转换为整数类型。 WinForm串口通信的具体步骤可以分为以下几个方法或步骤: 1. 创建虚拟串口 2. 创建WinForm应用程序 3. 绘制WinForm窗体 4. 进行属性初始化 5. 加载界面事件与初始化控件 6. 设置波特率选择事件 7. 检测可用串口 8. 进行串口设置 9. 打开或关闭串口 10. 发送和接收数据 11. 编写完整的代码 12. 进行测试并查看结果 13. 可以下载Demo来进行参考和学习。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Winform串口通讯](https://download.csdn.net/download/me683547/87793361)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [1小时搞定C# winForm串口通信](https://blog.csdn.net/niuyong_10086/article/details/108882823)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [C# WinForm下利用虚拟串口工具进行串口通信](https://blog.csdn.net/lwkliuwenkang/article/details/130357331)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值