C#解决串口数据丢失问题
C# 解決串口數據丟失問題
C # 串行類( SerialPort )是.NET Framework version 2.0 中一個新增的類,該類將串口操作了封裝,從而為串口通信提供了簡便方法。
但在實際串口通信的應用中,在串口高波特率大信息量的數據通信時,會出現丟失數據的問題。
通常我們使用SerialPort類接收串口發送過來的數據時,只需要寫一個事件函數。
即DataReceived 事件綁定一個處理函數,然后就可以在該函
數中實現對串口數據的讀取。 這個函數的內容可以根據我們的需求自行修改。就單純從接收數據的角度出發, 假設該函數內容如下:
大多串口程序都會采用這種思路來實現串口通信。即先接收數據,然后處理數據,并在完成數據處理后,再次等待接收新數據。但這種實現方法在串口高速率大信息量通信時,會出現丟失數據的情況。
這里根據我自己的情況舉一個例子:
我從下位機每次發送一幀數據給串口,我希望這一幀數據如下:
應答:$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#解决串口数据丢失问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LINUX 安装护眼软件
- 下一篇: c# EASYUI+MVC filebo