Чтение с последовательного порта с Boost Asio - PullRequest
6 голосов
/ 11 мая 2010

Я хочу проверить наличие пакетов данных на последовательном порту, используя boost.asio. Каждый пакет данных будет начинаться с заголовка длиной один байт и будет указывать, какой тип сообщения был отправлен. Каждый тип сообщения имеет свою длину. Функция, которую я хочу написать, должна непрерывно прослушивать новые входящие сообщения, а когда она находит одно, она должна читать его и вызывать какую-то другую функцию для ее анализа. Мой текущий код выглядит следующим образом:

void check_for_incoming_messages()
{
    boost::asio::streambuf response;
    boost::system::error_code error;
    std::string s1, s2;
    if (boost::asio::read(port, response, boost::asio::transfer_at_least(0), error)) {
        s1 = streambuf_to_string(response);
        int msg_code = s1[0];
        if (msg_code < 0 || msg_code >= NUM_MESSAGES) {
            // Handle error, invalid message header
        }
        if (boost::asio::read(port, response, boost::asio::transfer_at_least(message_lengths[msg_code]-s1.length()), error)) {
            s2 = streambuf_to_string(response);
            // Handle the content of s1 and s2
        }
        else if (error != boost::asio::error::eof) {
            throw boost::system::system_error(error);
        }
    }
    else if (error != boost::asio::error::eof) {
        throw boost::system::system_error(error);
    }
}

Является ли boost::asio::streambuf правильным инструментом для использования? И как мне извлечь из него данные, чтобы я мог разобрать сообщение? Я также хочу знать, нужно ли мне иметь отдельный поток, который вызывает только эту функцию, чтобы он вызывался чаще. Стоит ли беспокоиться о потере данных между двумя вызовами функции из-за высокого трафика и исчерпания буфера последовательного порта? Я использую библиотеки Qt для графического интерфейса и не знаю, сколько времени нужно для обработки всех событий.

Редактировать: Интересный вопрос: как я могу проверить, есть ли какие-либо входящие данные на последовательном порту? Если нет входящих данных, я не хочу, чтобы функция блокировала ...

Ответы [ 2 ]

17 голосов
/ 07 июня 2010

Эта статья полезна для понимания того, как ASIO может использоваться асинхронно с последовательными портами:

ОБНОВЛЕНИЕ (2019-03) :

Оригинальная статья, на которую я ссылался, больше не доступна и ее трудно найти даже в Интернет-архиве. (Вот снимок .). В настоящее время есть новые статьи об использовании ASIO для последовательного ввода-вывода, которые легко найти с помощью поиска, но эта старая статья все еще очень полезна Я помещаю это в публичную суть, чтобы это не потерялось. Код, описанный в статье, похоже, был скопирован здесь:

Автор, кажется, обновил его для C ++ 11. Я считаю, что статья была Первоначально написано fede.tft .

2 голосов
/ 12 марта 2012

Джейсон

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

Что касается вещи boost::streambuff, я лично предпочитаю просто заблокировать некоторую память в виде массива символов - char m_RXBuffer[m_RXBuffSize] и использовать boost::asio::buffer(m_RXBuffer, m_RXBuffSize) для передачи целевого буфера в async_read_some. В частности, для RS232 я всегда обнаруживал тот факт, что лежащие в основе данных данные представляют собой поток байтов, который, естественно, намного лучше отображает простой массив символов, чем любая из более сложных структур данных.

Удачи!

...