Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#串行端口(接收、解码和显示)丢弃数据问题_C#_Winforms_Logging_Serial Port_Decode - Fatal编程技术网

C#串行端口(接收、解码和显示)丢弃数据问题

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数据 此事件还调用解

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

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

  • 需要解码帧,检查是否有效,提取采样计数器,并从帧中提取四个8位ADC通道,以便在停止记录后导出到csv

  • 在GUI中绘制一个ADC通道的图形

  • 我采用以下方法:

  • 使用
    serialPort1\u DataReceived
    事件读取
    rx数据
  • 此事件还调用解码函数,该函数将解码数据添加到 结构列表
  • GUI有一个计时器,可以从结构列表中读取数据以进行绘图 图表
  • 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                                                           
    }
    
    
    私有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)&&&&&&实时流)//检查数据帧