2010-03-22 3 views
5

직렬 인터페이스를 통해 연결하려는 장치가 두 개 있지만 호환되지 않는 연결이 있습니다. 이 문제를 해결하기 위해 필자는 PC에 연결했고 COM 포트 X에서 COM 포트 Y로 트래픽을 라우팅하는 C# 프로그램을 만들고 있습니다.C# SerialPort - 다른 보드 속도로 포트를 혼합 할 때의 문제

프로그램이 두 개의 COM 포트에 연결됩니다. 데이터 수신 이벤트 핸들러에서 들어오는 데이터를 읽고 다른 COM 포트에 씁니다. 나가는 COM 포트가 들어오는 COM 포트보다 더 높은 전송 속도로 작동으로

private void HandleDataReceived(SerialPort inPort, SerialPort outPort) 
    { 
     byte[] data = new byte[1]; 

     while (inPort.BytesToRead > 0) 
     { 
      // Read the data 
      data[0] = (byte)inPort.ReadByte(); 

      // Write the data 
      if (outPort.IsOpen) 
      { 
       outPort.Write(data, 0, 1); 
      } 
     } 
    } 

는 그 코드가 한 괜찮 았는데 이렇게하려면, 나는 다음과 같은 코드가 있습니다. 들어오는 COM 포트가 나가는 COM 포트보다 빠르면 데이터가 손실되기 시작했습니다. 나는 다음과 같은 코드를 수정해야만했다 :

private void HandleDataReceived(SerialPort inPort, SerialPort outPort) 
    { 
     byte[] data = new byte[1]; 

     while (inPort.BytesToRead > 0) 
     { 
      // Read the data 
      data[0] = (byte)inPort.ReadByte(); 

      // Write the data 
      if (outPort.IsOpen) 
      { 
       outPort.Write(data, 0, 1); 
       while (outPort.BytesToWrite > 0); //<-- Change to fix problem 
      } 
     } 
    } 

나는 그 수정이 필요한 이유를 모르겠다. 나는 C#에 익숙하지 않다. (이것은 나의 첫번째 프로그램이다.) 그래서 나는 빠진 것이 있는지 궁금해하고있다. SerialPort의 기본값은 2048 바이트의 쓰기 버퍼이며 명령은 10 바이트 미만입니다. 쓰기 버퍼는 느린 COM 포트에 쓸 수있을 때까지 데이터를 버퍼링 할 수 있어야합니다.

요약하면 COM X에 데이터를 받고 COM Y에 데이터를 쓰고 있습니다. COM X는 COM Y보다 빠른 보오율로 연결되어 있습니다. 왜 쓰기 버퍼의 버퍼링이이 차이를 처리하지 않습니까? 데이터 손실을 피하기 위해 쓰기 버퍼가 소진 될 때까지 기다려야하는 이유는 무엇입니까?

감사합니다.

* 업데이트 *

언급 한 바와 같이,이 코드는 매우 쉽게 큰 및/또는 빠른 수신 데이터 전송에 오버 플로우 상태로 실행할 수 있습니다. 내 데이터 스트림에 대해 더 많이 작성 했어야합니다. 나는 < 10 Hz에서 10 바이트 명령 (< 10 바이트 응답)을 기대하고 있습니다. 또한 첫 번째 명령에서 오류가 표시됩니다. 이 코드는 확장 및 최적보다 작하지 않습니다 알고 동안 2-4K 심지어 첫 번째 명령을 처리 할 수 ​​/ 쓰기 버퍼를 읽을 이유

그래서, 궁금하네요. 내가 이해하지 못하는 이벤트 처리기로 데이터 또는 단일 바이트를 쓰는 버그가 있는지 궁금합니다. 감사.

는 * 업데이트 *

다음은 오류의 예 : 0x01로는 0x02은 0x3 0x4를 :

하는의 내 명령은 4 바이트입니다 가정 해 봅시다. COM X의 장치가 명령을 보냅니다. C# 프로그램이 4 바이트를 받고 COM Y의 장치로 보내는 것을 볼 수 있습니다. COM Y의 장치는 0x01 0x03의 두 바이트를받습니다. 나는 COM Y의 장치가 신뢰할 수 있다는 것을 알고 있으므로 두 바이트가 어떻게 떨어 졌는지 궁금합니다. 나는 원래의 질문을 편집 유지해야하는 경우 그런데

가, 누군가가 나를 그냥 의견에 대한 답변에 댓글을 올리려면 더 있는지 모르거나 할 수 있습니까? 어느 것이 더 도움이됩니까?

답변

0

