Boost Asio を使用したシリアル ポートからの読み取り
-
25-09-2019 - |
質問
を使用して、シリアル ポート上の受信データ パッケージを確認したいと考えています。 boost.asio
. 。各データ パケットは 1 バイト長のヘッダーで始まり、送信されたメッセージの種類を指定します。さまざまな種類のメッセージにはそれぞれ独自の長さがあります。私が書きたい関数は、新しい受信メッセージを継続的にリッスンし、メッセージを見つけたらそれを読み取り、他の関数を呼び出してそれを解析する必要があります。私の現在のコードは次のとおりです。
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
使用する適切なツールは何ですか?また、メッセージを解析できるようにそこからデータを抽出するにはどうすればよいでしょうか?また、より頻繁に呼び出されるように、この関数のみを呼び出す別のスレッドが必要かどうかも知りたいです。高トラフィックとシリアル ポートのバッファ不足により、関数の 2 回の呼び出しの間にデータが失われることを心配する必要がありますか?GUI 用に Qt のライブラリを使用していますが、すべてのイベントを処理するのにどれくらい時間がかかるかよくわかりません。
編集: 興味深い質問は次のとおりです。シリアルポートに受信データがあるかどうかを確認するにはどうすればよいですか?受信データがない場合、関数をブロックしたくないのですが...
解決
この記事は、ASIO をシリアル ポートと非同期で使用する方法を理解するのに役立ちます。
更新情報 (2019-03):
私がリンクしていた元の記事はもう入手できず、インターネット アーカイブでも見つけるのが困難です。(がここにあります スナップショット。)。現在、シリアル I/O に ASIO を使用することに関する新しい記事が検索で簡単に見つかりますが、この古い記事は依然として非常に役立ちます。失われないように、公開 Gist に入れておきます。
この記事で説明されているコードはここにコピーされているようです。
作者はC++11用にアップデートしたようです。私は記事がだったと信じています 原作者 フェデ.tft.
他のヒント
ジェイソン、
それはあなたのアプリケーションに適している場合は、、私は非常にコールバックベースの非同期シリアルRXを実装するお勧めします。私はノンブロッキングがASIOですかを使用して読んで行うにはどうすればよいは、タイムアウトで非同期シリアルを実装する方法の偉大な小さな例があります。あなたが認識されるようにあなたが受け取ったデータは必ずコピーをたくさん行っていないにするためにバッファリングされるいくつかの考えを配置する必要がありますので、それは、パフォーマンス上の利点を得るために、マルチスレッドの実装が必要になります。
boost::streambuff
にターゲットバッファを渡すためにchar m_RXBuffer[m_RXBuffSize]
や使用boost::asio::buffer(m_RXBuffer, m_RXBuffSize)
- は限りasync_read_some
のものが行くように、私は個人的にはいくつかのchar型の配列としてメモリを遮断することを好みます。特にRS232のために、私はいつも基礎となるデータは、バイトのストリームであるという事実は、自然に、より複雑なデータ構造のいずれよりも、単純なchar配列にかなり良くマッピングし発見した。
グッドラック!