关于串口接收数据不全的问题

  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);
}
}
}

  

原文地址:https://www.cnblogs.com/laowengdiaodayu/p/4553394.html