天天看點

C#winform小demo-序列槽傳輸實作硬體資料回傳(SerialPort類使用)

這節介紹實作的是利用SerialPort類進行序列槽的連結。

.Net Framework 作為微軟開發的一個架構,萬變不離其宗,要怎麼使用一個東西,就最好看它的說明書 。   

SerialPort Class 的文檔連結:https://docs.microsoft.com/en-us/dotnet/api/system.io.ports.serialport?view=netframework-4.5

它的示例介紹寫着:

The following code example demonstrates the use of the SerialPort class to allow two users to chat from two separate computers connected by a null modem cable. In this example, the users are prompted for the port settings and a username before chatting. Both computers must be executing the program to achieve full functionality of this example.

提取重點就是:兩個計算機的users 通過使用SerialPort class 去進行聊天 ,兩個電腦通過的是a null modem cable(這裡應該指的是序列槽線,因為RS232線的名字是RS232 Cable (Null Modem Cable))進行連接配接。

我們現階段主要實作的從序列槽中擷取資料,寫資料暫時不需要,是以我們可以在裡面提取我們需要的部分。

在文檔的左側,我們可以選擇其方法和事件來選擇我們所需要的執行個體。

C#winform小demo-序列槽傳輸實作硬體資料回傳(SerialPort類使用)
C#winform小demo-序列槽傳輸實作硬體資料回傳(SerialPort類使用)

 選取事件中的DataReceived,我們這次所需要的,其執行個體代碼:

using System;
using System.IO.Ports;

class PortDataReceived
{
    public static void Main()
    {
        SerialPort mySerialPort = new SerialPort("COM1");

        mySerialPort.BaudRate = 9600;
        mySerialPort.Parity = Parity.None;
        mySerialPort.StopBits = StopBits.One;
        mySerialPort.DataBits = 8;
        mySerialPort.Handshake = Handshake.None;
        mySerialPort.RtsEnable = true;

        mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

        mySerialPort.Open();

        Console.WriteLine("Press any key to continue...");
        Console.WriteLine();
        Console.ReadKey();
        mySerialPort.Close();
    }

    private static void DataReceivedHandler(
                        object sender,
                        SerialDataReceivedEventArgs e)
    {
        SerialPort sp = (SerialPort)sender;
        string indata = sp.ReadExisting();
        Console.WriteLine("Data Received:");
        Console.Write(indata);
    }
}
           

可以看到,微軟的執行個體很清楚的向我們展示了需要初始化的内容和SerialDataReceivedEventHandler的使用,有興趣的可以先體驗實作一下,然後我們看一下我們程式裡面使用的版本。 

看一下界面:

C#winform小demo-序列槽傳輸實作硬體資料回傳(SerialPort類使用)

 界面實作,兩個 comboBox,DropDownStyle選擇DropDownList隻允許選不允許修改,然後通過button進行觸發(打開/關閉)。comboBox的資料項自己設計,序列槽這裡就可以利用SerialPort.GetPortNames()來擷取電腦的序列槽。

序列槽comboBox實作代碼:

private void Com_comboBox_Click()
{
   string[] portNamesArray = SerialPort.GetPortNames();
   this.Com_comboBox.Items.Clear();
   foreach (var item in portNamesArray)
    {
       this.Com_comboBox.Items.Add(item);
    }
       this.Com_comboBox.Items.Add("");
}
           

 波特率就沒什麼實作代碼啦,資料項我是寫了幾個常用在item裡面了。

(因為停止位什麼的都是寫死的,是以直接用Label寫死)

然後就是按鈕的實作代碼,裡面主要是對序列槽的初始化和打開 :

private void Com_btn_Click(object sender, EventArgs e)
        {
            if (!com.IsOpen)
            {
                try
                {
                    string serialName = Com_comboBox.SelectedItem.ToString();
                    com.PortName = serialName;
                    string strBaudRate = Bps_comboBox.SelectedItem.ToString();
                    Int32 iBaudRate = Convert.ToInt32(strBaudRate);

                    com.BaudRate = iBaudRate;
                    com.Parity = Parity.None;//無奇偶校驗位
                    com.StopBits = StopBits.One;//1個停止位
                    com.Handshake = Handshake.RequestToSend;//控制協定
                    com.ReceivedBytesThreshold = 13;//設定 DataReceived 事件發生前内部輸入緩沖區中的位元組數

                    com.Handshake = Handshake.RequestToSend;//握手協定:RTS硬體流控制
                    com.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

                    if (com.IsOpen == true)
                    {
                        com.Close();
                    }
                    com.Open();
                    Com_btn.Text = "關閉序列槽";

                }
                catch (Exception ex)
                {
                    MessageBox.Show("錯誤資訊:" + ex.Message + "!");
                    return;
                }
            }
            else
            {
                com.Close();
                Com_btn.Text = "打開序列槽";
            }
        }
           

DataReceivedHandler的代碼:

void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                if (com.IsOpen)
                {
                    try
                    {

                        TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);//自己加的延時
                        Thread.Sleep(waitTime);
                        string str = "";//接收的字元串
                        int count = com.BytesToRead;

                        byte[] readBuffer = new byte[count];//byte
                        com.Read(readBuffer, 0, count);

                        foreach (byte item in readBuffer)
                        {
                            str += Convert.ToChar(item);//byte[] to char ->string
                        }


                        com.DiscardOutBuffer();//outBuffer
                        if (count != 0)
                        {
                            //線程裡不可以直接對UI進行指派
                            this.Invoke(new System.Threading.ThreadStart(delegate ()
                            {
                                
                               /*
                                    這裡可以更新UI
                                */
                                }
                            }));
                        }
                    }
                    catch (TimeoutException) { }
                }
                else
                {
                    TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);
                    Thread.Sleep(waitTime);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("錯誤資訊:" + ex.Message + "!");
            }
        }
           

(這裡轉換資料的方法網上五花八門,而且有的還有些亂碼什麼的,踏了不少坑還是微軟的文檔比較省事) 

我用的是讀取位元組,再轉成char再拼接成字元串,好像Read可以直接接收Char字元,可以把處理資料那裡改成:

// Read (char[] buffer, int offset, int count);
   char[] readBuffer = new char[count];
   com.Read(readBuffer, 0, count);
   foreach (char item in readBuffer)
     {
        str += item;
     }
           
C#winform小demo-序列槽傳輸實作硬體資料回傳(SerialPort類使用)

 SerialPort類到此就介紹完成了,完成到這裡,你的項目已經具備了連接配接序列槽、接收資料的功能了(更新UI的代碼在更新Ui章節貼出)。

自備序列槽助手這個就不用說了,除此之外建議大家安裝一個虛拟序列槽工具,在大家沒有連接配接硬體的情況下,通過序列槽助手發送資料,也能進行測試。

我用的是Configure Virtual Serial Port Driver,添加端口就能用,一個發一個收,還挺好用的。

C#winform小demo-序列槽傳輸實作硬體資料回傳(SerialPort類使用)

下一節介紹Chart圖表的應用。

繼續閱讀