C#串行端口(接收、解码和显示)丢弃数据问题
我对所有这些C#东西都很陌生,更习惯于嵌入式C。 我正在尝试开发一个windows窗体记录器以执行以下操作:-C#串行端口(接收、解码和显示)丢弃数据问题,c#,winforms,logging,serial-port,decode,C#,Winforms,Logging,Serial Port,Decode,我对所有这些C#东西都很陌生,更习惯于嵌入式C。 我正在尝试开发一个windows窗体记录器以执行以下操作:- 以状态帧14字节的形式从端口接收串行数据,通常在日志记录开始前几秒钟。然后以每秒2000次(52kbytes/s)的速率传输26字节的数据帧 需要解码帧,检查是否有效,提取采样计数器,并从帧中提取四个8位ADC通道,以便在停止记录后导出到csv 在GUI中绘制一个ADC通道的图形 我采用以下方法: 使用serialPort1\u DataReceived事件读取rx数据 此事件还调用解
serialPort1\u DataReceived
事件读取rx数据
李>
当程序在解码和显示其接收到的数据事件时,看起来像是在丢弃字节。有更好的方法吗
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int num_bytes;
byte[] ecu_status = new byte[140];
num_bytes = serialPort1.BytesToRead;
// Console.WriteLine(num_bytes);
// status frames muliples of 14 bytes
if (num_bytes % 14 == 0 && num_bytes < 140 && _start_log_flag == false)
{
serialPort1.Read(ecu_status, 0, num_bytes);
decode_status(ecu_status, num_bytes);
}
else if (num_bytes > 25) // data frames 26 bytes
{
byte[] ecu_data = new byte[num_bytes];
serialPort1.Read(ecu_data, 0, num_bytes);
decode_data(ecu_data, num_bytes);
_start_log_flag = true;
}
else serialPort1.DiscardInBuffer(); // corupt clear buffer
}
私有void serialPort1_DataReceived(对象发送方,SerialDataReceivedEventArgs e)
{
int num_字节;
字节[]ecu_状态=新字节[140];
num_bytes=serialPort1.BytesToRead;
//Console.WriteLine(num_字节);
//14字节的多个状态帧
if(num_bytes%14==0&&num_bytes<140&&num_start_log_flag==false)
{
serialPort1.Read(ecu_状态,0,num_字节);
解码_状态(ecu_状态,num_字节);
}
else if(num_bytes>25)//数据帧26字节
{
字节[]ecu_数据=新字节[num_字节];
serialPort1.Read(ecu_数据,0,num_字节);
解码_数据(ecu_数据,num_字节);
_开始日志标志=true;
}
else serialPort1.DiscardInBuffer();//清除缓冲区
}
我已经将上面的事件更新为下面的内容,它改进了一些东西,但我仍然会发现每1秒或10000个样本中就有一个小故障/轻微的数据丢失
private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) // Receive data event callback
{
//stopwatch.Stop(); // Stop timing.
// Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed); // Write result.
int no_bytes;
no_bytes = sp.BytesToRead; // get num bytes from serial port buffer
if ((no_bytes == 14 || no_bytes == 28) && !_start_log_flag) // check if status frame\s (14 bytes each) once logging ignore status frames
{
byte[] _rx_data = new byte[no_bytes]; // create array for data
sp.Read(_rx_data, 0, no_bytes); // get status frame\s from serial buffer
decode_status(_rx_data, no_bytes); // decode & process status frame\s
}
else if ((no_bytes == 26 || (no_bytes > 51 && no_bytes < 4097)) && _live_stream) // check for data frames (26 bytes each)
{
_start_log_flag = true; // now logging
Console.WriteLine(no_bytes);
byte[] _rx_data1 = new byte[no_bytes]; // create array for data
sp.Read(_rx_data1, 0, no_bytes); // get data frames from comms buffer
data_frames.Enqueue(_rx_data1); // queue array to process later
}
else
{
sp.DiscardInBuffer(); // jibberish clear buffer
}
// stopwatch.Reset();
// stopwatch.Start();
}
private void sp_DataReceived(对象发送方,SerialDataReceivedEventArgs e)//接收数据事件回调
{
//stopwatch.Stop();//停止计时。
//WriteLine(“经过的时间:{0}”,stopwatch.appeased);//写入结果。
int无字节;
no_bytes=sp.BytesToRead;//从串行端口缓冲区获取num字节
if((无字节==14 | |无字节==28)和&&!_start_log_标志)//检查状态帧(每个14字节)是否在记录后忽略状态帧
{
byte[]_rx_data=新字节[no_bytes];//为数据创建数组
sp.Read(_rx_data,0,无字节);//从串行缓冲区获取状态帧
解码状态(_rx_数据,无字节);//解码和处理状态帧\s
}
else if((无字节==26 | |(无字节>51&&无字节<4097))&&&&u live_流)//检查数据帧(每个26字节)
{
_start\u log\u flag=true;//现在记录
Console.WriteLine(无字节);
byte[]_rx_data1=新字节[no_bytes];//为数据创建数组
sp.Read(_rx_data1,0,无字节);//从comms缓冲区获取数据帧
data_frames.Enqueue(_rx_data1);//队列数组以供以后处理
}
其他的
{
sp.DiscardInBuffer();//jibberish清除缓冲区
}
//秒表复位();
//秒表。开始();
}
移动到内存流而不是队列大大减少了数据丢失问题。最坏情况是,如果串行接收1.99个数据帧并排队,则仅解码1个帧(50%的数据丢失)
现在不断地从内存流中提取400.99帧并解码400帧(0.25%的数据丢失)。不完美,但更好
private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) // Receive data event callback
{
int no_bytes;
no_bytes = sp.BytesToRead; // get num bytes from serial port buffer
if ((no_bytes == 14 || no_bytes == 28) && !_start_log_flag) // check if status frame\s (14 bytes each) once logging ignore status frames
{
byte[] _rx_data = new byte[no_bytes]; // create array for data
sp.Read(_rx_data, 0, no_bytes); // get status frame\s from serial buffer
decode_status(_rx_data, no_bytes); // decode & process status frame\s
}
else if ((no_bytes > 25 && no_bytes < 4097) && _live_stream) // check for data frames (26 bytes each)
{
_start_log_flag = true; // now logging
byte[] _rx_data1 = new byte[no_bytes]; // create array for data
int temp = sp.Read(_rx_data1, 0, no_bytes); // read data frames from comms buffer
ms.Seek(0, SeekOrigin.End); // ensure orign at the end of memory stream
ms.Write(_rx_data1, 0, _rx_data1.Length); // add data to memory stream
}
else
{
sp.DiscardInBuffer(); // jibberish clear buffer
}
}
私有void sp_DataReceived(对象发送方,SerialDataReceivedEventArgs e)//接收数据事件回调
{
int无字节;
no_bytes=sp.BytesToRead;//从串行端口缓冲区获取num字节
if((无字节==14 | |无字节==28)和&&!_start_log_标志)//检查状态帧(每个14字节)是否在记录后忽略状态帧
{
byte[]_rx_data=新字节[no_bytes];//为数据创建数组
sp.Read(_rx_data,0,无字节);//从串行缓冲区获取状态帧
解码状态(_rx_数据,无字节);//解码和处理状态帧\s
}
else if((无字节>25&&无字节<4097)&&&&&&实时流)//检查数据帧