Высокая загрузка ЦП со временем для последовательного порта - PullRequest
2 голосов
/ 01 марта 2012

Я сейчас работаю над проектом, в котором мне нужно постоянно читать последовательный порт.Данные поступают непрерывно в течение максимум 45 минут.Я должен проверить данные с помощью контрольной суммы и создать пакет из 79 байтов.После этого я должен построить данные (траекторию) в режиме реального времени.Проблема с кодом заключается в том, что при запуске он использует 20% загрузки ЦП (Pentium 4, 3,0 ГГц, Hyper-многопоточность) (который, я думаю, все еще высок), но со временем загрузка ЦП увеличивается и в конце достигает 60%..

Данные поступают со скоростью 115200 бод и непрерывно отправляются со скоростью 100 мсек.

Мой код для чтения, проверки и вывода на печать выглядит следующим образом:данные и проверить их ...

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

Следующая функция отображает данные на этикетках и рисует траекторию в графическом окне

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

        }           
    }    

Ответы [ 2 ]

4 голосов
/ 01 марта 2012

Я интенсивно работаю с устройствами, подключенными к последовательному порту, и могу вас заверить, что регулярное использование класса SerialPort само по себе не приводит к высокой загрузке процессора.

ПЕРВЫЙ Я бы предложил вам ПРОФИЛЬ ваше заявление. Есть куча профилировщиков для .NET

Только после профилирования. Я бы предложил разделить чтение SerialPort и обработку данных. Используйте шаблон Producer Consumer. Поместите данные из SerialPort в очередь и используйте их из другого потока.

То, что у меня есть в функции SerialPortDataReceived в одном из моих проектов

    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. Но ПРОФИЛЬ ПЕРВЫЙ!

1 голос
/ 02 марта 2012

я понял, в чем проблема с приведенным выше кодом ..

Я использую График пути для построения траектории

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

Теперь, когда приложение продолжает работать, оно собирает множество точек на графике, и, следовательно, построение этого огромного количества точек потребляет ресурсы.

Может кто-нибудь предложить мне решение этой проблемы, как построить траекторию без замедления системы ...

...