1 /// <summary> 2 /// 字节缓冲器 3 /// </summary> 4 public class ByteQueue 5 { 6 private List<byte> m_buffer = new List<byte>(); 7 public bool Find() 8 { 9 if (m_buffer.Count == 0) 10 return false; 11 int HeadIndex = m_buffer.FindIndex(o => o == 0xAA); 12 13 if (HeadIndex == -1) 14 { 15 m_buffer.Clear(); 16 return false; //没找到AA 17 } 18 19 else if (HeadIndex != 0) //不为开头移掉之前的字节 20 { 21 if (HeadIndex > 1) 22 m_buffer.RemoveRange(0, HeadIndex); 23 } 24 25 int length= GetLength(); 26 27 if (m_buffer.Count <length) 28 { 29 return false; 30 } 31 32 int TailIndex = m_buffer.FindIndex(o => o == 0x55); //查找55的位置 33 34 if (TailIndex == -1) 35 { 36 //这一步为防止连发一个AA开头的包后,没发55,而又发了一个AA 37 int head = m_buffer.FindLastIndex(o => o == 0xAA); 38 if (head > -1) 39 { 40 m_buffer.RemoveRange(0, head); 41 } 42 return false; 43 } 44 else if (TailIndex + 1 != length) //计算包尾是否与包长度相等 45 { 46 m_buffer.RemoveRange(0, TailIndex); 47 return false; 48 } 49 50 return true; 51 } 52 53 /// <summary> 54 /// 命令类型 55 /// </summary> 56 /// <returns></returns> 57 public byte Cmd() 58 { 59 if (m_buffer.Count >= 2) 60 { 61 return m_buffer[1]; 62 } 63 return 0; 64 } 65 66 /// <summary> 67 /// 序号 68 /// </summary> 69 /// <returns></returns> 70 public byte Number() 71 { 72 if (m_buffer.Count >= 3) 73 { 74 return m_buffer[2]; 75 } 76 return 0; 77 } 78 79 /// <summary> 80 /// 包长度 81 /// </summary> 82 /// <returns></returns> 83 public int GetLength() 84 { 85 int len = 5;//AA 命令类型 序号 校验和 55 86 if (m_buffer.Count >= 3) 87 { 88 switch (m_buffer[2]) //第三字节为序号 89 { 90 case 0x00: //序号 91 return len + 16; 92 case 0x01: //序号 93 return len + 10; 94 case 0x02: //序号 95 return len + 12; 96 } 97 } 98 return 0; 99 } 100 /// <summary> 101 /// 提取数据 102 /// </summary> 103 public void Dequeue(byte[] buffer, int offset,int size) 104 { 105 m_buffer.CopyTo(0,buffer,offset,size); 106 m_buffer.RemoveRange(0, size); 107 } 108 109 /// <summary> 110 /// 队列数据 111 /// </summary> 112 /// <param name="buffer"></param> 113 public void Enqueue(byte[] buffer) 114 { 115 m_buffer.AddRange(buffer); 116 } 117 }
1 private ByteQueue queue = new ByteQueue(); 2 private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) 3 { 4 int len = serialPort1.BytesToRead; 5 if (len > 0) 6 { 7 byte[] temp = new byte[len]; 8 serialPort1.Read(temp, 0, len); 9 queue.Enqueue(temp); 10 while (queue.Find()) //while可处理同时接收到多个AA ... 55 ,AA...55的包 11 { 12 int length = queue.GetLength(); 13 byte[] readBuffer = new byte[len]; 14 queue.Dequeue(readBuffer, 0, length); 15 OnReceiveData(readBuffer); //<这里自己写一个委托吧就OK了 16 } 17 18 } 19 20 }
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); } } }