Не считывает полные данные последовательного порта в C # - PullRequest
5 голосов
/ 11 января 2011

Я использую .Net Framework 4 и создаю приложение с графическим интерфейсом последовательного порта в C #.В некоторых случаях объект SerialPort (порт) не получает все данные (я сравниваю его с осциллографом смешанных сигналов)

Например, если подключенное устройство отправляет:

0x00 0x010x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09

Я могу получить:

0x00 0x01 0x02 0x03 0x04 0x08 0x09

Я пробовал разные коды с одинаковымиПроблема:

  • Используйте событие полученных данных для заполнения буфера:

        private void dataReceived(object sender, SerialDataReceivedEventArgs e) {
            while (port.BytesToRead > 0){
                byte[] newBytes = new byte[port.BytesToRead];
                int LengthRead = port.Read(newBytes, 0, newBytes.Length);
                Array.Resize(ref newBytes, LengthRead);
                System.Buffer.BlockCopy(newBytes, 0, buffer, positionInBuffer, newBytes.Length);
                positionInBuffer += newBytes.Length;
            }
        }
    
  • Цикл для ожидаемого количества байтов, в этом случаевызывая TimeoutException:

            while (port.BytesToRead < expectedSize)
        {
            System.Threading.Thread.Sleep(10);
            waitingLoop++;
            if (waitingLoop > TimeOut)             // wait for a 1s timeout
                throw new TimeoutException();
        }
    
        newBytes = new byte[expectedSize];
        LengthRead = port.Read(newBytes, 0, newBytes.Length);
        if (LengthRead != newBytes.Length)
            throw new TimeoutException(); // or any exception, doesn't matter...
    

Я пытался изменить размер ReadBufferSize, информацию о тайм-ауте, ... но ничего не работает.Есть идеи?

Ответы [ 3 ]

4 голосов
/ 11 января 2011

В этом коде есть тонкие ошибки. Array.Resize () первого фрагмента ничего не делает, может быть, вместо buffer нужно изменить размер? Второй фрагмент бомбы на TimeoutException, когда больше байт было получено, чем ожидаемый размер . Что, безусловно, возможно и не является проблемой тайм-аута.

Но я думаю, что настоящая проблема в том, что вы делаете с массивом вне этого кода. Как правило, вызов SerialPort.Read () дает вам только пару байтов. Последовательные порты работают медленно. Вам нужен какой-то протокол, чтобы знать, когда получен «полный» ответ. Очень распространенным (недвоичным) является просто завершение ответа переводом строки. Тогда вы просто используете ReadLine () в обработчике событий DataReceived. Неясно, каким будет правильный подход в вашем случае.

Также реализуйте событие ErrorReceived. Он сообщит вам, когда произошло что-то плохое, например SerialError.Overrun или RXOver, об ошибках, которые также приводят к исчезновению байтов.

2 голосов
/ 11 января 2011

Попробуйте настроить программное обеспечение (XON / XOF) или аппаратное (например, RTS / CTS) подтверждение связи на последовательном порту для соответствия конфигурации устройства, которое передает.

0 голосов
/ 12 января 2011

Спасибо за ответы.

На самом деле у меня есть какой-то протокол в последовательных данных.Это что-то вроде:

<ID><SIZE><DATA....><CHECKSUM>

Обычно я правильно получаю идентификатор, РАЗМЕР и затем прослушиваю ожидаемые байты данных «размер» (размер меньше 1000, а последовательный порт работает на 115200, поэтомудолжно быть короткое время).Но когда я жду их, например, со вторым кодом (цикл ожидания), они никогда не появляются в моем C # -коде, даже если они действительно передают через последовательную строку (проверяется с помощью области действия).Все еще выполняя 2-й код, я получил 1-е TimeOutException (в цикле ожидания), что означает, что я не получаю все данные в течение 1 с (также пытался увеличить до 5 с).Таким образом, ошибка перехватывается перед переходом к функции SerialPort.Read ().

В любом случае, я проверю событие ErrorReceived, чтобы проверить, поймал ли я что-то ...

В отношении массива.Resize () Я написал это в случае, если возвращенные данные SerialPort.Read () имеют меньше байтов, чем ожидаемые.Размер буфера предварительно соответствует максимальному размеру моего буфера SerialPort (4096).Что касается моей второй ошибки в коде, то вы совершенно правы.Мне лучше использовать более подходящее исключение:)

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