0

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

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

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 个字符。

4

1 回答 1

2

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

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

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

于 2012-11-16T14:14:56.157 回答