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