現在樓主接收的是后面的數據而前面的數據消失了,應該就是你在事件中處理數據過慢 導致新的串口數據往緩存區中發送把你原有緩存區的數據沖掉了。在接收事件中就不應該去做數據的處理特別是大循環的語句會消耗你機器的性能和時間,定義一個緩存區只做數據的接收,在另外開啟一個線程來做數據的處理 ,比如你所需要的字符串的拼接。
而微軟封裝串行口的接收數據事件是另外開了一個異步線程來做的處理。
int data_num = 0;//上次未處理數據長度 byte[] data_buf = new byte[50000];//存放上次未處理數據
接收處理程序:
else { int _frame_num = 0; // 接收幀在frame數組里的索引, int _frame_len = 0; // 幀長度 , if (n > 20000) return;//接收到的數據過長,可能出錯 serialPort1.Read(data_buf, data_num, n);//讀取緩沖數據,從data_buf的第data_num處開始寫入,與之前未處理數據連接在一起 data_num += n;//未處理的數據位置 重新定位到 data_num + n int I = 0;// while (I < data_num - 4)//遍歷接收數據 { if (data_buf[I] == 0xaa && data_buf[I + 1] == 0xaa && data_buf[I + 3] < 51) { _frame_num = data_buf[I + 2]; _frame_len = data_buf[I + 3]; if ((data_num - I - 5) >= _frame_len) // 數據接收完畢 { byte sum = 0; for (int j = I; j <= I + 3 + _frame_len; j++)//計算sum sum += data_buf[j]; if (sum == data_buf[I + 4 + _frame_len])//sum校驗通過 { int j; switch (_frame_num) { case 2://傳感器數據 j = I + 4; S_acc_x = (Int16)(data_buf[j] << 8 | data_buf[j + 1]); S_acc_y = (Int16)(data_buf[j + 2] << 8 | data_buf[j + 3]); S_acc_z = (Int16)(data_buf[j + 4] << 8 | data_buf[j + 5]); S_gyr_x = (Int16)(data_buf[j + 6] << 8 | data_buf[j + 7]); S_gyr_y = (Int16)(data_buf[j + 8] << 8 | data_buf[j + 9]); S_gyr_z = (Int16)(data_buf[j + 10] << 8 | data_buf[j + 11]); S_mag_x = (Int16)(data_buf[j + 12] << 8 | data_buf[j + 13]); S_mag_y = (Int16)(data_buf[j + 14] << 8 | data_buf[j + 15]); S_mag_z = (Int16)(data_buf[j + 16] << 8 | data_buf[j + 17]); break; default: break; } I = I + 5 + _frame_len; // I指向下一幀數據 } else//sum校驗未通過 { I++; } } else//HEAD FUN LEN符合要求,但是數據未接收完畢 { for (int j = I; j <= data_num - 1; j++) { data_buf[j - I] = data_buf[j]; } data_num = data_num - I; return; } } else//HEAD FUN LEN 不符合要求 { I++; } } if (I < data_num) // 剩幾字節沒有處理完 { for (int j = I; j <= data_num - 1; j++) { data_buf[j - I] = data_buf[j]; } data_num = data_num - I; } } }
http://www.cnblogs.com/haofaner/p/3402307.html
使 用緩存機制完成。首先通過定義一個成員變量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); } } }
