识别字节流中的数据包

时间:2013-04-23 19:49:39

标签: serial-port checksum packet serial-communication

我对加速计传感器的通信有点问题。传感器连续输出大约8000个读数/秒。传感器插入带有adaper的usb端口,显示为com4。我的问题是我似乎无法从字节流中挑选传感器读取数据包。数据包的大小为五个字节,格式如下:

            High nibble                     Low nibble

Byte 1      checksum, id for packet start   X high
Byte 2      X mid                           X low
Byte 3      Y high                          Y mid
Byte 4      Y low                           Z high
Byte 5      Y mid                           Y low

X,y,z是加速度。

在传感器的文档中,它指出第一个字节中的高半字节是校验和(计算的Xhigh + Xlow + Yhigh + Ylow + Zhigh + Zlow),但也是数据包开始的标识。我很擅长针对外部设备进行编程,并且无法真正掌握如何将校验和用作程序包启动的标识符(校验和不会一直变化吗?)。这是识别数据包开始的常用方法吗?有谁知道如何解决这个问题?

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

  

...无法真正掌握校验和如何用作程序包开头的标识符(校验和不会一直变化吗?)。

是的,校验和会发生变化,因为它来自数据 但即使是固定值的数据包开始半字节(单独)也不足以(最初)识别(或验证)数据包。由于这是二进制数据(而不是文本),因此数据可以采用与任何固定值数据包开始相同的值。如果你对这个初始半字节进行了一次微不足道的扫描,那么该算法很容易将数据半字节错误识别为起始半字节。

  

这是识别数据包开始的常用方法吗?

不,但鉴于高数据速率,似乎是一种最小化数据包大小的方案。

  

有谁知道如何解决这个问题?

您可能必须首先扫描每个字节序列五次(即数据包帧的长度) 计算此帧的校验和,并将其与第一个半字节进行比较 匹配表示您(可能)具有帧对齐 不匹配意味着您应该丢弃第一个字节,并测试下一个可能的数据包帧,该数据包帧将从第二个字节开始(即移位剩余的4个字节并附加新的第5个字节)。

一旦实现(或假设)帧对齐,您需要不断验证每个数据包的校验和,以确认数据完整性并确保帧对齐。任何校验和错误都应该强制进行另一次正确的帧对齐(从当前数据包的第二个字节开始)。

答案 1 :(得分:1)

您需要做的是在项目中的c#import中获取一些免费的SerialPortTerminal,并首先检查您获得的所有数据和数据包,除非您已经这样做了。不仅仅是为了阅读你需要做的事情......

   using System;
   using System.IO.Ports;
   using System.Windows.Forms;

   namespace SPE
   {
     class SerialPortProgram
     {
       // Create the serial port with basic settings
       private SerialPort port = new SerialPort("COM4",      9600, Parity.None, 8, StopBits.One);

       [STAThread]
       static void Main(string[] args)
       { 
         // Instatiate this class
         new SerialPortProgram();
       }

       private SerialPortProgram()
       {
         Console.WriteLine("Incoming Data:");

         // Attach a method to be called when there      // is data waiting in the port's buffer
         port.DataReceived += new         SerialDataReceivedEventHandler(port_DataReceived);

         // Begin communications
         port.Open();

         // Enter an application loop to keep this thread alive
         Application.Run();
       }

       private void port_DataReceived(object sender,      SerialDataReceivedEventArgs e)
       {
         // Show all the incoming data in the port's buffer
         Console.WriteLine(port.ReadExisting());
       }
     }
   }