2013-07-09 6 views
3

직렬 포트에서 여러 바이트를 비동기 적으로 읽으려고합니다. 현재 내가 사용하고있는 코드는 (소스는 How do I perform a nonblocking read using asio?입니다.) 오직 1 바이트 만 읽으면 끝납니다. 직렬 포트에 들어오는 데이터가 없어 질 때까지 코드가 계속 읽도록하려면 어떻게해야합니까? 감사합니다 :)에서직렬 포트 읽기 비동기식 부스트

void foo() 
{ 
    boost::asio::io_service io_svc; 
    boost::asio::serial_port ser_port(io_svc, "/dev/ttyS0"); 
    boost::asio::deadline_timer timeout(io_svc); 
    unsigned char my_buffer[2]; 
    bool data_available = false; 

    ser_port.async_read_some(boost::asio::buffer(my_buffer), 
      boost::bind(&read_callback, boost::ref(data_available), 
        boost::ref(timeout),boost::asio::placeholders::error(), 
        boost::asio::placeholders::bytes_transferred())); 
    timeout.expires_from_now(boost::posix_time::seconds(30)); 
    timeout.async_wait(boost::bind(&wait_callback, boost::ref(ser_port),boost::asio::placeholders::error())); 

    io_svc.run(); 

    io_svc. 

    if(!data_available) 
    { 
     ser_port.close(); 
     cout << "ser_port was closed"; 
    } 

} 

void read_callback(bool& data_available, boost::asio::deadline_timer& timeout, const boost::system::error_code& error, std::size_t bytes_transferred) 
{ 
    if (error || !bytes_transferred) 
    { 
     // No data was read! 
     data_available = false; 
     return; 
    } 

    timeout.cancel(); 
    data_available = true; 
} 

void wait_callback(boost::asio::serial_port& ser_port, const boost::system::error_code& error) 
{ 
    if (error) 
    { 
     // Data was read and this timeout was cancelled 

     return; 
    } 

    ser_port.cancel(); 
} 

답변

3

당신의 read_callback 당신이 당신의 타이머를 취소하고 새로운 읽기를 시작하지 마십시오.
그래서 ASIO가 무엇을 기대합니까? 모든 핸들러를 취소하고 문서 상태처럼 핸들러가 남아 있지 않으면 run 메소드가 리턴됩니다.

수신하는 1 바이트보다 많은 데이터를 얻고 싶다면 다음 두 가지를 할 수 있습니다.
먼저 포트에서 더 많은 정보를 읽으려면 asio라는 또 다른 호출을 실행하십시오.

void read_callback(bool& data_available, boost::asio::deadline_timer& timeout, const boost::system::error_code& error, std::size_t bytes_transferred) 
{ 
    if (error || !bytes_transferred) 
    { 
     // No data was read! 
     data_available = false; 
     return; 
    } 
    // do something with the data you just read 
    ser_port.async_read_some(boost::asio::buffer(my_buffer), 
     boost::bind(&read_callback, boost::ref(data_available), 
       boost::ref(timeout),boost::asio::placeholders::error(), 
       boost::asio::placeholders::bytes_transferred())); 
    //restart your timer 
    data_available = true; 
} 

또는 당신은 당신이 필요로하는 데이터의 최소 금액을 얻기 위해 사용 transfer_at_least을 추가 할 수 있습니다.

+0

좋습니다. 이 함수에서는 정의되지 않았으므로 직렬 포트와 버퍼를 main에서 초기화해야합니까? – user2554193

+0

@ user2554193 메인에서 할 수 있고 콜백에 대한 포트/버퍼 포인터를 전달할 수 있습니다. 또는 멤버로 클래스에 넣고 멤버 함수에 바인딩합니다. – mkaes

+0

고맙습니다. 작동합니다 :) – user2554193