【问题标题】:Parsing the data packet received from serial port解析串口收到的数据包
【发布时间】:2018-11-13 09:13:10
【问题描述】:

我正在通过以下代码从串口获取响应。

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

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

我以块的形式接收数据,有时是 4 个字节,有时是 8 个字节。我想做的是 1.我想首先检查我在该数据包中收到的内容,例如标头 2.然后当我收到下一个数据块时,我不想检查标题,而是检查下一个信息,如日期和时间等..

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

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

谢谢。

【问题讨论】:

  • 如果有人愿意,我也可以上传硬件响应代码
  • 一般来说,它是如何工作的,当你获得整个消息时你就知道了。许多协议以<CR><LF> 结束它们的消息,你需要一些东西来让你知道你有完整的消息。你应该像你一样在DataReceivedHandler 中构建你的字符串,当你看到你有整个消息时,解析字符串以获取所有相关数据。
  • @Baddack 感谢您的回复。有没有办法使用循环缓冲区或动态数组来存储串行端口一次发送的数据,然后解析缓冲区中可用的内容和然后再次将数据放入其中,依此类推..

标签: c# visual-studio parsing serial-port


【解决方案1】:

我使用StringBuilder 来构建我的字符串。在您的情况下,您正在使用字节,也许您可​​以使用全局 byte[] 数组。下面是一个示例,其中<LF> 表示我收到了整个消息。我将字符附加到我的字符串,直到我知道我有整个消息。我快速清除缓冲区,因为您的下一个字符串可能会在您评估时进入。

StringBuilder sb = new StringBuilder();
char LF = (char)10;

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    string Data = serialPort1.ReadExisting();

    foreach (char c in Data)
    {
        if (c == LF)
        {
            sb.Append(c);

            CurrentLine = sb.ToString();
            sb.Clear();

            //do something with your response 'CurrentLine'
            Eval_String(CurrentLine);
        }
        else
        {
            sb.Append(c);
        }
    }
}

获得完整信息后,您可以根据需要对其进行评估。在我的示例中,我的消息以逗号分隔,因此我可以使用逗号作为分隔符将字符串拆分为字符串数组,并从消息中获取每个值。

public void Eval_String(string s)
{
    string[] eachParam;
    eachParam = s.Split(',');

    if (eachParam.Length == 5)
    {
        //do something
        Console.WriteLine(eachParam[2]);
    }
}

【讨论】:

  • 感谢您的回复。但是您可以对具有两个指针的循环缓冲区执行相同的操作吗?一个要写入,一个要读取。我知道在 c# 中没有提供循环缓冲区的默认实现,所以我是使用github.com/joaoportela/CircullarBuffer-CSharp
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多