2012-03-01 3 views
2

현재 Iam은 직렬 포트를 계속 읽어야하는 프로젝트에서 작업하고 있습니다. 데이터는 최대 45 분 동안 계속오고 있습니다. 체크섬을 통해 데이터의 유효성을 검사하고 79 바이트의 패킷을 만들어야합니다. 이 후 실시간으로 데이터 (탄도)를 그려야합니다. 이 코드의 문제점은 처음에는 CPU 사용량의 20 % (Pentium 4, 3.0 GHz, 하이퍼 스레딩)를 사용하지만 (시간이 지나면 CPU 사용량이 증가하고 결국에는 60 % .CPU 높은 시간 직렬 포트에 대한 시간 사용

데이터는 전송 속도 115200에서 수신되고 100msec 속도로 연속적으로 전송됩니다.

읽기에 대한 나의 코드를 확인하는 다음과 같이 플로팅는 다음 기능은 라벨의 데이터를 표시하고에 궤적을 그릴

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     try 
     { 
      header1 = serialPort1.ReadByte(); 
      if (header1 == 0) 
       header2 = serialPort1.ReadByte(); 
      if ((header1 == 0) && (header2 == 1))//Store the data in an array. 
      { 
       for (int i = 0; i < 77; i++) 
        abudata[i] = serialPort1.ReadByte(); 
       tail = abudata[76]; 
      } 
      else 
      { 
       serialPort1.DiscardInBuffer(); 
      } 
      checksum = 1;// Calculate the checksum. 
      for (i = 0; i < 74; i++) 
       checksum = checksum + (abudata[i]); 
      checksum1 = (abudata[75] << 8); 
      checksum1 = checksum1 + (abudata[74]); 

      if ((checksum == checksum1) && (tail == 4)) 
       this.Invoke(new EventHandler(Display_Results));// Function to display 
     } 
     catch (Exception ode) 
     { 
      l4[4].BackColor = Color.Red; 
     } 
    } 

다음 함수는 데이터를 수신하고이를 검증 ... 사진을 정기적으로 높은 CPU 부하를 생성하지 않습니다 그 자체로하여 SerialPort 클래스의 사용하여 해당 상자

private void Display_Results(object s, EventArgs e) 
    { 
     head1[0] = header1; 
     head1[1] = header2; 
     for (k = 0; k < 77; ++k) 
      head1[k + 2] = (((int)abudata[k]) & 0x000000ff); 
     jk = 0; 
     for (k = 0; k < 36; ++k) //Data packing into 36 bytes 
     { 
      num_1[k] = (ulong)((head1[jk + 1]) + (head1[jk] << 8)) & 0x0000ffff; 
      num_1[k] = (double)num_1[k]; 
      num_2[k] = (double)num_1[k]; 
      jk = jk + 2; 
      signbit = (int)num_1[k] >> 15; 

      if (signbit == 1) 
      { 
       sgnval = -1; 
       num_1[k] = num_1[k] - 65535; 
       num_1[k] = num_1[k] * (-1.0); 
      } 
      else 
       sgnval = 1; 

      //Converting the data into engineering values 

      engval[k] = Math.Round(num_1[k] * parammaxval[k] * sgnval/32767.0, 3); 

      if (k == 14) 
      { 
       try 
       { 

        curr_x = (pictureBox2.Width/2) + (int)((engval[13] * (pictureBox2.Width))/map_width); 
        curr_y = (pictureBox2.Height/2) - (int)((engval[14] * (pictureBox2.Height))/map_height); 
        PointF p1 = new Point(curr_x, curr_y); 
        if (_gPath != null && _gPath.PointCount > 0) 
         p1 = _gPath.PathPoints[_gPath.PathPoints.Length - 1]; 
        PointF p2 = new Point(curr_x, curr_y); 
        _gPath.AddLine(p1, p2); 
        pictureBox2.Invalidate(); 
       } 
       catch (Exception ex) 
       { 
        MessageBox.Show(ex.Message); 
       } 
      } 

     }   
    }  
+0

당신은 "C#을 직렬 포트를"무엇을 의미합니까 ... 나에게 어떻게 시스템을 저하없이 궤적을 그릴 수 있다는이 문제에 대한 솔루션을 제안 할 수 있습니다? C#에는 직렬 포트가 없습니다. –

답변

1

..

응용 프로그램이 계속 실행 나는 지금 궤적

if (k == 14) 
{ 
    try 
    { 

     curr_x = (pictureBox2.Width/2) + (int)((engval[13] * (pictureBox2.Width))/map_width); 
     curr_y = (pictureBox2.Height/2) - (int)((engval[14] * (pictureBox2.Height))/map_height); 
     PointF p1 = new Point(curr_x, curr_y); 
     if (_gPath != null && _gPath.PointCount > 0) 
      p1 = _gPath.PathPoints[_gPath.PathPoints.Length - 1]; 
     PointF p2 = new Point(curr_x, curr_y); 
     _gPath.AddLine(p1, p2); 
     pictureBox2.Invalidate(); 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
} 

음모를 꾸미고 그래프에 경로를 사용하고, 그것은 그래프 포인트를 많이 수집 따라서이 엄청난 수의 포인트를 플로팅하면 리소스가 소모됩니다.

은 아무도

4

내가 광범위하게 직렬 포트에 연결된 장치와 함께 작동하고 당신을 확신 할 수 있습니다.

FIRSTPROFILE 신청서를 제출해주십시오. .NET 용 a bunch of 프로파일 러가 있습니다.

프로파일 이후에는 전용입니다. SerialPort 읽기와 데이터 처리를 분리 할 것을 제안합니다. 프로듀서 소비자 패턴을 사용하십시오. SerialPort의 데이터를 대기열에 넣고 다른 스레드에서 소비합니다.

그게 내 프로젝트 중 하나

private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     lock (SyncObject) 
     { 
      if (!_serialPort.IsOpen) return; 

      try 
      {      
       int toread = _serialPort.BytesToRead; 
       byte[] bytes = new byte[toread]; 
       _serialPort.Read(bytes, 0, toread); 

       ProducerAddBytes(bytes); 
      } 
      catch (TimeOutException) 
      { 
       //logic 
      } 
     } 
    } 

P.S.에 SerialPortDataReceived 기능이 무엇인지 그러나 첫 번째 프로필! 내가 위의 코드와 함께 문제가 무엇인지있어

+0

+1은 생산 된 소비자 접근법을 제안합니다. DataReceived 이벤트는 IO Completion 스레드에서 발생하므로 데이터 처리를 수행하고 거기에서 메서드 호출을 수행하는 것은 큰 실수입니다. – ogggre

+0

시리얼 포트에 문제가 없다고 제안 하셨듯이 장엄한 감사드립니다. – tspshikari