項目需要實現下位機和上位機的數據傳輸,看了網上的很多上位機的處理方法主要有兩種。方法一是: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 { }
}