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") + "\r\n";
                if (type == comType._up)
                {
                    textBox_serialPort.Text += (date + msg + "\r\n");
                }
                else
                {
                    textBox_serialPort2.Text += (date + msg + "\r\n");
                }
            }
        }
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虛擬連接):


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM