C# 串行端口 ReadLine 与 ReadExisting 或如何正确从串行端口读取数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/636758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 11:13:14  来源:igfitidea点击:

Serial Port ReadLine vs ReadExisting or how to read the data from serial port properly

c#compact-frameworkserial-portwindows-ce

提问by sarsnake

I am reading data from serial port. The data comes off the scale. I am now using Readline()and getting data dropped even after I removed DiscardInBuffer().

我正在从串口读取数据。数据超出了规模。我现在使用Readline()和获取数据下降,我删除后也DiscardInBuffer()

What is the proper way to read the data from the serial port? There are so few examples online that I feel it's like some holy grail that no one has figured out.

从串口读取数据的正确方法是什么?网上的例子太少了,我觉得这就像一些没有人想出的圣杯。

C#, WinCE 5.0, HP thin client, Compact framework 2.0

C#、WinCE 5.0、HP 瘦客户端、Compact framework 2.0

 private void WeighSample()
    {
        this._processingDone = false;
        this._workerThread = new Thread(CaptureWeight);
        this._workerThread.IsBackground = true;
        this._workerThread.Start();
    } //end of WeighSample()


    private void CaptureWeight()
    {
         globalCounter++;
         string value = "";


          while (!this._processingDone)
          {
              try
              {

                 value = this._sp.ReadLine();

                  if (value != "")
                  {
                      if (value == "ES")
                      {
                          _sp.DiscardInBuffer();
                          value = "";
                      }
                      else
                      {
                          this.Invoke(this.OnDataAcquiredEvent, new object[] { value });
                      }
                  }
              }
              catch (TimeoutException)
              {
                  //catch it but do nothing
              }
              catch
              {
                  //reset the port here?
                  MessageBox.Show("some other than timeout exception thrown while reading serial port");
              }
          }


    } //end of CaptureWeight()

One thing to note about my application is that I start the thread (weighSample) when the cursor jumps onto the textbox. The reason to this is that the weight can also be typed in manually (part of the requirements). So I don't know in advance whether a user is going to press PRINT on the balance or type the weight. In either case after the data is acquired, I exit the worker thread. Also, note that I am not using serial port event DataReceived, since I have been told it's not reliable.

关于我的应用程序需要注意的一件事是,当光标跳到文本框上时,我启动了线程 (weighSample)。这样做的原因是重量也可以手动输入(部分要求)。所以我事先不知道用户是要按天平上的 PRINT 还是输入重量。在获取数据后的任何一种情况下,我都会退出工作线程。另外,请注意,我没有使用串行端口事件 DataReceived,因为有人告诉我它不可靠。

This is my first experience with serial ports.

这是我第一次使用串口。

采纳答案by ctacke

I have neverhad luck with ReadLine working. Just do a Read into a local buffer whenever data is available and then use a separate thread to scan the data and find line breaks yourself.

从来没有在 ReadLine 工作过运气。只需在数据可用时读取本地缓冲区,然后使用单独的线程扫描数据并自己查找换行符。

回答by joshperry

Depends on what the end-of-line (EOL) character(s) is for your input data. If your data is line oriented then ReadLine is a valid function to use, but you may want to look at the NewLine property and be sure that it is set appropriately for your input data.

取决于输入数据的行尾 (EOL) 字符是什么。如果您的数据是面向行的,那么 ReadLine 是一个可以使用的有效函数,但您可能需要查看 NewLine 属性并确保为您的输入数据正确设置了它。

For example, if your scale outputs linefeed for EOL then set port.NewLine = "\n";

例如,如果您的秤为 EOL 输出换行符,则设置 port.NewLine = "\n";

http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.newline.aspx

http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.newline.aspx

回答by Elias Santos

if (serialPort1->IsOpen){
    if (serialPort1->BytesToRead>0){
        this->textBox1->Text += serialPort1->ReadExisting();
    }
}

回答by newbie programmerz

I am adding an answer to respond to Elias Santos. There are some gotchas in using the ReadExisting method:

我正在添加一个答案来回应 Elias Santos。使用 ReadExisting 方法有一些问题:

https://msdn.microsoft.com/en-us/library/system.io.ports.serialport.readexisting(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/system.io.ports.serialport.readexisting(v=vs.110).aspx

Note that this method can leave trailing lead bytes in the internal buffer, which makes the BytesToRead value greater than zero.

请注意,此方法可能会在内部缓冲区中留下尾随前导字节,这会使 BytesToRead 值大于零。

I faced some issues with ReadExisting before and this is because of the unwanted bytes. Using Readline fixed those issues.

我之前在 ReadExisting 方面遇到过一些问题,这是因为不需要的字节。使用 Readline 解决了这些问题。