2014-12-28 5 views
0

У меня есть код, который необходимо прочитать с последовательного устройства. Это функция опроса, вызываемая скоростью r.Чтение последних данных из последовательного порта с использованием boost asio

Устройство выплескивает данные в строках, разделенных \r\n и быстро, на частоте около 100 Гц. Всякий раз, когда я опросу, я хочу прочитать весь серийный буфер. Я считаю, что это сложно сделать с boost :: asio, потому что он не обеспечивает функцию available() для меня.

Один из методов, я попытался было использовать read_until(), но это не решает мою проблему, потому что могут быть новые данные в буфере после \r\n что read_until() остановками.

Я пробовал consume() в буфере после того, как прочитал его, но это все еще проблема с взломом, пока я не знаю, что я прочитал последние данные с устройства.

У кого-нибудь есть совет по этой проблеме?

+0

Это то, что вам нужно будет позаботиться о себе, boost :: asio не думает, что '\ r \ n' - все это особенное. Используйте буфер. –

+0

@HansPassant Конечно, я об этом подумал и использовал функцию read_until() для ее обработки. Но я думаю о том, что если я буду использовать read_until(), он будет считываться с вершины стека буфера. Я хочу, чтобы данные были самыми последними, и, следовательно, будут в нижней части стека. Как я могу отменить буфер? – Nopestradamus

+0

Просто не пополняйте буфер, пока он не станет пустым. У драйвера последовательного порта уже есть буфер приема. –

ответ

1

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

  • Прочитано из потока, пока операция чтения не завершится с таймаутом. В то время как Boost.Asio не обеспечивает неблокирующее синхронное чтение и чтение с тайм-аутами для объектов последовательного ввода-вывода, можно реализовать это поведение, используя асинхронные чтения и таймеры. Boost.Asio предоставляет набор тайм-аутов examples. Поскольку последовательность символов «\r\n» используется для границы данных, рассмотрите возможность использования async_read_until() для соблюдения границ данных без необходимости вводить обработку границ в код приложения. Если скорость проникновения больше, чем расход, то тайм-аут может не быть детерминированным.
  • Используйте последовательный порт native_handle() с системными вызовами для определения количества доступных для чтения байтов. Затем, есть стратегия чтения, которая использует количество байтов, доступных для определения, когда прекратить чтение. Имейте в виду, что количество доступных байтов может не попасть непосредственно на границу данных. Следовательно, приложение должно будет обрабатывать фрагментацию. Например, можно было бы async_read_until() с таймаутом. Однако, как только ранее известное количество доступных байтов было потреблено, асинхронная цепочка вызовов может быть явно остановлена. Это обеспечивает детерминированный конец асинхронной цепочки вызовов, даже если скорость входа превышает расход. Обратитесь к документации по системе, чтобы определить, как запросить доступные байты, готовые для чтения, но часто это ioctl(..., FIONREAD, ...) в Linux и ClearCommError() на Windows.
  • Разделение данных из последовательного порта и запрос на получение последних данных. С разделением обязанностей потребительский поток будет непрерывно считывать из последовательного порта через цепочку вызовов async_read_until() и сохранять последние данные, которые были прочитаны. В зависимости от того, как можно получить доступ к последним данным, механизмы синхронизации, такие как мьютексы, могут быть необходимы, чтобы избежать условий гонки. Один из вариантов, который устраняет необходимость блокировки после чтения, последовательный порт должен использовать будущее/обещание, а также выполнять операцию, которая выполняет обещание в той же цепочке, которая работает в цикле async_read_until().
  • Если данные записываются на достаточно высокой частоте, где приемлема ожидаемая полная выборка в рамках опроса, тогда можно было бы flush the serial port's receive buffer, в результате чего все данные были бы отброшены. После отбрасывания можно считывать из последовательного порта, ожидая записи, в результате чего появляются самые последние данные. Поскольку промывка буфера может отменить часть образца, может потребоваться прочитать до второй границы данных, чтобы гарантировать, что полный образец был прочитан.
Смежные вопросы