C# 解決上位機串口接收數據丟失問題


項目需要實現下位機和上位機的數據傳輸,看了網上的很多上位機的處理方法主要有兩種。方法一是:port_DataReceived(SerialPort控件的數據接收方法,當有數據來臨時會觸發)會創建一個線程,因此當串口在等待數據時,不影響主窗體或主線程的操作。方法二是:使用緩存機制(參考:http://blog.csdn.net/jiqiang_paul/article/details/6914619)。首先通過定義一個成員變量List ReceBuf  new List(4096);用來存放所有的數據,在接收函數里,通過RecBuf.AddRange()方法不斷地將接收到的數據加入到ReceBuf中,並同時對Recebuf中的數據進行檢驗,如果達到一定的長度並且校驗結果正確(校驗方法在發送方和接收方一致),再進行處理。

經過測試發現這兩種方法在數據包發送間隔小於200ms時,會出現數據丟包的問題,現在將這兩種方法結合起來,同時將方法二改進為雙緩存機制,經過測試發現可以解決數據的丟包的問題。
一、在 public MainForm()中定義串口數據接收事件
  public MainForm()
        {
            InitializeComponent();
            serialPort_port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);//串口接收事件
            System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;//關閉誇線程檢查
        }
二、MainForm類下定義接收事件的委托並編寫接收程序
 
  public delegate void PortDelegate();
        private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            PortDelegate proc_PORTGETDATA = new PortDelegate(getComData);
            IAsyncResult async_PORTGETDATA = proc_PORTGETDATA.BeginInvoke(null, null);
        }
private List ReceBuffer = new List(4096);//串口接收一級緩存,默認分配一頁內存並始終不超過 
 private byte[] DataTemp = new byte[10];//從一級緩存拷貝到二級緩存 
 private List DataBuf = new List(1000);//串口接收二級緩存,默認分配1000並始終不超過
 private byte[] DataTemp2 = new byte[10];//從二級緩存拷貝出來分析
 private byte[] DataAnalyBuf = new byte[8]; 
 public void getComData()
 { 
 try
 { 
 int n = serialPort_port.BytesToRead; 
 byte[] Receive = new byte[n]; 
 serialPort_port.Read(Receive, 0, Receive.Length); 
 bool DataCatched = false;//數據可以分析的標志
 //緩存數據 
 ReceBuffer.AddRange(Receive); 
 //完整性判斷 
 while(ReceBuffer.Count >= 10)
 { 
 ////查看幀首和尾數據,判斷准確性 
//這里可以寫成對數據的校驗如CRC
if (ReceBuffer[0] == 0x50 && ReceBuffer[9] == 0x42) 
 { 
 ReceBuffer.CopyTo(0, DataTemp, 0, 10); 
 DataBuf.AddRange(DataTemp); 
DataCatched = true; 
 ReceBuffer.RemoveRange(0, 10);//獲得一條正確的數據,刪除緩存
 }
 else
 { 
 ReceBuffer.RemoveAt(0);//不是數據頭,刪除數據
 }
 }
 //分析數據 
 if (DataCatched == true) 
 { 
 while (DataBuf.Count > 0)
 {
 DataBuf.CopyTo(0,DataTemp2,0,10); 
在這里寫自己的數據分析
DataBuf.RemoveRange(0, 10);
 } 
 }
 } catch { } 
 }


免責聲明!

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



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