我正在开发一个与FPGA设备对话的winforms应用程序。由于设备仍在开发中,我正在尝试使用com0com(http://com0com.sourceforge.net/)和另一个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个字节是标头,第四个字节包含要遵循的字节数。在这种情况下,40 = 0x28。 API规范中没有终止值。以下是我处理DataRecieved事件的方法:
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#经验,我很难理解如何做到这一点。
任何建议都将不胜感激。
答案 0 :(得分:4)
您需要一台状态机来跟踪您在接收消息方面取得的进展。这看起来像这样:
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..
}