zoukankan      html  css  js  c++  java
  • 关于串口接收数据不全的问题

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

      

  • 相关阅读:
    021.day21 反射 Class类 反射常用操作
    020.day20 线程概述 多线程优缺点 线程的创建 线程常用方法 生命周期 多线程同步
    019.day19 缓冲流 对象流 标准输入输出流
    018.day18 map集合如何实现排序 File类 IO流 字节流 字符流 编码
    017.day17 Map接口 克隆 treeSet集合排重缺陷
    016.day16 HashSet TreeSet 比较器Comparable Comparator
    015.day15
    014.day14
    013.day13
    线程
  • 原文地址:https://www.cnblogs.com/laowengdiaodayu/p/4553394.html
Copyright © 2011-2022 走看看