質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Boost

Boost (ブースト)は、C++の先駆的な開発者のコミュニティ、 またそのコミュニティによって公開されているオープンソースライブラリのことを指します。

Q&A

解決済

1回答

1636閲覧

C++ boost::asioを利用したシリアル通信で非同期受信(async_read)をしたい

ashinari

総合スコア1

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Boost

Boost (ブースト)は、C++の先駆的な開発者のコミュニティ、 またそのコミュニティによって公開されているオープンソースライブラリのことを指します。

0グッド

0クリップ

投稿2023/05/15 08:46

概要

・PC(USB)⇔相手機器(RS485)という形式で接続しシリアル通信を行っています
・PCからコマンドを送信すると相手機器はそれに反応し、結果をPC側に送信する仕様となります
・コマンドによって送信データのサイズは変動し、受信するデータのサイズもそれに合わせて変動します
・boost::asio::write関数で同期送信し、boost::asio::async_read関数で非同期受信をします
・現状のコードだとwriteによる送信で相手機器に反応はありますが、async_readのコールバック関数が呼ばれません

該当のソースコード

C++

1#include <iostream> 2#include <iomanip> 3#include <boost/thread/thread.hpp> 4#include <boost/asio.hpp> 5 6class CommSample 7{ 8public: 9 CommSample(const std::string& portname); 10 ~CommSample(); 11 void test(); 12private: 13 boost::thread _thread; 14 unsigned char _receive_data[64]; 15 boost::asio::io_service _io; 16 boost::asio::serial_port _port; 17 void handler(const boost::system::error_code&, size_t); 18}; 19CommSample::CommSample(const std::string& portname) : _io(), _port(_io) 20{ 21 _port.open(portname); 22 _port.set_option(boost::asio::serial_port_base::baud_rate(19200)); 23 _port.set_option(boost::asio::serial_port_base::character_size(8)); 24 _port.set_option(boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none)); 25 _port.set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none)); 26 _port.set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one)); 27 boost::asio::io_service::work w(_io); 28 boost::thread t(boost::bind(&boost::asio::io_service::run, &_io)); 29 _thread = boost::move(t); 30} 31CommSample::~CommSample() 32{ 33 _io.stop(); 34 _thread.join(); 35} 36void CommSample::test() 37{ 38 constexpr int receive_size = 8; 39 unsigned char send_data[6]{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; 40 boost::asio::async_read(_port, 41 boost::asio::buffer(_receive_data), 42 boost::asio::transfer_exactly(receive_size), 43 boost::bind(&CommSample::handler, 44 this, 45 boost::asio::placeholders::error, 46 boost::asio::placeholders::bytes_transferred)); 47 boost::asio::write(_port, boost::asio::buffer(send_data)); 48} 49void CommSample::handler(const boost::system::error_code& error, size_t bytes_transferred) 50{ 51 for (size_t i = 0; i < bytes_transferred; i++) 52 { 53 std::cout << std::uppercase << std::setfill('0') << std::hex << std::setw(2) << (int)_receive_data[i]; 54 } 55} 56int main() 57{ 58 CommSample a("COM3"); 59 while (true) 60 { 61 char c = getchar(); 62 if (c == 'q')break; 63 if (c == 'a')a.test(); 64 } 65 return 0; 66}

試したこと

ネットで調べますとio_service::run関数は処理するものがないと終了するそうで
見様見真似ですがboost::asio::io_service::work w(_io);というものをスレッド作成前に呼んでいます
しかしio_service::stopped()関数はコンストラクタを呼んだ直後には既にtrueを返してしまいます

async_readではなく
read(_port,boost::asio::buffer(_receive_data),boost::asio::transfer_exactly(receive_size));
の同期関数に変更すると受信したいデータがちゃんと_receive_dataに格納されています
write関数の後にこれは書きました

どこを修正したら良いでしょうか?
write関数は今回の目的が実現できるのであればasync_write関数に変更可能です

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

自己解決しました
boost::asio::io_service::work w(_io);
は正しかったのですが
コンストラクタ内で書いていたのでコンストラクタが終了した時点で
wも寿命を迎えていました
メンバ変数にboost::asio::io_service::work w;を持ち
コンストラクタでw(_io)と初期化しましたら動きました

投稿2023/05/16 07:41

ashinari

総合スコア1

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問