boost :: asio :: serial_port :: async_read_some - handler接收eof

时间:2015-03-03 14:26:39

标签: c++ boost serial-port arduino boost-asio

我想通过串口与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;
}

0 个答案:

没有答案
相关问题