字节流中数据包的识别

6

我在与加速度传感器通信时遇到了一些问题。该传感器连续输出约8000个读数/秒。传感器通过适配器插入到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),同时也是数据包起始标识。我对编程外部设备比较陌生,无法理解校验和如何作为数据包起始标识符(难道校验和不会一直变化吗?)。这种方式通常用于标识数据包起始吗?有没有人知道如何解决这个问题呢?

非常感谢您的帮助。


这些是什么类型的数据包?UDP?TCP?还是其他的? - J. Davidson
@J.Davidson 这必须是它们之一吗?它可以是从外部设备读取的字节块吗? - I4V
每秒采样率为8192个样本,波特率设置为921600bps(根据手册)。对于UDP和TCP我不太确定,我是通过C#.net中的串口类进行读取。 - karra
你观察到了“第一个字节的低四位”吗?它可以是id吗? - I4V
我现在已经让它工作得相当不错了。我必须检查每个半字节,直到找到根据我的问题中的算法为其后续半字节生成的校验和。感谢大家的帮助! - karra
显示剩余6条评论
2个回答

4
我不太理解校验和如何作为数据包开头的标识符(因为校验和不会一直保持不变)。
是的,校验和会随着数据的改变而改变。但是仅仅一个固定值的起始字节也不能单独用于(最初)识别(或验证)数据包。由于这是二进制数据(而不是文本),数据可以具有与任何固定值的起始字节相同的值。如果您对此起始字节进行了简单的扫描,该算法很容易将数据字节错误地识别为起始字节。
这是一种常见的识别数据包开头的方法吗?
不是,但考虑到高数据速率,它似乎是一种最小化数据包大小的方案。
有人有任何想法如何解决这个问题吗?
您可能需要最初每次扫描五个字节的序列(即数据包的长度)。计算此“数据包”的校验和,并将其与第一个字节进行比较。匹配表示您(可能)已经完成了数据包对齐。不匹配意味着您应该丢弃第一个字节,并测试下一个以第二个字节开头的可能的数据包(即移动剩余的4个字节并添加新的第5个字节)。
一旦完成了数据包对齐(或者假定已完成),您需要不断验证每个数据包的校验和,以确认数据完整性并确保数据包数据对齐。任何校验和错误都应该强制重新寻找正确的数据包对齐(从当前“数据包”的第二个字节开始)。

0
你需要做的是在你的项目中导入一些免费的C#串口终端,并首先检查你所获取的所有数据和数据包,除非你已经完成了这个步骤。然后只需要读取,你需要做类似于...的操作。
   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());
       }
     }
   }

1
你认为 OP 是在读取数据方面有问题还是在解释数据方面有问题?我在评论中看到:“我观察了所有的字节,但找不到任何一个保持不变。” - I4V
是的,我似乎能够读取数据,但我无法正确解释它。我明天会尝试您的代码并将其与我的结果进行比较。 - karra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接