我正在从发送启动命令后连续发送数据的串行端口读取数据。我正在使用1408000的极高波特率和2000的采样率。我必须以以下方式处理传入的数据:2个开始字节(0xAA,0x55),然后是68个字节的实际数据。 在Win 7中运行程序不是问题,但是在Win 10中运行它会导致某些字节丢失-有时我会得到例如只有20个字节的数据,有时我会得到72个(总是更改值)。我想念什么吗?
这是我的代码:
SerialPort m_serialPort = new System.IO.Ports.SerialPort("COM8");
private static System.Timers.Timer timer = new System.Timers.Timer();
private static ConcurrentQueue<List<byte>> incomingdataQueue = new ConcurrentQueue<List<byte>>();
private static readonly ReaderWriterLockSlim locker = new ReaderWriterLockSlim();
static bool isProcessing = false;
private static List<byte> sampleData = new List<byte>();
public Form1()
{
InitializeComponent();
timer.Interval = 250;//250ms
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
m_serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
SetComConnectParam("COM8");
if (!ComOpen()){UpdateStatus("Problem!\n");}
init_System(gain, sample, trigger); // sends a signal to the port to init the system
UpdateStatus("start data recording " + DateTime.Now.ToString());
Start_Data(); // sends a signal to the port to start data processing
timer.Start();
}
public void SetComConnectParam(string portName, int baudRate = 1408000)
{
m_serialPort.PortName = portName;
m_serialPort.BaudRate = baudRate;
m_serialPort.Parity = Parity.None;
m_serialPort.DataBits = 8;
m_serialPort.StopBits = StopBits.One;
}
private bool ComOpen()
{
// Closing serial port if it is open
if (m_serialPort != null && m_serialPort.IsOpen){m_serialPort.Close();}
if (false == m_serialPort.IsOpen)
{
try
{
m_serialPort.Open();
m_serialPort.DiscardInBuffer();
}
catch { return false; }
}
return true;
}
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort comport = sender as SerialPort;
if (comport == null || comport.BytesToRead == 0 || !comport.IsOpen) { return; }
int dataLength = comport.BytesToRead;
byte[] buffer = new byte[dataLength];
int nbrDataRead = comport.Read(buffer, 0, dataLength);
if (nbrDataRead == 0) { return; }
incomingdataQueue.Enqueue(buffer.Take(nbrDataRead).ToList());
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (incomingdataQueue.Count == 0) { return; }
ProcessData();
}
private void ProcessData()
{
int byteperdatasample = 68;
if (incomingdataQueue.Count == 0) { return; }
if (!locker.TryEnterWriteLock(100)) { return; }
if (isProcessing)
{
locker.ExitWriteLock();
return;
}
isProcessing = true;
List<byte> currentData = new List<byte>();
while (incomingdataQueue.Count > 0)
{
incomingdataQueue.TryDequeue(out currentData);
for (int i = 0; i < currentData.Count; i++)
{
// problem: startseq is 0xAA, 0x55. 0xAA might be last entry in currentData list and 0x55 might be first entry in next data list
if (i == currentData.Count - 1 && currentData[i].Equals(170)) { startIndex = -99; startFound = false; }
if (i == 0 && currentData[i].Equals(85))
{
if (startIndex.Equals(-99)){startFound = true;}
else{startFound = false;}
}
if (i < currentData.Count - 1 && currentData[i].Equals(170) && currentData[i + 1].Equals(85))
{
startFound = true;
startIndex = i;
}
if (startFound)
{
if (startIndex == -99){sampleData.RemoveAt(sampleData.Count - 1);}//remove latest item (first start item 0xaa was added in last currentData list)
if (sampleData.Count == byteperdatasample)//
{
/* whole block of data processing */
}
else{//error}
else
{
if (i != startIndex + 1){sampleData.Add(currentData[i]);}
}
}
}
isProcessing = false;
locker.ExitWriteLock();
}
private void ButtonStop_Click(object sender, EventArgs e)
{
Stop_Data();
timer.Stop();
}
答案 0 :(得分:0)
可以尝试不使用计时器 如果(incomingdataQueue.Count == 0){return; } Task.Run(()=> ProcessData());在DataReceivedHandler处理程序中。
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort comport = sender as SerialPort;
if (comport == null || comport.BytesToRead == 0 || !comport.IsOpen) { return; }
int dataLength = comport.BytesToRead;
byte[] buffer = new byte[dataLength];
int nbrDataRead = comport.Read(buffer, 0, dataLength);
if (nbrDataRead == 0) { return; }
incomingdataQueue.Enqueue(buffer.Take(nbrDataRead).ToList());
if (incomingdataQueue.Count > 0) {
Task.Run(()=>ProcessData());
}
}