解析从串口接收的数据包 [英] Parsing the data packet received from serial port

查看:213
本文介绍了解析从串口接收的数据包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

输出基本上是字节的十进制表示。并且连接到串口的硬件以这些格式发送E0,F2,设备ID,2字节长度,当前日期,当前时间(通过右移和其他一些数据存储当前日期和当前时间超过2个字节)



我收到的数据有时是4个字节,有时是8个字节。我想做的是1.我想先检查一下我收到的数据包里有什么喜欢标题2.然后当我收到下一个数据块时,我不想检查标题,而是查看日期和时间等下一个信息等等。



基本上我想要解析传入的数据包。



任何人都可以举个小例子。这将非常有用。



谢谢。



我的尝试:



The output is basically the dec representation of the bytes. and the hardware connected to serial port send it in these format E0 ,F2 ,device id ,2 bytes length,current date,current time(store both current date and current time in more than 2 bytes by right shifting and some other data)

I am receiving data in chunks sometimes 4 bytes, sometimes 8 bytes.What i want to do is 1.I want to check first what i have received in that data packet like header 2.then when i received next data block i do not want to check for header but for next information like date and time and so on..

basically i want to parse the incoming packet.

can anyone please give an small example.It will be really helpful.

Thanks.

What I have tried:

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SerialPortHexCommunication
{
public class Program
{
    static void Main(string[] args)
    {

        SerialPort port = new SerialPort();
        port.PortName = "COM5";
        port.Parity = Parity.None;
        port.BaudRate = 9600;
        port.DataBits = 8;
        port.StopBits = StopBits.One;

        if (port.IsOpen)

        {
            port.Close();
            port.Dispose();
        }
         port.Open();

        byte[] bytesToSend = new byte[6] { 0xD0, 0xF2, 0xFF, 0x00, 0x06, 0xC7 };

        port.Write(bytesToSend, 0, bytesToSend.Length);


        port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

        Console.ReadKey();
        port.Close();
        port.Dispose();




    }

    private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
    {
        Console.WriteLine("Data receive at time "+ DateTime.Now.TimeOfDay);
        SerialPort port = (SerialPort)sender;

        int bytes = port.BytesToRead;
        byte[] buffer = new byte[bytes];

        if (port.BytesToRead > 1)
        {
            port.Read(buffer, 0, bytes);
        }

        foreach (byte item in buffer)
        {
            Console.WriteLine(item);

        }


    }
}

推荐答案

接收串行数据是一种异步操作,通常不会从包含单个事件的数据包中获取所有数据。



所以你必须创建至少接收缓冲区和索引作为(私有)类成员,通过附加来存储接收的数据,直到您知道已收到完整的包。缓冲区必须足够大,以存储尽可能大的包装尺寸。



从头开始的一个非常简单的例子:

Receiving serial data is an asynchronous operation and you usually get not all data from a packet with a single event.

So you have to create at least the receive buffer and an index as (private) class members to store the received data by appending until you know that a complete package has been received. The buffer must be large enough to store the largest possible package size.

A very simple example from scratch:
// Private class members.
// Note that these are used by the receive handler which is executed 
//  in another thread
bool newData = false;
int rxOffset = 0;
byte[] rxBuffer = new byte[MAX_PACKAGE_LENGTH];
// To hold a package after it has been received
byte[] rxPackage = new byte[MAX_PACKAGE_LENGTH];

private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort port = (SerialPort)sender;
    int bytes = port.BytesToRead;
    port.Read(rxBuffer, rxOffset, bytes);
    rxOffset += bytes;
    // Check here if a complete package has been received
    if (HasCompletePackage())
    {
        rxBuffer.CopyTo(rxPackage, 0);
        rxOffset = 0;
        // Or signal the main thread that a new package is available
        newData = true;
    }
}

请注意,上面的内容不包括接收缓冲区溢出,检测到不完整的包(例如启动时)和锁定对共享变量的访问权限(此处) : newData rxPackage )。

Note that the above does not include additional checks like overflow of the receive buffer, detection of incomplete packages (e.g. at startup) and locking access to shared variables (here: newData and rxPackage).


调用串行数据,因为它以串行方式逐个到达,而不是作为信息的托管数据包:每个字节都可以导致单独的DataReceived事件触发。

因此将其存储在缓冲区中并处理缓冲区以决定做什么。

我从一个基本的状态机开始:等待标题,建立消息作为最低限度。

你开始等待,并在收到每个字节时对其进行处理,直到获得指示实际数据开始的代码。然后切换到构建并存储消息,直到结束 - 此时它返回等待,您可以处理已存储的整个数据块。
Serial data is called that because it arrives in a serial fashion, byte by byte instead of as a "managed packet" of information: each byte can cause a separate DataReceived event to fire.
So store it in a buffer and process the buffer to decide what to do.
I'd start with a basic state machine: "Waiting for header", "Building message" as a minimum.
You start in "Waiting", and process each byte as it is received until you get the code which indicates the start of actual data. Then you switch to "Building" and store the message until you get to the end - at which point it's back to "Waiting" and you can process the whole data block you have stored.


这篇关于解析从串口接收的数据包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