USB 직렬 어댑터 (FTDI FT232H)를 사용하여 높은 전송 속도 (8 MegaBaud)로 마이크로 컨트롤러에서 이진 데이터를 읽는 C# 어플리케이션을 구현 중입니다. 문제는 스트림에 0x1A가 포함되어 있으며이 바이트 다음에 큰 데이터 청크 (수천 바이트)가 손실되는 경우입니다.SerialPort는 데이터가 높은 통신 속도로 손실되면 0x1A를 포함합니다.
포럼에서 0x1A가 특수 문자 (EOFCHAR)이고 Windows에서이 작업을 특별하게 처리하고 있음을 발견했습니다. 그러나 SerialStream
을 디 컴파일하고 EOFCHAR
을 다른 바이트 값으로 변경하면 this solution이 도움이되지 않습니다. 전체 바이트 범위 (0..255)를 사용해야합니다.
using System;
using System.IO.Ports;
using System.Collections.Generic;
using System.Text;
namespace SerialPort_0x1A_Loss_Test
{
class Program
{
static void Main(string[] args)
{
const byte BYTE_FILL = 0x1A; // 0x1A is EOFCHAR
const int BAUD_RATE = 3000000; // 3 MegaBaud
const int BUFF_SIZE = 1000000;
SerialPort sp1_FT232R =
new SerialPort("COM3", BAUD_RATE, Parity.None, 8, StopBits.One);
SerialPort sp2_FT232H =
new SerialPort("COM6", BAUD_RATE, Parity.None, 8, StopBits.One);
sp1_FT232R.Encoding = Encoding.GetEncoding(1252);
sp1_FT232R.WriteBufferSize = 20000000;
sp1_FT232R.Open();
sp2_FT232H.Encoding = Encoding.GetEncoding(1252);
sp2_FT232H.ReadBufferSize = 20000000;
sp2_FT232H.ReceivedBytesThreshold = 20000000;
sp2_FT232H.Open();
byte[] bufferTx = new byte[BUFF_SIZE];
for (int i = 0; i < BUFF_SIZE; i++)
{
bufferTx[i] = BYTE_FILL;
}
Console.WriteLine("Sending ...");
sp1_FT232R.Write(bufferTx, 0, BUFF_SIZE);
Console.WriteLine("Sending finished. " +
"Press a key to view status, ESC to exit.");
// Receiving maybe not yet finished,
// query the status with a keypress
while (Console.ReadKey(true).Key != ConsoleKey.Escape)
{
Console.WriteLine("TOTAL RX = " + sp2_FT232H.BytesToRead);
}
// A second test, using .Read() call
// This will be executed after pressing ESC for the previous test
int totalRX_Read_Call = 0;
var listBufferRx = new List<byte>();
int btr; // BytesToRead
while ((btr = sp2_FT232H.BytesToRead) > 0)
{
var bufferRx = new byte[btr];
totalRX_Read_Call += sp2_FT232H.Read(bufferRx, 0, btr);
listBufferRx.AddRange(bufferRx);
Console.WriteLine("totalRX_Read_Call = " + totalRX_Read_Call +
"; listBufferRx.Count = " + listBufferRx.Count);
}
Console.ReadKey();
sp1_FT232R.Close();
sp2_FT232H.Close();
}
}
}
테스트 결과 (BUFF_SIZE 연결된 = 1000000) 모든 시험 : 2, 3, 4, 그러나 낮은 같은 시험에도
1. BYTE_FILL = 0x55; BAUD_RATE = 3000000; TOTAL RX = 1000000 (no loss)
2. BYTE_FILL = 0x1A; BAUD_RATE = 3000000; TOTAL RX = 333529 (66% loss)
3. BYTE_FILL = 0x1A; BAUD_RATE = 2000000; TOTAL RX = 627222 (37% loss)
4. BYTE_FILL = 0x1A; BAUD_RATE = 1000000; TOTAL RX = 1000000 (no loss)
의 CPU의 부하 (i7-4770k 4 GHz에서) 높은 (30 % 이상이다) (3 %) 테스트 1에 대한, 나는 다른 모든 패턴을 바이트 (0x00..0x19, 0x1B..0xFF)로 시도했지만 손실이 없다. .
해결 방법이 있습니까? 대단히 감사합니다!
이 테스트는 의미가 없다 실제로는 Read()를 호출하지 마십시오. 하나의 Read() 호출로 모든 데이터를 거의 얻지는 못합니다. 수신 버퍼에있는 모든 것입니다. 0x1a 바이트가 포함되면 더 적습니다. DataReceived 이벤트를 사용하는 경우 e.EventType 속성을 무시하지 않아야합니다. –
@HansPassant 답장을 보내 주셔서 감사합니다. 내 질문의 코드를 편집하고 Read()로 테스트를 추가했으며 그 결과는 같습니다. 또한, 내 응용 프로그램에서는 DataReceived 이벤트를 사용하고'e.EventType == SerialData.Eof'를 반환하려고했지만 0x1A 데이터 손실 문제는 해결되지 않았습니다. 8 MBaud에서 0x1A 만 보낼 때 전송하는 것의 약 5 % 만 수신합니다. – nnn
나는 어떤 것들이 문제가 있는지보기 위해 모든 8 비트 패턴으로 이것을 시도 할 것이다. * 단지 * 1A라면 소프트웨어 문제 일 수 있습니다. 그렇지 않으면 아마 하드웨어가 그것을 처리 할 수 없을 것입니다. – Gabe