C#分割帧中的SerialPort通信 [英] SerialPort communication in C# splitting frames

查看:134
本文介绍了C#分割帧中的SerialPort通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要编写一个程序,通过 RS485 监听 ModBus 网络中的通信.我使用 RS485 <> USB 加密狗连接到网络.

I need to write a program, that will listen to communication in ModBus network through RS485. I am connected to the network with RS485 <> USB dongle.

我可以使用 SerialPort.DataReceived 事件读取一些数据,但它给出了奇怪的结果.数据通常是拆分的,而它应该是一体的.(Modbus 主站每 100 毫秒传输一次).

I can read some data using SerialPort.DataReceived event, but it gives strange results. Data is often split, when it should come in one piece. (Modbus Master transmits every 100ms).

class Serial
{
    private SerialPort port;
    Queue<byte[]> buffer;

    public Serial()
    {
        buffer = new Queue<byte[]>();
        port = new SerialPort("COM3", 19200, Parity.Even, 8, StopBits.One);
        port.DataReceived += port_DataReceived;
    }

    public void Open()
    {
        if (port.IsOpen)
        {
            port.Close();
        }

        port.Open();
    }

    void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        byte[] buff = new byte[port.BytesToRead];
        port.Read(buff, 0, port.BytesToRead);
        buffer.Enqueue(buff);
    }
}

我在传输中没有任何启动标志.帧之间的延迟是最小值.3.5 个字符,字符之间的最大延迟为 1.5 个字符.

I don't have any start sign in transmission. Delay between frames is min. 3.5 chars, and max delay between chars is 1.5 chars.

推荐答案

这完全正常,串口是很慢的设备.一旦接收到一个字节,就会触发 DataReceived 事件.您需要调用 Read() 并注意它返回的值,它能够从输入缓冲区检索的字节数.这可能不止一个,但很少等于数据包"中的字节数,只有在机器由于某种原因变得非常慢时才会发生这种情况.

This is entirely normal, serial ports are very slow devices. The DataReceived event is fired as soon as one byte was received. You'll need to call Read() and pay attention to the value it returns, the number of bytes it was able to retrieve from the input buffer. Which might be more than one but is only very rarely equal to the number of bytes in a "packet", that could only happen if the machine got very slow for some reason.

请注意,调试器是一种使其变慢的方法,断点或单步执行事件处理程序代码可为驱动程序提供足够的时间来接收数据包中的所有字节.以便 Read() 调用将它们全部返回.但是一旦您停止调试该代码,它就会停止工作.

Beware that the debugger is one way to make it that slow, a breakpoint or single-stepping the event handler code gives the driver enough time to receive all the bytes in a packet. So that the Read() call returns them all. But that stops working as soon as you stop debugging that code.

您可以使用 ReceivedBytesThreshold 属性来延迟事件,但这只能在数据包具有固定大小时起作用.只需使用 Read() 调用的第二个参数将您获得的字节附加到 byte[] 中.并且在获得所有数据包之前不要处理数据包.

You could use the ReceivedBytesThreshold property to delay the event but that can only work when a packet has a fixed size. Simply append the bytes you get into byte[], using the 2nd argument of the Read() call. And don't process the packet until you have them all.

这篇关于C#分割帧中的SerialPort通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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