C# 多次接收到串行端口数据

C# 多次接收到串行端口数据,c#,winforms,serial-port,C#,Winforms,Serial Port,我正在开发一个winforms应用程序,它可以与FPGA设备通信。由于该设备仍在开发中,我尝试使用com0com()和另一个winforms应用程序作为模拟器来模拟它 我正在从我的应用程序向模拟器发送一个44字节的字节数组: CC AA 01 28 09 2A 0C 00 01 FF 00 FA 02 FF 01 5E 03 FF 01 C2 04 FF 02 26 05 FF 02 8A 06 FF 02 EE 07 FF 03 52 08 FF 03 B6 09 FF 04 1A 前4个字节

我正在开发一个winforms应用程序,它可以与FPGA设备通信。由于该设备仍在开发中,我尝试使用com0com()和另一个winforms应用程序作为模拟器来模拟它

我正在从我的应用程序向模拟器发送一个44字节的字节数组:

CC AA 01 28 09 2A 0C 00 01 FF 00 FA 02 FF 01 5E 03 FF 01 C2 04 FF 02 26 05 FF 02 8A 06 FF 02 EE 07 FF 03 52 08 FF 03 B6 09 FF 04 1A

前4个字节是标头,第4个字节包含要跟随的字节数。在这种情况下,40=0x28。API规范中没有终止值。以下是我如何处理DataReceived事件:

void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    int byte_count = 0;
    int read_count = 0;
    while (comPort.BytesToRead > 0)
    {
        byte_count = comPort.BytesToRead;
        byte[] byteTemp = new byte[byte_count];
        read_count = comPort.Read(byteTemp, 0, byte_count);
    }
    byte[] byteBuffer = new byte[read_count];
    int intNumBytes2read = byteBuffer[3];

    // do other stuff
}
我的问题是,当事件触发时,模拟器并不总是接收整个有效负载。事实上,每次我从应用程序向模拟器发送数据时,事件通常会触发不止一次。我对这个问题的研究表明,这是一个常见的问题,我需要创建某种排队机制。以我有限的C#经验,我正在努力理解如何做到这一点


任何建议都将不胜感激。

您需要一个状态机来跟踪您在接收消息方面取得的进展。可以这样看:

private int state;
private byte[] payload;
private int payloadIndex;

private void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e) {
    while (comPort.BytesToRead > 0) {
        byte b = (byte)comPort.BaseStream.ReadByte();
        switch (state) {
            case 0: 
                if (b == 0xcc) state++;
                else protocolViolation("Bad header, expected 0xcc");
                break;
            case 1:
                if (b == 0xaa) state++;
                else protocolViolation("Bad header, expected 0xaa");
                break;
            case 2:
                if (b == 0x01) state++;
                else protocolViolation("Bad header, expected 0x01");
                break;
            case 3:
                payload = new byte[b];
                payloadIndex = 0;
                state++;
                break;
            case 4:
                payload[payloadIndex++] = b;
                if (payloadIndex == payload.Length) {
                    processPayload(payload);
                    state = 0;
                }
                break;
        }
    }
}

private void protocolViolation(string why) {
    state = 0;
    Debug.WriteLine(why);
}

private void processPayload(byte[] payload) {
    // etc..
}

您需要一个状态机来跟踪您在接收消息方面取得的进展。可以这样看:

private int state;
private byte[] payload;
private int payloadIndex;

private void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e) {
    while (comPort.BytesToRead > 0) {
        byte b = (byte)comPort.BaseStream.ReadByte();
        switch (state) {
            case 0: 
                if (b == 0xcc) state++;
                else protocolViolation("Bad header, expected 0xcc");
                break;
            case 1:
                if (b == 0xaa) state++;
                else protocolViolation("Bad header, expected 0xaa");
                break;
            case 2:
                if (b == 0x01) state++;
                else protocolViolation("Bad header, expected 0x01");
                break;
            case 3:
                payload = new byte[b];
                payloadIndex = 0;
                state++;
                break;
            case 4:
                payload[payloadIndex++] = b;
                if (payloadIndex == payload.Length) {
                    processPayload(payload);
                    state = 0;
                }
                break;
        }
    }
}

private void protocolViolation(string why) {
    state = 0;
    Debug.WriteLine(why);
}

private void processPayload(byte[] payload) {
    // etc..
}