我想通过串口与arduino通信。
我发送一些数据并等待一段时间后才能回复。 奇怪的是 - 如果我在写入后直接调用async_read_some(),我将在读处理程序中收到文件结束错误。据我所知,这是一个封闭港口的指示。然而,串行端口上的is_open()仍返回true。如果我在写完后睡了几毫秒并调用async_read_some()然后,处理程序将收到响应,但也会在一段时间后收到一个eof。如果我减少等待的时间,有时只收到部分消息,然后就会得到一个eof。
我不知道我到底做错了什么,或者如何更好地调试。这是一些显示我正在做的事情的独立代码:
#include <boost/asio.hpp>
#include <boost/asio/serial_port.hpp>
#include <chrono>
#include <condition_variable>
#include <cstring>
#include <functional>
#include <iostream>
#include <mutex>
#include <sstream>
#include <string>
#include <thread>
int serialtest()
{
using namespace std::chrono;
using hrc=high_resolution_clock;
using namespace std;
using namespace boost::asio;
int rc = 0;
int i = 1;
io_service io;
serial_port port(io, "/dev/ttyACM0");
if(port.is_open())
{
cout << "Found serial device on port " << i << ". Opened successfully." << endl;
}
// option settings...
port.set_option(serial_port_base::baud_rate(115200));
port.set_option(serial_port_base::character_size(8));
port.set_option(serial_port_base::stop_bits(serial_port_base::stop_bits::one));
port.set_option(serial_port_base::parity(serial_port_base::parity::none));
port.set_option(serial_port_base::flow_control(serial_port_base::flow_control::none));
mutex response_mutex;
condition_variable response_cv;
seconds timeout_s(1);
std::size_t bufsize = 4096;
boost::asio::streambuf read_buffer;
auto mbuf = read_buffer.prepare(bufsize);
stringstream response;
hrc::time_point begin,end;
milliseconds timeout(0);
function<void(const boost::system::error_code&,size_t)> handler;
handler = [&](const boost::system::error_code& error,
size_t bytes_transferred)
{
unique_lock<mutex>(response_mutex);
if(bytes_transferred != 0)
{
cout << "Received " << bytes_transferred << " bytes from serial" << endl;
response << buffer_cast<const char*>(read_buffer.data());
read_buffer.consume(bytes_transferred);
response_cv.notify_one();
}
if(boost::system::errc::success != error.value())
{
cout << "Error reading: " << error.value() << endl;
cout << "Error message: " << error.message() << endl;
return;
}
port.async_read_some(mbuf,handler);
};
// check if motion
string msg = "INFO.ISMOTION;";
cout << "Checking if it's a motion controller" << endl;
boost::system::error_code ec;
port.async_write_some(buffer(reinterpret_cast<const void*>(msg.c_str()),msg.size()),
[&](const boost::system::error_code& error,
size_t bytes_transferred)
{
if(bytes_transferred != 0)
{
cout << "Wrote " << bytes_transferred << " bytes to serial" << endl;
}
if(boost::system::errc::success != error.value())
{
cout << "Error writing to port: " << error.message() << endl;
}
});
// Hard wait for a response
this_thread::sleep_for(milliseconds(5));
port.async_read_some(mbuf, handler);
thread io_thread([&io](){io.run();});
begin = hrc::now();
while((response.str().back() != ';') && (timeout < timeout_s))
{
unique_lock<mutex> lock(response_mutex);
response_cv.wait_for(lock, milliseconds(100), [&response,&timeout,&timeout_s]()
{
return ((response.str().back() == ';') || (timeout >= timeout_s));
});
cout << "Current response buffer: " << response.str() << endl;
end = hrc::now();
timeout += duration_cast<milliseconds>(end-begin);
begin = hrc::now();
}
cout << "Complete response: " << response.str() << endl;
if((timeout >= timeout_s))
{
cout << "Timed out waiting for response to INFO.ISMOTION" << endl;
rc = -2;
}
if("INFO.ISMOTION;" != response.str())
{
cout << "Not a motion controller at port " << i << endl;
rc = -3;
}
else
{
cout << "Is a motion controller!" << endl;
}
io.stop();
port.cancel();
port.close();
io.reset();
io_thread.join();
return rc;
}
int main()
{
using std::cout;
using std::endl;
int rc;
try
{
rc=serialtest();
}
catch(boost::system::system_error& error)
{
cout << "Error occured: " << error.what() << endl;
rc = -5;
}
return rc;
}