【问题标题】:C# .Net Serial DataReceived Event response too slow for high-rate dataC# .Net Serial DataReceived 事件响应对于高速数据来说太慢了
【发布时间】:2010-06-01 06:58:00
【问题描述】:

我在 VS2008 express 中设置了一个基于表单的程序的 SerialDataReceivedEventHandler。我的串口设置如下:

115200, 8N1

已启用 Dtr 和 Rts

ReceivedBytesThreshold = 1

我有一个通过蓝牙、USB 转串口连接的设备。超级终端以任何数据速率接收数据都很好。数据以 22 字节长的数据包定期发送。该设备具有可调节的数据发送速率。在 10-20Hz 的低数据速率下,下面的代码运行良好,没有问题。但是,当我将数据速率提高到 25Hz 以上时,一个呼叫开始接收多个数据包。我的意思是每个传入的数据包都应该有一个事件触发器。使用更高的输出速率,我在调用事件时立即测试了缓冲区大小(BytesToRead 命令),然后缓冲区中有多个数据包。我认为事件触发得很慢,当它到达代码时,更多的包已经到达缓冲区。我做的一项测试是查看每秒触发事件的次数。在 10Hz 时,我得到 10 个事件触发器,太棒了。在 100Hz 时,我得到了 40 个事件触发器,并不好。我的数据速率目标是可以接受 100Hz,首选 200Hz,最佳 300Hz。这应该可以工作,因为即使在 300Hz 下,也只有 52800bps,不到设置的 115200 波特率的一半。有什么我在看的吗?

    public Form1()
    {
        InitializeComponent();
        serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);            
    }


    private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        this.Invoke(new EventHandler(Display_Results));
    }


    private void Display_Results(object s, EventArgs e)
    {
        serialPort1.Read(IMU, 0, serial_Port1.BytesToRead);
    }

【问题讨论】:

    标签: c# .net events serial-port baud-rate


    【解决方案1】:

    您是否尝试调整 USB 串行转换器的时间延迟?我在使用 FTDI USB 到串行转换器时遇到了同样的问题。我使用示波器查看来自设备的 IN 和 OUT 数据,我可以看到计算机总是响应缓慢。默认情况下,设备上的时间延迟设置为 16 毫秒。我将其更改为 2 毫秒,这有很大的不同。转到设备管理器中的 USB 串行转换器,然后在高级设置中,将延迟时间更改为 2 毫秒。它应该有效。试试看。

    【讨论】:

    • 知道为什么“16 毫秒”延迟会在收到的数据束之间转换为数百毫秒吗?
    【解决方案2】:

    为什么 Invoke() 调用 DisplayResults?

    这会将它推送到 MessageLoop,这是一个不必要的延迟。

    如果 DataReceived() 将数据推送到(线程安全)队列以进行解耦处理会更好。

    我还认为您可能会遇到拆分包的问题。

    【讨论】:

    • 我尝试删除 Invoke() 调用并直接在 DataReceived() 事件中读取数据,结果相同。抱歉有点天真,但你能告诉我更多关于你如何做队列以及为什么它工作得更快的更多信息。感谢您的帮助。
    【解决方案3】:

    问题在于接收到的数据处理程序。

    我用while(true) 循环和serial.ReadLine() 运行了一个单独的线程,一切正常。

    using System.Threading;
    
    Thread readThread = new Thread(Read);
    readThread.Start();
    

    希望其他人不需要花费 3 个小时来解决这个问题。

    【讨论】:

      【解决方案4】:

      可以尝试设置 ReceivedBytesThreshold = 22,这将导致在至少有 22 个字节要读取时触发事件。请注意,它将是至少 22。可能还有更多。

      但我个人认为我不会这样做,因为如果将来您的数据包大小发生变化(例如更改为 12 字节)会发生什么?您最终会在缓冲区中有 12 个字节,但根本不会触发事件。

      最好将其设置为 1,这将在 至少 1 个字节可用时触发事件。然后将所有接收到的字节推送到 Henk 已经发布的列表或队列中。

      请注意,DataReceivedEvent 当然不知道您认为数据包是什么。它只是在有可用字节时触发。由开发人员将这些字节组合成有意义的消息或数据包。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-23
        • 2020-08-08
        • 1970-01-01
        • 2016-05-28
        • 1970-01-01
        • 1970-01-01
        • 2011-01-25
        • 2016-05-15
        相关资源
        最近更新 更多