簡體   English   中英

boost::asio SerialPort 無法接收數據

[英]boost::asio SerialPort unable to receive data

使用異步時,我無法通過 boost::asio 中的串行端口接收數據。 當我使用同步例程時,我能夠接收數據。

代碼:

串口端口.cpp

bool SerialPort::read_async(std::uint32_t read_timeout)
{
    try
    {
        if (read_timeout not_eq SerialPort::ignore_timeout)
            this->read_timeout = read_timeout;//If read_timeout is not set to ignore_timeout, update the read_timeout else use old read_timeout
        this->port.async_read_some(boost::asio::buffer(this->read_buffer.data(), this->read_buffer.size()),
            boost::bind(&SerialPort::read_handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
        return true;
    }
    catch (const std::exception& ex)
    {
        PLOG_ERROR << ex.what();
        return false;
    }
}

void SerialPort::read_handler(const boost::system::error_code& error, std::size_t bytes_transferred)
{
    std::string received_data_buffer;
    std::transform(this->read_buffer.begin(), this->read_buffer.begin() + bytes_transferred,
        std::back_inserter(received_data_buffer), [](std::byte character) {
            return static_cast<char>(character);
        });
    PLOG_INFO << "In Read Buffer : " << received_data_buffer;
}

bool SerialPort::open_port(void)
{
    try
    {
        this->port.open(this->port_name);
        return true;
    }
    catch (const std::exception& ex)
    {
        PLOG_FATAL << ex.what();
    }
    return false;
}

串口端口.hpp

class SerialPort
{
private:
    boost::asio::io_context         io;
    boost::asio::serial_port        port;
    boost::asio::serial_port::native_handle_type    native_port;
    std::string                     port_name;
    const static std::uint32_t      READ_BUFFER_MAX_LENGTH{ 8096 };

    std::array<std::byte, SerialPort::READ_BUFFER_MAX_LENGTH> read_buffer;//Used in synchronous read 
    
    void                            read_handler(
        const boost::system::error_code& error, // Result of operation.
        std::size_t bytes_transferred       // Number of bytes read.
    );
    //boost::asio::deadline_timer       timer;

public:
    SerialPort() : io(), port(io), thread_sync_read()
    {
    }
    ~SerialPort();

    bool                            open_port(void);

    bool                            read_async(std::uint32_t read_timeout = SerialPort::ignore_timeout);

};

主文件

SerialPort sp;

int main()
{
    sp.open_port("COM11");
    sp.write_sync("Testing123");
    sp.read_async();

    while (true)
    {
    }
    return 0;
}

據說您正在嘗試異步執行一些操作。

首先,混合同步和異步操作並不總是可取的。 某些服務/IO 對象可能包含假設其中之一的內部 state。

其次,異步操作需要運行io_service。 那不會發生。 您可以使其顯式而不是當前的while()循環。

#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <iostream>
namespace asio = boost::asio;
using boost::system::error_code;

std::ostream PLOG_INFO(std::clog.rdbuf());
std::ostream PLOG_ERROR(std::clog.rdbuf());
std::ostream PLOG_FATAL(std::clog.rdbuf());

class SerialPort
{
public:
  SerialPort()
      : io_()
      , port_(io_) /*, thread_sync_read()*/
  {}
  ~SerialPort() = default;

  bool open_port(std::string name);

  static constexpr uint32_t ignore_timeout = -1;
  bool read_async(std::uint32_t read_timeout = SerialPort::ignore_timeout);
  void run() { io_.run(); }

private:
  static constexpr uint32_t READ_BUFFER_MAX_LENGTH{8096};

  asio::io_context          io_;
  asio::serial_port         port_;
  std::string               port_name_;
  uint32_t                  read_timeout_ = ignore_timeout;
  // asio::deadline_timer   timer;

  std::array<std::byte, READ_BUFFER_MAX_LENGTH> read_buffer_;

  void read_handler(error_code error, size_t bytes_transferred);
};

bool SerialPort::read_async(std::uint32_t read_timeout) {
    try {
        if (read_timeout != SerialPort::ignore_timeout)
            read_timeout_ =
                read_timeout; // If read_timeout is not set to ignore_timeout,
                              // update the read_timeout else use old
                              // read_timeout
        port_.async_read_some(
            asio::buffer(read_buffer_.data(), read_buffer_.size()),
            boost::bind(&SerialPort::read_handler, this,
                        asio::placeholders::error,
                        asio::placeholders::bytes_transferred));
        return true;
    } catch (const std::exception& ex) {
        PLOG_ERROR << ex.what() << std::endl;
        return false;
    }
}

void SerialPort::read_handler(error_code error, size_t bytes_transferred) {
    std::string s;
    std::transform(
        read_buffer_.begin(), read_buffer_.begin() + bytes_transferred,
        std::back_inserter(s),
        [](std::byte character) { return static_cast<char>(character); });
    PLOG_INFO << "In Read Buffer : " << s << " (" << error.message() << ")" << std::endl;
}

bool SerialPort::open_port(std::string name) {
    try {
        port_name_ = std::move(name);
        port_.open(port_name_);
        return true;
    } catch (std::exception const& ex) {
        PLOG_FATAL << ex.what() << std::endl;
        return false;
    }
}

SerialPort sp;

int main(int argc, char** argv) {
    sp.open_port(argc > 1 ? argv[1] : "COM11");
    // sp.write_sync("Testing123");
    sp.read_async();

    sp.run();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM