C# 串口連接的讀取與發送(附串口工具的編寫源碼)


一、串口連接的打開與關閉

串口,即COM口,在.NET中使用 SerialPort 類進行操作。串口開啟與關閉,是涉及慢速硬件的IO操作,頻繁打開或關閉會影響整體處理速度,甚至導致打開或關閉串口失敗。非特殊情況,串口一次性打開后,在退出程序時關閉串口即可。在打開串口前,可以設置一些常用的參數。常用的參數如下:

(1)串口的接受/發送超時時間:ReadTimeout/WriteTimeout。

(2) 串口的接受/發送緩存區大小:ReadBufferSize/WriteBufferSize。

具體代碼如下:

 1             // Open Com
 2             _serialPort = new SerialPort(com, baud);
 3             if (_serialPort.IsOpen) _serialPort.Close();
 4 
 5             // Set the read / write timeouts
 6             _serialPort.ReadTimeout = 500;
 7             _serialPort.WriteTimeout = 500;
 8 
 9             // Set read / write buffer Size,the default of value is 1MB
10             _serialPort.ReadBufferSize = 1024 * 1024;
11             _serialPort.WriteBufferSize = 1024 * 1024;
12 
13             _serialPort.Open();
14 
15             // Discard Buffer
16             _serialPort.DiscardInBuffer();
17             _serialPort.DiscardOutBuffer();

需要注意的是超出緩沖區的部分會被直接丟棄。因此,如果需要使用串口傳送大文件,那接收方和發送方都需要將各自的緩沖區域設置的足夠大,以便能夠一次性存儲下大文件的二進制數組。若條件限制,緩沖區域不能設置過大,那就需要在發送大文件的時候按照發送緩沖區大小分包去發送,接收方按順序把該數組組合起來形成接受文件的二進制數組。

二、串口發送

SerialPort 類發送支持二進制發送與文本發送,需要注意的是文本發送時,需要知道轉換的規則,一般常用的是ASCII、UTF7、UTF-8、UNICODE、UTF32。具體代碼如下:

 1         #region Send
 2         /// <summary>
 3         /// 發送消息(byte數組)
 4         /// </summary>
 5         /// <param name="buffer"></param>
 6         /// <param name="offset"></param>
 7         /// <param name="count"></param>
 8         public void Send(byte[] buffer, int offset, int count)
 9         {
10             lock (_mux)
11             {
12                 _serialPort.Write(buffer, offset, count);
13                 _sendCount += (count - offset);
14             }
15         }
16 
17         /// <summary>
18         /// 發送消息(字符串)
19         /// </summary>
20         /// <param name="encoding">字符串編碼方式,具體方式見<see cref="Encoding"/></param>
21         /// <param name="message"></param>
22         public void Send(Encoding encoding , string message)
23         {
24             lock (_mux)
25             {
26                 var buffer = encoding.GetBytes(message);
27                 _serialPort.Write(buffer, 0, buffer.Length);
28                 _sendCount += buffer.Length;
29             }
30         }
31         #endregion

三、串口接受

​ 串口接受需要注意,消息接受與消息處理要代碼分離。不能把流程處理的代碼放入信息接受處,因為消息處理或多或少會有耗時,這會造成當發送方發送過快時,接受方的接受緩沖區會緩存多條消息。我們可以把接受到的消息放入隊列中,然后在外部線程中,嘗試去拿出該條消息進行消費。采用 “生產-消費”模式。具體代碼如下:

 1      #region Receive
 2         private void PushMessage()
 3         {
 4             _serialPort.DataReceived += (sender, e) =>
 5             {
 6                 lock (_mux)
 7                 {
 8                     if (_serialPort.IsOpen == false) return;
 9                     int length = _serialPort.BytesToRead;
10                     byte[] buffer = new byte[length];
11                     _serialPort.Read(buffer, 0, length);
12                     _receiveCount += length;
13                     _messageQueue.Enqueue(buffer);
14                     _messageWaitHandle.Set();
15                 }
16             };
17         }
18 
19         /// <summary>
20         /// 獲取串口接受到的內容
21         /// </summary>
22         /// <param name="millisecondsToTimeout">取消息的超時時間</param>
23         /// <returns>返回byte數組</returns>
24         public byte[] TryMessage(int millisecondsToTimeout = -1)
25         {
26             if (_messageQueue.TryDequeue(out var message))
27             {
28                 return message;
29             }
30 
31             if (_messageWaitHandle.WaitOne(millisecondsToTimeout))
32             {
33                 if (_messageQueue.TryDequeue(out message))
34                 {
35                     return message;
36                 }
37             }
38             return default;
39         }
40         #endregion

四、完整代碼與測試結果

​ 串口工具類的完整代碼如下:

imgView Code

​ 測試代碼如下:

imgView Code

使用串口工具測試如下,對於串口的接受如絲般順滑。當我們在消息中增加測試延時后,就會發現當串口工具繼續快速發送一段時間后關閉發送,發現使用隊列后,依然沒有丟失一條來自發送方的消息。

img

五、串口工具編寫實例

通過以上對串口的了解,我們模仿串口工具進行編程,完成如下:

img img

該串口工具采用WPF框架的MVVM模式進行開發,代碼地址:https://github.com/Dwayne112401/MyProgra-SerialportTool


免責聲明!

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



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