Последовательный порт;Пропавшие пакеты через несколько часов - PullRequest
0 голосов
/ 03 февраля 2011

Я новичок в Visual C #.Я должен получать пакет из 468 байтов каждую секунду от встроенного устройства поочередно.Заголовок пакета 0xbf, 0x13, 0x97, 0x74.После проверки правильности заголовка пакета я сохраняю этот пакет, обрабатываю его и отображаю его графически.Проблема в том, что я начинаю терять пакеты через несколько часов.(Другое программное обеспечение регистрировало одни и те же данные за всю неделю и работает хорошо.)

Код здесь ...

private void DataRec(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)    
{
        rtTotBytes = comport.BytesToRead;
        rtTotBytesRead = comport.Read(rtSerBuff, 0, rtTotBytes);
        this.Invoke(new ComportDelegate(ComportDlgtCallback), rtSerBuff, rtTotBytesRead);
}

    //Delegate
    delegate void ComportDelegate(byte[] sBuff, int sByte);

    //Callback Function to Delegate
    private void ComportDlgtCallback(byte[] SerBuff, int TotBytes)
    {
        for (int k = 0; k < TotBytes; k++)
        {
            switch (rtState)
            {
                case 0:
                    if (SerBuff[k] == 0xbf) { rtState = 1; TempBuff[0] = 0xbf; }
                    else rtState = 0;
                    break;
                case 1:
                    if (SerBuff[k] == 0x13) { rtState = 2; TempBuff[1] = 0x13; }
                    else rtState = 0;
                    break;
                case 2:
                    if (SerBuff[k] == 0x97) { rtState = 3; TempBuff[2] = 0x97; }
                    else rtState = 0;
                    break;
                case 3:
                    if (SerBuff[k] == 0x74) { rtState = 4; TempBuff[3] = 0x74; rtCnt = 4; }
                    else rtState = 0;
                    break;
                case 4:
                    if (rtCnt == 467)
                    {
                        TempBuff[rtCnt] = SerBuff[k];
                        TempBuff.CopyTo(PlotBuff, 0);
                        ProcessPacket(PlotBuff);
                        rtState = 0; rtCnt = 0;
                    }
                    else
                        TempBuff[rtCnt++] = SerBuff[k];
                    break;
            }
        }
    }

Другой вопрос: может ли BytesToRead быть нулевымесли произошло событие DataReceivedEvent?Вы должны проверить (BytesToRead>0) в DataRecievedEvent?

Ответы [ 4 ]

2 голосов
/ 03 февраля 2011

Входные данные последовательного порта должны рассматриваться как поток, а не как серия пакетов.Например, когда устройство отправляет пакет 0xbf, 0x13, 0x97, 0x74, функцию DataRec можно вызывать один раз для всего пакета или два раза для пакетов 0xbf, 0x13 и 0x97, 0x74 или 4 раза с одним байтом и т. Д. Программа должнабыть достаточно гибким, чтобы обрабатывать входной поток, используя некоторый парсер.Ваша текущая программа не делает этого, она может пропустить логические пакеты, полученные в результате нескольких вызовов функций.Возможна и другая ситуация, когда за один вызов функции DataRec получено несколько пакетов - ваша программа также не готова к такой ситуации.

Редактировать.

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

  1. Функция DataRec добавляет полученные данные во входную очередь и вызывает анализатор вызовов.

  2. Входная очередь - это некоторый байтовый массив, который уже содержит данныеполучил, но еще не разобрал.Новые данные добавляются в конец, а проанализированные пакеты удаляются из начала этой очереди.

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

1 голос
/ 03 февраля 2011

Я думаю, что проблема может заключаться в том, что вы не можете быть уверены, что получите полный пакет в рамках события DataReceived.Вполне возможно, что вы только что получили первую половину пакета и полсекунды спустя вторую половину.

Таким образом, вы должны реализовать другой уровень, где вы помещаете данные в буфер.Дальнейшие действия зависят от формата данных.

Если вы получаете дополнительную информацию, такую ​​как конечная отметка или длина данных, вы можете проверить, содержит ли буфер эту информацию.Если да, добавьте этот полный пакет в свою программу.

Если у вас нет этой информации, вам придется подождать до получения следующего заголовка и переслать данные в вашем буфере до этого нового заголовка.

0 голосов
/ 03 февраля 2011

Как указывает Алекс Фарбер , нет гарантии, что при вызове вашего обработчика DataReceived все байты будут там.

Если ваши буферы всегда имеют фиксированный размер и с низкой скоростью, вы можете напрямую использовать функцию Read, а не полагаться на событие DataReceived. Концептуально:

packetSize = 468;    
...initialization...
comport.ReadTimeout = 2000; //packets expected every 1000 milliseconds, so give it some slack

while (captureFlag) {
    comport.Read(rtSerBuff, 0, packetSize);
    ...do stuff...
}

Это можно поместить в собственный рабочий поток, если хотите.

Другой подход заключается в использовании метода ReadLine. Вы упоминаете, что пакеты имеют известную начальную подпись. У них также есть известная конечная подпись, которая гарантированно не будет повторяться в пакете? Если это так, вы можете установить свойство NewLine для этой конечной подписи и использовать ReadLine. Опять же, вы можете поместить это в рабочий поток,

0 голосов
/ 03 февраля 2011

Вы проверили использование памяти программой? Возможно, у вас есть небольшой класс взаимодействия, память или что-то, что не освобождается должным образом, складывается через несколько часов и замедляет работу программы, что приводит к потере данных.

Я бы использовал обозреватель процессов, чтобы проверить, как меняется использование памяти и процессора через несколько часов. Может быть, также проверьте активность жесткого диска.
Если это не приводит к результатам, используйте полнофункциональный профилировщик, такой как ANTS, и попробуйте запустить программу под профилировщиком, чтобы проверить наличие проблем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...