【问题标题】:Identification of packets in a byte stream字节流中数据包的标识
【发布时间】:2013-04-23 19:49:38
【问题描述】:

我在与加速度计传感器的通信方面遇到了一点问题。传感器连续输出约 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 是否必须是其中之一。可以是从外部设备读取的字节块吗?
  • 5 字节/数据包,每秒 8000 = 40Kb/秒,您需要 400000 的波特率,而不是标准问题 COM 设置
  • 每秒 8192 个样本,buad rate 设置为 921600bps(根据手册)。我不确定 UDP、TCP,我正在通过 C# .net 中的 com 端口类阅读。
  • 你观察到low nibble in the first byte了吗?可以是id吗?

标签: serial-port checksum packet serial-communication


【解决方案1】:

...无法真正理解如何将校验和用作包开始的标识符(校验和不是一直在变化吗?)。

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

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

不,但考虑到高数据速率,这似乎是一种最小化数据包大小的方案。

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

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

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

【讨论】:

    【解决方案2】:

    你需要做的是在你的项目中用 c# 导入一些免费的 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());
           }
         }
       }
    

    【讨论】:

    • 您认为 OP 在读取数据解释数据方面是否存在问题。我在 cmets 中看到 I have observed the nibbles (all of them) but I can't find anyone that remains constant
    • 是的,我似乎可以读取数据,但无法正确解释。我明天会试试你的代码,并将它与我的结果进行比较。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多