基本上我的问题是在同一函数中async_read_some 之后没有启动io_service 线程。你能怪我吗?这东西不是很清楚。这是我的代码,以防有人需要(INFO 和 ERROR 来自 boost 日志记录,请参阅我的其他问题之一):
serial_comm.hpp
#ifndef __SERIAL_COMM_HPP
#define __SERIAL_COMM_HPP
#include <boost/asio.hpp>
#include <boost/asio/serial_port.hpp>
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <string>
#include <atomic>
#include "logging.hpp" // Boost logging
#define MAX_RESPONSE_SIZE 256
class serial_comm
{
public:
void open_serial_port (std::string device_path, unsigned int baud_rate);
void close_serial_port (void);
void async_read_some (void);
std::string serial_read_data;
std::atomic <bool> serial_data_read_complete{false};
private:
// functions
void data_received (const boost::system::error_code& ec, size_t bytes_transferred);
// variables
boost::mutex mutex;
boost::system::error_code error;
boost::asio::io_service io_service;
typedef boost::shared_ptr<boost::asio::serial_port> serial_port_ptr;
serial_port_ptr serial_port;
char read_buffer[MAX_RESPONSE_SIZE];
};
#endif // __SERIAL_COMM_HPP
serial_comm.cpp
#include "../include/serial_comm.hpp"
void serial_comm::open_serial_port (std::string device_path, unsigned int baud_rate)
{
INFO << "started";
try
{
serial_port.reset();
serial_port = serial_port_ptr(new boost::asio::serial_port(io_service));
serial_port->open(device_path, error);
if (error)
{
ERROR << "error.message() >> " << error.message().c_str();
throw -3;
}
// set options
serial_port->set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
serial_port->set_option(boost::asio::serial_port_base::character_size(8));
serial_port->set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one));
serial_port->set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none));
serial_port->set_option(boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none));
}
catch (int error)
{
ERROR << "error = " << error;
throw -1;
}
catch (const std::exception &e)
{
ERROR << "e.what() = " << e.what();
throw -2;
}
INFO << device_path << " opened correctly";
INFO << "ended";
return;
}
void serial_comm::close_serial_port()
{
boost::mutex::scoped_lock lock(mutex); // prevent multiple thread access
INFO << "started";
try
{
if (serial_port)
{
serial_port->cancel();
serial_port->close();
serial_port.reset();
}
else
{
WARNING << "serial port is not open";
}
io_service.stop();
io_service.reset();
}
catch (const std::exception &e)
{
ERROR << "e.what() = " << e.what();
throw -1;
}
INFO << "ended";
return;
}
void serial_comm::async_read_some (void)
{
boost::mutex::scoped_lock lock (mutex); // prevent multiple threads
INFO << "started";
std::string data;
try
{
if (serial_port.get() == NULL || !serial_port->is_open())
{
WARNING << "serial port is not open";
throw -2;
}
serial_port->async_read_some(
boost::asio::buffer(read_buffer, MAX_RESPONSE_SIZE),
boost::bind(
&serial_comm::data_received,
this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
// start io_service run thread after giving it work
boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));
}
catch (const std::exception &e)
{
ERROR << "e.what() = " << e.what();
throw -1;
}
INFO << "ended";
return;
}
void serial_comm::data_received(const boost::system::error_code& error, size_t bytes_transferred)
{
boost::mutex::scoped_lock lock(mutex); // prevent multiple thread access
INFO << "started";
try
{
if (serial_port.get() == NULL || !serial_port->is_open())
{
WARNING << "serial port is not open";
throw -2;
}
if (error)
{
ERROR << "error.message() >> " << error.message().c_str();
throw -3;
}
for (unsigned int i = 0; i < bytes_transferred; ++i) {
serial_read_data += read_buffer[i];
}
INFO << "bytes_transferred = " << bytes_transferred << "; serial_read_data = " << serial_read_data;
serial_data_read_complete = true;
}
catch (const std::exception &e)
{
ERROR << "e.what() = " << e.what();
throw -1;
}
// prevent io_service from returning due to lack of work
serial_port->async_read_some(
boost::asio::buffer(read_buffer, MAX_RESPONSE_SIZE),
boost::bind(
&serial_comm::data_received,
this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
INFO << "ended";
return;
}
main.cpp
#include "../include/serial_comm.hpp"
int main(void)
{
serial_comm _serial_comm;
try
{
_serial_comm.open_serial_port("/dev/ttyS0", 9600);
_serial_comm.async_read_some(); // this function will always check for data
loop:
while (!_serial_comm.serial_data_read_complete)
{
sleep(1);
}
INFO << "_serial_comm.serial_read_data = " << _serial_comm.serial_read_data;
_serial_comm.serial_read_data.clear();
_serial_comm.serial_data_read_complete = false;
goto loop;
}
catch (int error)
{
ERROR << "error >> " << error;
return;
}
FATAL << "main ended";
return;
}