C#中用SerialPort類實現簡單串口編程

  

.NET提供了SerialPort類進行串口通信,使用很簡單,連我這個.NET新手也能很快上手.以下是從網上找到並自己修改後的參考代碼:

 

使用SerialPort類的方法:

方法一:

首先要添加

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

1...在類的內部定義SerialPort com;

2...打開串口

            com = new SerialPort();
            com.BaudRate = 115200;
            com.PortName = "COM1";
            com.DataBits = 8;
            com.Open();//打開串口

3...發送數據

            Byte[] TxData ={1,2,3,4,5,6,7,8 };
            com.Write(TxData, 0, 8);

4...接收數據

     4.1使用事件接收

     this.com.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.OnDataReceived);

private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)

    4.2使用線程接收

     接收數據啓動一個線程,使其接收。

在類的內部定義

        Thread _readThread;
        bool _keepReading;

打開串口後啓動線程

            _keepReading = true;
            _readThread = new Thread(ReadPort);
            _readThread.Start();

線程函數

view plaincopy to clipboardprint?
private void ReadPort()  
{  
    while (_keepReading)  
    {  
        if (com.IsOpen)  
        {  
            byte[] readBuffer = new byte[com.ReadBufferSize + 1];  
            try
            {  
                // If there are bytes available on the serial port,  
                // Read returns up to "count" bytes, but will not block (wait)  
                // for the remaining bytes. If there are no bytes available  
                // on the serial port, Read will block until at least one byte  
                // is available on the port, up until the ReadTimeout milliseconds  
                // have elapsed, at which time a TimeoutException will be thrown.  
                int count = com.Read(readBuffer, 0, com.ReadBufferSize);  
                String SerialIn = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count);  
                if (count != 0)  
                    //byteToHexStr(readBuffer);  
                    Thread(byteToHexStr(readBuffer,count));  
            }  
            catch (TimeoutException) { }  
        }  
        else
        {  
            TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);  
            Thread.Sleep(waitTime);  
        }  
    }  
}
        private void ReadPort()
        {
            while (_keepReading)
            {
                if (com.IsOpen)
                {
                    byte[] readBuffer = new byte[com.ReadBufferSize + 1];
                    try
                    {
                        // If there are bytes available on the serial port,
                        // Read returns up to "count" bytes, but will not block (wait)
                        // for the remaining bytes. If there are no bytes available
                        // on the serial port, Read will block until at least one byte
                        // is available on the port, up until the ReadTimeout milliseconds
                        // have elapsed, at which time a TimeoutException will be thrown.
                        int count = com.Read(readBuffer, 0, com.ReadBufferSize);
                        String SerialIn = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count);
                        if (count != 0)
                            //byteToHexStr(readBuffer);
                            Thread(byteToHexStr(readBuffer,count));
                    }
                    catch (TimeoutException) { }
                }
                else
                {
                    TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);
                    Thread.Sleep(waitTime);
                }
            }
        }

方法二:使用C#自帶的SerialPor控件。

1...在“工具箱”的“組件”中選擇SerialPor控件添加。

2...設置串口並打開

serialPort1.PortName = "COM1";

serialPort1.BaudRate = 9600;

serialPort1.Open();

3...寫入數據可以使用Write或者下面的函數

serialPort1.WriteLine(str);

4...添加數據接收的事件

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)

使用中的一些常見問題

C#中SerialPort類中DataReceived事件GUI實時處理方法(來自[email protected] 的看法)
MSDN:從 SerialPort 對象接收數據時,將在輔助線程上引發 DataReceived 事件。由於此事件在輔助線程而非主線程上引發,因此嘗試修改主線程中的一些元素(如 UI 元素)時會引發線程異常。如果有必要修改主 Form 或 Control 中的元素,必須使用 Invoke 回發更改請求,這將在正確的線程上執行.進而要想將輔助線程中所讀到的數據顯示到主線程的Form控件上時,只有通過Invoke方法來實現
下面是代碼實例:
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
   int SDateTemp = this.serialPort1.ReadByte();
   //讀取串口中一個字節的數據
   this.tB_ReceiveDate.Invoke(  
//在擁有此控件的基礎窗口句柄的線程上執行委託Invoke(Delegate)
//即在textBox_ReceiveDate控件的父窗口form中執行委託.
new MethodInvoker(           
/*表示一個委託,該委託可執行託管代碼中聲明爲 void 且不接受任何參數的任何方法。 在對控件的 Invoke 方法進行調用時或需要一個簡單委託又不想自己定義時可以使用該委託。*/
delegate{                
    /*匿名方法,C#2.0的新功能,這是一種允許程序員將一段完整代碼區塊當成參數傳遞的程序代碼編寫技術,通過此種方法可 以直接使用委託來設計事件響應程序以下就是你要在主線程上實現的功能但是有一點要注意,這裏不適宜處理過多的方法,因爲C#消息機制是消息流水線響應機制,如果這裏在主線程上處理語句的時間過長會導致主UI線程阻塞,停止響應或響應不順暢,這時你的主form界面會延遲或卡死      */                  
this.tB_ReceiveDate.AppendText(SDateTemp.ToString());//輸出到主窗口文本控件
this.tB_ReceiveDate.Text += " ";}
    )
    );
}

如何知道當前電腦有哪個串口

在窗體上添加一個comboBox控件。

然後使用comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames()); 或者

string[] portList = System.IO.Ports.SerialPort.GetPortNames();
            for (int i = 0; i < portList.Length; ++i)
            {
                string name = portList[i];
                comboBox1.Items.Add(name);
            }

文獻來源:http://blog.21ic.com/user1/1949/archives/2010/66360.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章