繁体   English   中英

C#串口(接收、解码、显示)掉线问题

[英]C# serial port ( received, decode and display) droping data issues

我对所有这些 C# 的东西都很陌生,更习惯于嵌入式 C。 我正在尝试开发一个 windows 表单记录器来执行以下操作:-

  1. 从端口以状态帧 14 字节的形式接收串行数据,通常在记录开始前几秒钟。 然后以每秒 2000 次 (52kbytes/s) 的速率传输 26 字节数据帧

  2. 在记录停止后,需要对帧进行解码、检查是否有效、提取样本计数器并从帧中提取四个 8 位 ADC 通道以导出到 csv。

  3. 在 GUI 中绘制一个 ADC 通道。

我正在使用以下方法:

  1. 使用serialPort1_DataReceived事件读取rx data
  2. 此事件还调用解码 function 将解码数据添加到结构列表
  3. GUI 有一个计时器,它从结构列表中读取数据到图表中的 plot。
  4. ADC 通道为 10ksps,因此每 10 个样本绘制一次(显示 1ksps)

我希望看到绘制的测试信号的分辨率降低,但缺少部分。
看起来程序在解码和显示其数据接收事件时正在丢弃字节。 它有更好的方法吗?


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                                                           
}

我已将上述事件更新为下面的事件,它有所改进,但我仍然每 1 秒或 10,000 个样本出现故障/轻微丢失数据?

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();
}  

私人无效serialPort1_DataReceived(对象发送者,SerialDataReceivedEventArgs e)

{

int num_bytes;

byte[] ecu_status = new byte[140];

byte[] ecu_data = new byte[4082];

num_bytes = serialPort1.BytesToRead;                  // Console.WriteLine(num_bytes); 

// status 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 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                                                           

}

移动到内存流而不是队列大大减少了数据丢失问题。 最坏的情况是,如果串行接收 1.99 个数据帧并排队,则只有 1 帧被解码(50% 的数据丢失)。

现在不断从 memory stream 中获取 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
            }
        }


暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM