【问题标题】:C# serial port ( received, decode and display) droping data issuesC#串口(接收、解码和显示)丢弃数据问题
【发布时间】:2020-02-18 15:12:35
【问题描述】:

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

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

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

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

我正在使用以下方法:

  1. 使用serialPort1_DataReceived 事件读取rx data
  2. 此事件还调用解码函数,将解码后的数据添加到 结构列表
  3. GUI 有一个计时器,可以从结构列表中读取数据以进行绘图 图表。
  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();
}  

【问题讨论】:

  • 欢迎来到 SO。请阅读How to Asktourminimal reproducible example 以改进您的问题
  • 我的猜测是你在事件中读取数据错误并且没有完全读取缓冲区中的每个字节,但是没有代码很难说你做错了什么。
  • c# 是最好的方法吗?开销可能会影响数据。
  • 你能添加你的serialPort1_DataReceived事件代码吗?
  • 这不是一个论坛,它是一个问答网站。请编辑您的问题以包含此信息,然后删除此答案 - Scott Chamberlain 17 小时前

标签: c# winforms logging serial-port decode


【解决方案1】:

移动到内存流而不是队列大大减少了数据丢失问题。最坏的情况是,如果串行接收 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
            }
        }


【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 2018-04-17
    • 2011-06-01
    • 1970-01-01
    相关资源
    最近更新 更多