당신은 outPort.WriteBufferSize 당신이 보낼 것으로 예상되는 가장 큰 버퍼보다 ​​큰 있는지 확인해야합니다. 또한 루프에 ReadByteWriteByte을 호출하는 것이 일반적으로 느려질 것입니다.당신이 뭔가에 핸들러를 변경하는 경우 :

int NumBytes = 20; //or whatever makes sense 
byte[] data = new byte[NumBytes]; 

while (inPort.BytesToRead > 0) 
{ 
    // Read as much data as possible at once 
    count = inPort.Read(data, 0, min(NumBytes, inPort.BytesToRead)); 

    // Write the data 
    if (outPort.IsOpen) 
    { 
     outPort.Write(data, 0, count); 
    } 
} 

이 어떤 도움이한다고, 오버 헤드를 줄일 수 있습니다. 그러면 Write 버퍼가 예상대로 타이밍을 처리합니다.

2

당신이하려고하는 것은 소방 호스에서 마시는 것과 같습니다. 물을 저장하기 위해 수신 버퍼에 의존하고 있습니다. 누군가가 탭을 끄지 않으면 오래 가지 못할 것입니다. 해결 방법을 사용하면 수신 버퍼가 자동으로 오버플로되는 것을 확인하고 있습니다. 아마도 ErrorReceived 이벤트를 구현하지 않았을 것입니다.

이 작업을하려면 버퍼가 가득 차면 송신을 중지하도록 입력 장치에 지시해야합니다. 핸드 쉐이크 속성을 설정하여이를 수행하십시오. 먼저 Handshake.RequestToSend로 설정하십시오. 다음에 XOnXOff를 사용하십시오. 핸드 쉐이크 신호를 올바르게 사용할 지 여부는 장치에 따라 다릅니다.

이 방법을 좀 더 효율적으로 사용하려면 Read() 메서드를 사용하십시오.


오케이, 소화 호스가 아닙니다. 나는 다른 가능성을 생각할 수있다. 초기 UART 칩 설계의 공통적 인 문제는 온칩 수신 버퍼가 1 바이트 만 저장할 수 있다는 점입니다. 인터럽트 서비스 루틴은 다음 바이트가 도착하기 전에 그 바이트를 읽어야했다. ISR이 충분히 빠르지 않으면 칩은 SerialError.Overrun 상태를 켜고 바이트는 영구적으로 손실됩니다.

이 문제의 해결 방법은 인위적으로 전송 된 각 바이트 사이에 지연을 넣어 장치의 ISR에 바이트를 읽는 데 더 많은 시간을주는 것이 었습니다. 부작용으로 회피 코드가하는 것은 무엇입니까?

현대적인 칩 디자인에는 8 바이트 이상의 FIFO 버퍼가 있습니다. 이것에 대한 진실이 있다면, 전송 속도를 낮추면 문제가 사라지는 것을 볼 수 있습니다. 또한 ReadByte() 대신 Read()를 사용하면 Write() 호출이 한 번에 두 개 이상의 바이트를 전송할 수 있으므로 문자 간 지연이 없어 문제가 악화됩니다. 분명히 말하면 출력 장치에 대해 말하고 있습니다.

+0

예,이 코드는 소방 호스에서 마시는 것과 같습니다. 불행히도이 코드에 연결된 호스에 대해 더 자세히 기록해야했습니다. 10Hz에서 10 바이트 미만의 명령을 보내고 있습니다. 나는 2-4K의 읽기/쓰기 버퍼가 충분하다고 생각한다. 또한 첫 번째 명령에서 오류가 표시됩니다. 따라서이 코드가 더 크고 빠른 데이터 전송으로 확장되지 않는다는 것을 알고는 있지만 왜 작고 느린 전송에서는 작동하지 않는지 궁금합니다. 더 분명하지 않은 것에 대해 유감스럽게 생각합니다. – GrandAdmiral

+0

좋아요, 일해야합니다. "나는 실패를보고 있습니다"에 대해 명시 적으로 기재하십시오. –

+0

예. 내 명령이 4 바이트라고 가정 해 보겠습니다. 0x01 0x02 0x3 0x4. COM X의 장치가 명령을 보냅니다. C# 프로그램이 4 바이트를 받고 COM Y의 장치로 보내는 것을 볼 수 있습니다. COM Y의 장치는 0x01 0x03의 두 바이트를받습니다. 나는 COM Y의 장치가 신뢰할 수 있다는 것을 알고 있으므로 두 바이트가 어떻게 떨어 졌는지 궁금합니다. – GrandAdmiral

관련 문제