標籤:remove 校正位 show end else 全域 tin 完整 函數
方法1:
使 用緩衝機制完成。首先通過定義一個成員變數List<byte> buffer = new List<byte> (4096);用來存放所有的資料,在接收函數裡,通過buffer.AddRange()方法不斷地將接收到的資料加入到buffer中,並同時對 buffer中的資料進行檢驗,如果達到一定的長度並且校正結果正確(校正方法在發送方和接收方一致),再進行處理。具體代碼如下:代碼 private List<byte> buffer = new List<byte>(4096);
private void sp_DataReceived(objectsender, EventArgs e) //sp是串口控制項
{
int n = sp.BytesToRead;
byte[] buf = new byte[n];
sp.Read(buf, 0, n);
//1.快取資料
buffer.AddRange(buf);
//2.完整性判斷
while (buffer.Count >= 4) //至少包含幀頭(2位元組)、長度(1位元組)、校正位(1位元組);根據設計不同而不同
{
//2.1 尋找資料頭
if (buffer[0] == 0x01) //傳輸資料有幀頭,用於判斷
{
int len = buffer[2];
if (buffer.Count < len + 4) //資料區尚未接收完整
{
break;
}
//得到完整的資料,複製到ReceiveBytes中進行校正
buffer.CopyTo(0, ReceiveBytes, 0, len + 4);
byte jiaoyan; //開始校正
jiaoyan = this.JY(ReceiveBytes);
if (jiaoyan != ReceiveBytes[len+3]) //校正失敗,最後一個位元組是校正位
{
buffer.RemoveRange(0, len + 4);
MessageBox.Show("資料包不正確!");
continue;
}
buffer.RemoveRange(0, len + 4);
/////執行其他代碼,對資料進行處理。
}
else //幀頭不正確時,記得清除
{
buffer.RemoveAt(0);
}
}
}
方法2:
接收資料的事件如下:
void commPlc_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] buffer=new byte[commPlc.BytesToRead];
commPlc.Read(buffer, 0, commPlc.BytesToRead);
instr = "";
foreach (byte b in buffer)
{
instr += b.ToString("X2");
}
主程式中:
outbuf = new byte[6] { 0x10, 0x02, 0x00, 0x5C, 0x5E, 0x16 };
commPlc.Write(outbuf, 0, outbuf.Length);
System.Threading.Thread.Sleep(600);
if (instr == "681212680002083203000000000002000100000501FF4716")
{
………………………………
}
解決辦法有兩種,
一個是在DataReceived事件裡加入
System.Threading.Thread.Sleep(600);
byte[] buffer=new byte[commPlc.BytesToRead];
這樣可以等待緩衝區的資料緩衝好,一次接收資料,也就是只觸發一次DataReceived事件
方法二:
將instr定義成全域變數,刪除事件裡的instr="";這樣可以保證每次觸發的時候不會清空instr
以上內容僅僅是便於自己隨手查閱使用
C# 解決串口接收資料不完整