日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

C#解决串口数据丢失问题

發布時間:2023/12/18 C# 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C#解决串口数据丢失问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C# 解決串口數據丟失問題

C # 串行類( SerialPort )是.NET Framework version 2.0 中一個新增的類,該類將串口操作了封裝,從而為串口通信提供了簡便方法。

但在實際串口通信的應用中,在串口高波特率大信息量的數據通信時,會出現丟失數據的問題。

通常我們使用SerialPort類接收串口發送過來的數據時,只需要寫一個事件函數。

即DataReceived 事件綁定一個處理函數,然后就可以在該函
數中實現對串口數據的讀取。 這個函數的內容可以根據我們的需求自行修改。就單純從接收數據的角度出發, 假設該函數內容如下:

//串口接收事件private void SerialPort_Rec(object sender, SerialDataReceivedEventArgs e){//Thread.Sleep(50);string recString = string.Empty;while (this.SerialPort.BytesToRead > 0){recString += this.SerialPort.ReadExisting(); //數據讀取,直到讀完緩沖區數據}DealString(recString); //處理接收到的字符串,由自己寫}

大多串口程序都會采用這種思路來實現串口通信。即先接收數據,然后處理數據,并在完成數據處理后,再次等待接收新數據。但這種實現方法在串口高速率大信息量通信時,會出現丟失數據的情況。

這里根據我自己的情況舉一個例子:

我從下位機每次發送一幀數據給串口,我希望這一幀數據如下:

應答:$STA,A,27.0,1234,210914080000,X
A為儀器ID,27.0為溫度,1234為功耗1234mW,RTC時間,X為校驗

但實際接收過程中往往只收到一半數據$STA,A,27.0,1234就直接執行了數據處理函數。

解決方法

采樣多線程的方法來解決這個問題。

在主線程中專門接收數據,增加一個線程來處理數據。

最好不要選用像數組這樣數據結構。因為此類數據結構在多線程中操作時必須頻繁地“加鎖”和“解鎖”,在一定程度上會降低程序的性能。所以我們選用隊列 Queen 作為數據池的數據結構。

使用列隊的好處在這里充分體現了,數據先入先出,先收到的數據進行處理后就可以直接釋放掉這部分內存,使得程序的運行效率大幅增加。

同時在結束處理的的時候,要對隊列的長度進行判斷,只有把整個隊列處理結束才可以結束線程。

同時該方法也存很明顯在劣勢,如下:

當數據流入隊的速度大于出列隊(即接收數據的速度大于處理數據),舉個簡單例子,就相當于我們手上有一萬塊錢,每天要花20,每天只能賺10塊錢,短時間內我們的錢是夠用的,但時間一長,資源就會枯竭。

以上情況下,且需要長時間運行時,堆內存就有可能溢出。

這里貼出我的代碼:

//串口接收事件private void SerialPort_Rec(object sender, SerialDataReceivedEventArgs e){while (this.SerialPort.BytesToRead > 0){data_Queue.Enqueue((byte)SerialPort.ReadByte()); //數據入隊}}

數據處理線程:

//數據處理線程public void DealDataThread(){List<byte> databytes = new List<byte>();//byte[] databytes = new byte[20]; //C#,java的數組的數據只能分配在堆區,沒有辦法while (!canStop) //循環檢測列隊{ /*中間這部分是我個人的數據處理代碼,用戶可以根據自己需求自己改變*/if(data_Queue.Count>=24) //當接收到的數據長度足夠時開始處理{//System.Diagnostics.Debug.WriteLine(data_Queue.Peek());if (data_Queue.Dequeue()== 36) //36就是字符'$',即對應幀頭{if(data_Queue.Dequeue() == 36) //雙$$指令{for(int i = 0; i < 20; i++){databytes.Add(data_Queue.Dequeue());//databytes.(i, data_Queue.Dequeue().to,1);}fileWriter.WriteLine(System.Text.Encoding.Default.GetString(databytes.ToArray()));databytes.Clear()}}}}}

總結

以上是生活随笔為你收集整理的C#解决串口数据丢失问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。