2014-11-24 82 views
1

我正在開發一個與FPGA器件對話的Winforms應用程序。由於該設備仍在開發中,我試圖使用com0com(http://com0com.sourceforge.net/)和另一個winforms應用程序作爲模擬器來模擬它。串行端口DataReceived多次觸發

我送的44個字節的字節數組從我的應用程序到模擬器:

CC AA 01 28 09 0C 2A 00 01 FF 00 02 FA 01 FF 03 5E FF 01 04 C2 02 FF 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規範中沒有終止值。下面是我如何處理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#經驗,我正在努力理解如何做到這一點。

任何建議,將不勝感激。

回答

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.. 
} 
+0

謝謝漢斯!那正是我需要的...... – cce1911 2014-11-24 19:43:33