C#使用SerialPort類實現串口通信


 

原文轉自: https://www.cnblogs.com/hbtmwangjin/articles/9146299.html

主要用於學習記錄

如果需要了解更多的信息請登錄http://msdn.microsoft.com/zh-cn/library/system.io.ports.serialport(VS.80).aspx查看。

在.NET Framework 2.0中提供了SerialPort類,該類主要實現串口數據通信等。

下面主要介紹該類的主要屬性(表1)和方法(表.2) 

 

表1                                                      SerialPort類的常用屬性

名  稱

說  明

BaseStream

獲取 SerialPort 對象的基礎 Stream 對象

BaudRate

獲取或設置串行波特率

BreakState

獲取或設置中斷信號狀態

BytesToRead

獲取接收緩沖區中數據的字節數

BytesToWrite

獲取發送緩沖區中數據的字節數

CDHolding

獲取端口的載波檢測行的狀態

CtsHolding

獲取“可以發送”行的狀態

DataBits

獲取或設置每個字節的標准數據位長度

DiscardNull

獲取或設置一個值,該值指示 Null 字節在端口和接收緩沖區之間傳輸時是否被忽略

DsrHolding

獲取數據設置就緒 (DSR) 信號的狀態

DtrEnable

獲取或設置一個值,該值在串行通信過程中啟用數據終端就緒 (DTR) 信號

Encoding

獲取或設置傳輸前后文本轉換的字節編碼

Handshake

獲取或設置串行端口數據傳輸的握手協議

IsOpen

獲取一個值,該值指示 SerialPort 對象的打開或關閉狀態

NewLine

獲取或設置用於解釋 ReadLine( )和WriteLine( )方法調用結束的值

Parity

獲取或設置奇偶校驗檢查協議

續表

名  稱

說  明

ParityReplace

獲取或設置一個字節,該字節在發生奇偶校驗錯誤時替換數據流中的無效字節

PortName

獲取或設置通信端口,包括但不限於所有可用的 COM 端口

ReadBufferSize

獲取或設置 SerialPort 輸入緩沖區的大小

ReadTimeout

獲取或設置讀取操作未完成時發生超時之前的毫秒數

ReceivedBytesThreshold

獲取或設置 DataReceived 事件發生前內部輸入緩沖區中的字節數

RtsEnable

獲取或設置一個值,該值指示在串行通信中是否啟用請求發送 (RTS) 信號

StopBits

獲取或設置每個字節的標准停止位數

WriteBufferSize

獲取或設置串行端口輸出緩沖區的大小

WriteTimeout

獲取或設置寫入操作未完成時發生超時之前的毫秒數

表2                                                     SerialPort類的常用方法

方 法 名 稱

說  明

Close

關閉端口連接,將 IsOpen 屬性設置為False,並釋放內部 Stream 對象

Open

打開一個新的串行端口連接

Read

從 SerialPort 輸入緩沖區中讀取

ReadByte

從 SerialPort 輸入緩沖區中同步讀取一個字節

ReadChar

從 SerialPort 輸入緩沖區中同步讀取一個字符

ReadLine

一直讀取到輸入緩沖區中的 NewLine 值

ReadTo

一直讀取到輸入緩沖區中指定 value 的字符串

Write

已重載。將數據寫入串行端口輸出緩沖區

WriteLine

將指定的字符串和 NewLine 值寫入輸出緩沖區

 

使用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();

線程函數

 

[c-sharp]  view plain copy
 
 
  1. private void ReadPort()  
  2. {  
  3.     while (_keepReading)  
  4.     {  
  5.         if (com.IsOpen)  
  6.         {  
  7.             byte[] readBuffer = new byte[com.ReadBufferSize + 1];  
  8.             try  
  9.             {  
  10.                 // If there are bytes available on the serial port,   
  11.                 // Read returns up to "count" bytes, but will not block (wait)   
  12.                 // for the remaining bytes. If there are no bytes available   
  13.                 // on the serial port, Read will block until at least one byte   
  14.                 // is available on the port, up until the ReadTimeout milliseconds   
  15.                 // have elapsed, at which time a TimeoutException will be thrown.   
  16.                 int count = com.Read(readBuffer, 0, com.ReadBufferSize);  
  17.                 String SerialIn = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count);  
  18.                 if (count != 0)  
  19.                     //byteToHexStr(readBuffer);   
  20.                     ThreadFunction(byteToHexStr(readBuffer,count));  
  21.             }  
  22.             catch (TimeoutException) { }  
  23.         }  
  24.         else  
  25.         {  
  26.             TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);  
  27.             Thread.Sleep(waitTime);  
  28.         }  
  29.     }  
  30. }  

  

方法二:使用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實時處理方法(來自wanglei_wan@yahoo.com.cn 的看法)
MSDN:從 SerialPort 對象接收數據時,將在輔助線程上引發 DataReceived 事件。由於此事件在輔助線程而非主線程上引發,因此嘗試修改主線程中的一些元素(如 UI 元素)時會引發線程異常。如果有必要修改主 Form 或 Control 中的元素,必須使用 Invoke 回發更改請求,這將在正確的線程上執行.進而要想將輔助線程中所讀到的數據顯示到主線程的Form控件上時,只有通過Invoke方法來實現 
下面是代碼實例: 

[c-sharp]  view plain copy
 
 
  1. private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)  
  2. {  
  3.    int SDateTemp = this.serialPort1.ReadByte();  
  4.    //讀取串口中一個字節的數據   
  5.    this.tB_ReceiveDate.Invoke(     
  6.     //在擁有此控件的基礎窗口句柄的線程上執行委托Invoke(Delegate)   
  7.     //即在textBox_ReceiveDate控件的父窗口form中執行委托.   
  8.     new MethodInvoker(              
  9.     /*表示一個委托,該委托可執行托管代碼中聲明為 void 且不接受任何參數的任何方法。 在對控件的 Invoke    方法進行調用時或需要一個簡單委托又不想自己定義時可以使用該委托。*/  
  10.     delegate{                   
  11.     /*匿名方法,C#2.0的新功能,這是一種允許程序員將一段完整代碼區塊當成參數傳遞的程序代碼編寫技術,通過此種方法可  以直接使用委托來設計事件響應程序以下就是你要在主線程上實現的功能但是有一點要注意,這里不適宜處理過多的方法,因為C#消息機制是消息流水線響應機制,如果這里在主線程上處理語句的時間過長會導致主UI線程阻塞,停止響應或響應不順暢,這時你的主form界面會延遲或卡死      */                     
  12.     this.tB_ReceiveDate.AppendText(SDateTemp.ToString());//輸出到主窗口文本控件   
  13.     this.tB_ReceiveDate.Text += " ";}  
  14.     )  
  15.     );  
  16. }  

 

 

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

在窗體上添加一個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);
            }

 


免責聲明!

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



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