zoukankan      html  css  js  c++  java
  • C#上位机之—WinForm实现串口通信示例

    上位机开发常用到串口通信来控制设备,串口通信的主要参数:COM口,波特率(9600),停止位(One),数据位(8),校验位(None),括号中的是常用值,具体意思我也不太懂,会用能实现功能就行哈哈;

    开发工具:VS2012;   开发前需要添加以下服务引用:

    .......
    using System.IO.Ports;

    窗体搭建,因为没有串口设备供调试 ,所以我用虚拟串口即两个串口互相连接来实现通信,窗体分为上下两部分,对应两个串口区,上图为虚拟串口设置,下图为Winform样式:

     添加COM1和COM11端口                   上下对应两个COM区

    首先创建一个baseCom类:

    1.声明变量,构造函数:

            public delegate void delegateOnShowMsg(comType type,string msg);
            public delegate void delegateOnOpenCom(comType type, bool onOff);
            public event delegateOnShowMsg OnShow;
            public event delegateOnOpenCom OnOpen;
            comType type;
            string baudRate = string.Empty;
            string parity = string.Empty;
            string stopBits = string.Empty;
            string dataBits = string.Empty;
            string portName = string.Empty;
            public System.IO.Ports.SerialPort comPort = new System.IO.Ports.SerialPort();
            public baseCom(string portName, string baudRate, string stopBits, string dataBits, string parity,comType type)
            {
                this.portName = portName;
                this.baudRate = baudRate;
                this.stopBits = stopBits;
                this.dataBits = dataBits;
                this.parity = parity;
                this.type = type;
            }
    View Code

    2.打开串口和关闭串口函数:

            public void OpenPort()
            {
                try
                {
                    if (comPort.IsOpen)
                        comPort.Close();
                    comPort.BaudRate = int.Parse(baudRate);
                    comPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), stopBits);
                    comPort.DataBits = int.Parse(dataBits);
                    comPort.Parity = (Parity)Enum.Parse(typeof(Parity), parity);
                    comPort.PortName = portName;
                    comPort.Handshake = Handshake.None;
                    comPort.Open();
                    if (comPort.IsOpen)
                    {
                        showOnoff(true);
                        comPort.Handshake = Handshake.None;
                        comPort.DataReceived += comPort_DataReceived;
                    }
                    showMsg(portName + " Open Success");
                }
                catch (Exception ex)
                {
                    showMsg("Unable to Open " + portName);
                    showMsg(ex.Message);
                    showOnoff(false);
                }
            }
            public void ClosePort()
            {
                if (comPort.IsOpen)
                {
                    comPort.Close();
                    comPort.Dispose();
                    showOnoff(false);
                    showMsg(portName + " Close Success");
                }
            }
    View Code

    3.接受数据和发送数据函数:

            public void comPort_DataReceived(object sender,SerialDataReceivedEventArgs e)
            {
                try
                {
                    int n = comPort.BytesToRead;
                    if (n == 0)
                        return;
                    byte[] buffer = new byte[n];
                    comPort.Read(buffer, 0, n);
                    string rcv = Encoding.Default.GetString(buffer, 0, buffer.Length);
                    showMsg("RECV:" + rcv);
                }
                catch (Exception ex)
                {
                    ClosePort();
                    showMsg("Com Closed:" + ex.Message);
                }
            }
            public void comPort_SendData(string msg)
            {
                if (msg == "")
                {
                    showMsg("CAN Not EMPTY");
                    return;
                }
                if (comPort == null)
                {
                    showMsg("First Open Port");
                    return;
                }
                if (!comPort.IsOpen)
                {
                    showMsg("COM Not Open");
                    return;
                }
                byte[] data = Encoding.Default.GetBytes(msg);
                comPort.Write(data, 0, data.Length);
                showMsg("SEND:" + msg);
            }
    View Code

    4.显示信息,显示状态函数:

            public void showMsg(string msg)
            {
                if (OnShow != null)
                    OnShow(type, msg);
            }
            public void showOnoff(bool flag)
            {
                if (OnOpen != null)
                    OnOpen(type, flag);
            }
            public enum comType
            {
                _up,
                _down
            }
    View Code

    OK,baseCOM类已定义完成,现在编写窗体各控件的功能函数:

    1.初始化控件,主要是下拉菜单的Item的添加,初始值,初始状态:

            public string[] baudRates = { "2400", "4800", "9600", "19200", "39400", "43000", "56000" };
            public string[] paritys = { "None", "ODD", "Even" };
            public string[] dataBits = { "5", "6", "7", "8" };
            public string[] stopBits = { "None", "One", "Two", "OnePointFive" } ;
            public void InitControls()
            {
                comboBox_com.Items.Clear();
                comboBox_baudRate.Items.Clear();
                comboBox_dataBits.Items.Clear();
                comboBox_parity.Items.Clear();
                comboBox_StopBit.Items.Clear();
                comboBox_com2.Items.Clear();
                foreach (var v in baudRates)
                    comboBox_baudRate.Items.Add(v);
                foreach (var v in stopBits)
                    comboBox_StopBit.Items.Add(v);
                foreach (var v in paritys)
                    comboBox_parity.Items.Add(v);
                foreach (var v in dataBits)
                    comboBox_dataBits.Items.Add(v);
                foreach (var v in System.IO.Ports.SerialPort.GetPortNames())
                {
                    comboBox_com.Items.Add(v);
                    comboBox_com2.Items.Add(v);
                }
                comboBox_com.SelectedIndex = 0;
                comboBox_baudRate.SelectedIndex = 2;
                comboBox_dataBits.SelectedIndex = 3;
                comboBox_parity.SelectedIndex = 0;
                comboBox_StopBit.SelectedIndex = 1;
                comboBox_com2.SelectedIndex = 0;
            }
    View Code

    2.声明两个COM类,comUp和comDown:

    public delegate void delegateOnOff(comType type,bool onoff);//定义两个委托
    public delegate void delegateShow(comType type,string msg);//为了防止报错“从不是创建控件的线程控制它”
    baseCom comUp;    // 定义上串口COM
    baseCom comDown;   //定义下串口COM
    Image imgOn, imgOff; //指示灯
    Thread th;        //线程用来实现自动发送

    3.编写打开(关闭)串口按钮点击事件(打开comUp和打开comDown代码一样,只贴出comUp):

            private void button_OpenCom_Click(object sender, EventArgs e)
            {
                string cmd = ((Button)sender).Text.Split(' ')[0];
                if (comUp != null)
                    comUp.ClosePort();
                if (cmd == "Close")
                    return;
                string s1 = comboBox_com.SelectedItem.ToString();
                string s2 = comboBox_baudRate.SelectedItem.ToString();
                string s3 = comboBox_StopBit.SelectedItem.ToString();
                string s4 = comboBox_dataBits.SelectedItem.ToString();
                string s5 = comboBox_parity.SelectedItem.ToString();
                comUp = new baseCom(s1, s2, s3, s4, s5,comType._up);
                comUp.OnOpen += SignalState;
                comUp.OnShow += ShowMsg;
                comUp.OpenPort();
            }
    View Code

    4.编写发送数据按钮点击事件:

    private void button_Send_Click(object sender, EventArgs e)
    {
         if (comUp != null)
           comUp.comPort_SendData(textBox_ComSend.Text);
    }

    5.编写数据接受发送显示到文本框及状态指示灯变化函数:

            public void SignalState(comType type,bool onoff)
            {
                if (this.InvokeRequired)
                {
                    delegateOnOff d = new delegateOnOff(SignalState);
                    this.Invoke(d,new object[]{type,onoff});
                }
                else
                {
                    if (type == comType._up)
                    {
                        pictureBox_ComSignal.Image = onoff ? imgOn : imgOff;
                        button_OpenCom.Text = onoff ? "Close COM" : "Open COM";
                    }
                    else
                    {
                        pictureBox_Com2.Image = onoff ? imgOn : imgOff;
                        button_OpenCom2.Text = onoff ? "Close COM" : "Open COM";
                    }
                }
            }
            public void ShowMsg(comType type, string msg)
            {
                if (this.InvokeRequired)
                {
                    delegateShow d = new delegateShow(ShowMsg);
                    this.Invoke(d, new object[] { type, msg });
                }
                else
                {
                    string date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "
    ";
                    if (type == comType._up)
                    {
                        textBox_serialPort.Text += (date + msg + "
    ");
                    }
                    else
                    {
                        textBox_serialPort2.Text += (date + msg + "
    ");
                    }
                }
            }
    View Code

    6.Monitor函数,即线程函数,用来实现数据自动发送(没有进行准确定时,大概设了个间隔):

            public void Monitor()
            {
                double i =0;
                while (i++<10000000000)
                {
                    if (i == 1000000000)
                    {
                        i = 0;
                        if (checkBox_AutoSend.Checked)
                        {
                            if (comUp != null)
                                comUp.comPort_SendData(textBox_ComSend.Text);
                        }
                        if (checkBox_AutoSend2.Checked)
                        {
                            if (comDown != null)
                                comDown.comPort_SendData(textBox_comSend2.Text);
                        }
                    }
                }
            }
    View Code

    至此,串口通信功能已基本实现,可在此框架上进行实际应用开发,编码新手,欢迎大家批评指正!看下效果图(COM1和COM11虚拟连接):

  • 相关阅读:
    【ArcGIS 10.2新特性】ArcGIS 10.2将PostgreSQL原生数据发布为要素服务
    字节流,字符流 有什么区别
    java--模板方法模式
    hdu2829 四边形优化dp
    【ArcGIS 10.2新特性】ArcGIS 10.2 for Desktop 新特性(二)
    B/S架构 Web打印程序(Argox)
    poj 1611 The Suspects(并查集)
    microsoft visual studio遇到了问题,需要关闭
    [置顶] Windows显示驱动(WDDM)编程初步(2)
    Linux查看设置系统时区
  • 原文地址:https://www.cnblogs.com/cfsl/p/12327095.html
Copyright © 2011-2022 走看看