C# Windows 窗体 - 解析从串口接收到的字符串 [英] C# Windows form - parsing string received from serial port

查看:167
本文介绍了C# Windows 窗体 - 解析从串口接收到的字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 C# 开发 Windows 窗体应用程序,其中我从串行端口接收数据,现在我有以下代码(这只是我的问题的相关代码):

I'm developing a Windows Form application using C#, in which I receive data from the serial port and for now I have the following code (this is just the relevant code for my problem):

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)     
{
      ReceivedData = serialPort1.ReadExisting();
      this.Invoke(new EventHandler(interp_string));       
}

private void interp_string(object sender, EventArgs e)      
{
      textReceive.Text += ReceivedData + "\n";
}

但是现在我需要将接收到的数据解析成小字符串.ReceivedData 变量是具有以下格式的多个字符串的组合:value time \n",其中 value 从 0 到 1024,时间以秒为单位(并且总是增加)并且有 4 个小数位.我需要将 ReceivedData 变量拆分为单独的值,并在相应的时间将其绘制在图表中.考虑到使用ReadExisting,可能会出现一个字符串只读取一部分,其余的只在下次触发DataReceived事件时读取,但我不介意丢失一点数据,并不重要.

But now I need to parse the received data into small string. The ReceivedData variable is a combination of multiple strings with the following format: "value time \n" where value goes from 0 to 1024 and time is in seconds (and is always increasing) and has 4 decimal places. I need to split the ReceivedData variable into individual values and it's corresponding time to plot it in a chart. Taking in account that using ReadExisting, it may happen that one string will be read only partially and the rest will only be read in the next time that the DataReceived event is triggered, but I don't mind if I lose one point of data, is not crucial.

我已经尝试使用 ReadLine 而不是 ReadExisting 并且我设法拆分每个字符串并绘制数据但是,考虑到应用程序接收的大量数据,每 1 毫秒一个字符串,应用程序无法跟上并且即使已经过去了 10 秒,该应用程序仍在从第 2 秒开始打印数据,我按下按钮停止接收数据,该应用程序会在很长一段时间内保持打印值,我认为这些值是存储在接收缓冲区中的值.更改为 ReadExisting 是我发现的唯一一种实时读取和打印所有内容的方法.

I already tried to use ReadLine instead of ReadExisting and I managed to split each string and plot the data but, given the large amount of data the app is receiving, one string per 1 ms, the app can't keep up and even though it has passed 10 seconds the app is still printing data from the 2nd second, and I press a button to stop receiving data the app keeps printing values, for a long time, that I assume are the ones stored in the receiving buffer. And changing to ReadExisting was the only method I found to read and print everything in real time.

推荐答案

DataReceived 事件可能会在字符串中间触发,您可能还没有收到完整的消息.您需要知道要查找的内容,通常是换行符 (LF) 或回车符 (CR).我使用 StringBuilder 来构建我的字符串,下面是一个示例,其中 LF 表示我得到了整个消息.我将字符附加到我的字符串,直到我知道我有完整的消息.我快速清除缓冲区,因为在您评估时您的下一个字符串可能会进入.对于这个简单的例子,我只是调用一个函数来计算我的字符串,但你可能想在这里使用一个委托.

The DataReceived event may fire in the middle of a string and you might not receive the whole message yet. You'll need to know what you're looking for, generally a Line Feed (LF) or a Carriage Return (CR). I use StringBuilder to build my strings, below is an example where LF means I got the whole message. I append characters to my string until I know I have the whole message. I clear the buffer quickly, because your next string can be coming in while you are evaluating. For this simple example, I'm just calling a function to evaluate my string, but you may want to use a delegate here.

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

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

Once you get the whole message you can evaluate it for what you need. I'm not sure what your data looks like but in my example, my message comes back comma delimited, so I can split my string into a string array using a comma as my delimiter and get each value from the message.

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

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

这是一个关于如何使用队列更新 gui 的示例.

Here is an example on how to update your gui with a queue.

StringBuilder sb = new StringBuilder();
char LF = (char)10;
Queue<string> q = new Queue<string>();

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

            q.Enqueue(currentLine);
        }
        else
        {
            sb.Append(c);
        }
    }
}

private void backgroundWorkerQ_DoWork(object sender, DoWorkEventArgs e)
{
    while (true)
    {
        if (backgroundWorkerQ.CancellationPending)
            break;

        if (q.Count > 0)
        {
            richTextBoxTerminal.AppendText(q.Dequeue());
        }

        Thread.Sleep(10);
    }
}

如果您从未使用过后台工作器,则只需创建一个新的后台工作器对象,将 supportsCancellation 设置为 true,然后为其添加一个事件 DoWork事件.然后当你启动你的表单时,你可以告诉它 .RunWorkerAsync().

If you've never worked with background worker, you'll just have to create a new backgroundworker object, set supportsCancellation to true then add a event for it's DoWork event. Then when you start up your form you can tell it to .RunWorkerAsync().

if (!backgroundWorkerQ.IsBusy)
{
    backgroundWorkerQ.RunWorkerAsync();
}

请参阅:https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker?view=netframework-4.7.2另请注意,backgroundworker 位于它自己的线程中,您很可能需要使用 BeginInvoke 它来更新您的文本框.

See: https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker?view=netframework-4.7.2 Also note that backgroundworker is in it's own thread and you will most likely need to BeginInvoke it to update your textbox.

这篇关于C# Windows 窗体 - 解析从串口接收到的字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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