串行端口BytesToRead和readbuffer

时间:2013-01-14 17:30:01

标签: c# serial-port

我试图以非常快的速度连续从串口获取数据。波特率为230400。 当我打印出数据,时间戳以及BytesToRead到文件时,我注意到只要BytesToRead下降到一个数字且readLine()没有读取任何内容,就会发生200毫秒的延迟200毫秒。延迟之后,BytesToRead会回到3000左右,这个过程会一次又一次地发生。基本上我不是在不断获取数据。

我想也许我读的速度比缓冲区中的速度数据更快,所以我尝试更改readBuffer大小并让这个线程休眠1ms,以便让缓冲区保持我正在读取的速度。他们都没有工作。还有一些延迟。

欢迎任何想法。

 private void dostuff()//The thread I created after the port is opened
    {
        var startTime = DateTime.Now;
        var stopwatch = Stopwatch.StartNew();
        while (serialPortEncoder.IsOpen)
        {
            if (serialPortEncoder.BytesToRead > 210)
            {
                try
                {
                    var line = serialPortEncoder.ReadLine();
                    var timestamp = (startTime + stopwatch.Elapsed);
                    var lineString = string.Format("{0}  ----{1}",
                                    line,
                                    timestamp.ToString("HH:mm:ss:fff") + " "+serialPortEncoder.BytesToRead+"\r\n");

                    richTextBoxEncoderData.BeginInvoke(new MethodInvoker(delegate()
                    {
                        richTextBoxEncoderData.Text = line;//update UI                           
                    }));                                     
                }
                catch (Exception ex) { MessageBox.Show(ex.ToString()); }


            }}

3 个答案:

答案 0 :(得分:2)

除非每210个字节有一个换行符,否则ReadLine()函数可能会超时并且不返回任何内容。 ReadLine()将读取输入缓冲区,直到遇到换行值,然后返回它之前的任何数据。 http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.readline.aspx

港口有什么样的信息?如果要读取特定大小的缓冲区,只需使用Read方法。如果你需要阅读直到换行,请使用ReadLine()并经常检查它是否返回一个字符串。

答案 1 :(得分:2)

您的代码存在根本性缺陷,它受到“热等待循环”错误的影响。当串行端口没有足够的数据时,您的循环正在燃烧100%核心。这将使Windows在你烧掉量子之后将你的线程放入狗屋一段时间,让其他线程有机会运行。在那个狗屋里待200毫秒有点长,但肯定并不罕见。

你应该采取不同的方式,当有可用的串口数据时,你应该让Windows有机会叫醒你。当它查找要调度的下一个线程时,它支持具有I / O完成的线程。这很容易做到,只需删除BytesToRead测试即可。 ReadLine()调用是一个阻塞调用,在收到NewLine之前不会返回。你的线程现在将消耗接近0%的cpu周期。

当机器负载过重或垃圾收集器运行时,您仍将丢失任意时间。不,这不足以可靠地读取编码器并关闭反馈回路。可靠地执行此操作需要具有可预测的实时行为的微控制器。随时可从工业电子供应商处获得。

答案 2 :(得分:0)

在对网络进行了一些无休止的研究之后,我找到了延迟的原因。设备管理器--->端口---->提前---->将延迟改为1ms将解决问题。现在,每当缓冲区降至零时,最多只需2ms即可恢复正常。我现在使用单独的线程轮询数据。它运作得很好。

但就像Hans Passant所说的那样,我正试图想出一个更好的设计方法。