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


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

      

  • 相关阅读:
    redis几种数据类型以及使用场景
    Ubuntu16.04安装redis和php的redis扩展
    详细透彻解读Git与SVN的区别(集中式VS分布式)
    bootstrap轮播如何支持移动端滑动手势
    vue添加cnzz统计访问量
    el-tabs值修改时更新路由参数值
    Vue ,elementUI,dropdown组件中command方法添加额外参数的方法
    vue页面滚动监听
    mintui tabbar底部跳转页面
    vue 引入bootstrap
  • 原文地址:https://www.cnblogs.com/laowengdiaodayu/p/4553394.html
Copyright © 2020-2023  润新知