简体   繁体   English

C#.Net Serial DataReceived对于高速率数据,事件响应太慢

[英]C# .Net Serial DataReceived Event response too slow for high-rate data

I have set up a SerialDataReceivedEventHandler, with a forms based program in VS2008 express. 我已经在VS2008 express中使用基于表单的程序设置了一个SerialDataReceivedEventHandler。 My serial port is set up as follows: 我的串口设置如下:

115200, 8N1 115200,8N1

Dtr and Rts enabled Dtr和Rts启用

ReceivedBytesThreshold = 1 ReceivedBytesThreshold = 1

I have a device I am interfacing with over a BlueTooth, USB to Serial. 我有一个设备,我通过BlueTooth,USB转串口连接。 Hyper terminal receives the data just fine at any data rate. 超级终端以任何数据速率接收数据。 The data is sent regularly in 22 byte long packets. 数据以22字节长的数据包定期发送。 This device has an adjustable rate at which data is sent. 该设备具有可调节的数据发送速率。 At low data rates, 10-20Hz, the code below works great, no problems. 在低数据速率,10-20Hz,下面的代码工作得很好,没有问题。 However, when I increase the data rate past 25Hz, there starts to recieve mulitple packets on one call. 但是,当我将数据速率提高到25Hz以上时,一次呼叫就会开始收到多个数据包。 What I mean by this is that there should be a event trigger for every incoming packet. 我的意思是每个传入的数据包都应该有一个事件触发器。 With higher output rates, I have tested the buffer size (BytesToRead command) immediatly when the event is called and there are multiple packets in the buffer then. 由于输出速率较高,我在调用事件时立即测试了缓冲区大小(BytesToRead命令),然后缓冲区中有多个数据包。 I think that the event fires slowly and by the time it reaches the code, more packes have hit the buffer. 我认为事件会慢慢触发,当它到达代码时,更多的数据包已经打到了缓冲区。 One test I do is see how many time the event is trigger per second. 我做的一个测试是看每秒触发事件的次数。 At 10Hz, I get 10 event triggers, awesome. 在10Hz时,我得到10个事件触发器,真棒。 At 100Hz, I get something like 40 event triggers, not good. 在100Hz,我得到40个事件触发器,不好。 My goal for data rate is 100HZ is acceptable, 200Hz preferred, and 300Hz optimum. 我的数据速率目标是100HZ是可接受的,200Hz首选,300Hz最佳。 This should work because even at 300Hz, that is only 52800bps, less than half of the set 115200 baud rate. 这应该工作,因为即使在300Hz,这只是52800bps,不到设置的115200波特率的一半。 Anything I am over looking? 我在看什么?

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

Did you try to ajust time latency on the USB serial converter? 您是否尝试调整USB串行转换器的时间延迟? I had the same problem with a FTDI USB to serial converter. 我遇到了与FTDI USB转串口转换器相同的问题。 I use an oscilloscope to see my IN and OUT data coming from the device and I could see that the computer was always slow to respond. 我使用示波器查看来自设备的IN和OUT数据,我可以看到计算机响应总是很慢。 By default, time latency on the device is set to 16 ms. 默认情况下,设备上的时间延迟设置为16毫秒。 I changed it to 2 ms and it makes a big difference. 我将它改为2毫秒,这有很大的不同。 Go to your USB Serial Converter in the Device Manager and in the advanced settings, change Latency time to 2 ms. 在设备管理器中转到USB串行转换器,在高级设置中,将延迟时间更改为2毫秒。 It should works. 它应该有效。 Try it. 试试吧。

Why do you Invoke() the call to DisplayResults? 你为什么调用()调用DisplayResults?

This will push it to the MessageLoop, an unnecessary delay. 这会将它推送到MessageLoop,这是一个不必要的延迟。

It would be better if DataReceived() pushed data onto a (thread-safe) queue for decoupled processing. 如果DataReceived()将数据推送到(线程安全的)队列以进行解耦处理,那会更好。

I also think you could run into problems with split packages. 我也认为你可能遇到拆分包的问题。

The problem lies in the received data handler. 问题在于收到的数据处理程序。

I ran a separate thread with a while(true) loop and serial.ReadLine() , all works perfectly. 我使用while(true)循环和serial.ReadLine()运行了一个单独的线程,一切都很完美。

using System.Threading;

Thread readThread = new Thread(Read);
readThread.Start();

Hope someone else doesn't need to spend 3 hours fixing this. 希望别人不需要花3个小时来解决这个问题。

You could try setting ReceivedBytesThreshold = 22 , which will result in the event being fired when there are at least 22 bytes to read. 可以尝试设置ReceivedBytesThreshold = 22 ,这将导致在至少有22个字节要读取时触发事件。 Note that it will be at least 22. There may be more. 请注意,它至少是 22.可能会有更多。

I don't think I would personally do this though, because what happens if your packet size changes in the future, for example to 12 bytes? 我不认为我会亲自这样做,因为如果您的数据包大小在未来发生变化会发生什么,例如12个字节? You would end up with 12 bytes in the buffer but not firing the event at all. 您最终会在缓冲区中使用12个字节,但根本不会触发事件。

Far better to leave it set to 1, which will fire the event when at least 1 byte is available. 最好将它设置为1,这将在至少 1个字节可用时触发事件。 Then push all received bytes into a list or a queue as Henk has already posted. 然后将所有收到的字节推送到Henk已发布的列表或队列中。

Note that the DataReceivedEvent has no knowledge of what you consider a packet of data to be of course. 请注意,DataReceivedEvent当然不知道您认为数据包的内容。 It just fires when there are bytes available. 它只是在有可用字节时触发。 It is up to the developer to assemble these bytes into a meaningful message or packet. 由开发人员将这些字节组装成有意义的消息或数据包。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM