Home > front end >  Boost Asio Serial port How to find out the size of the buffer in the queue for reading C
Boost Asio Serial port How to find out the size of the buffer in the queue for reading C

Time:03-22

In Arduino data can be read as follows:

void setup() {
    Serial.begin(9600);
}

String Comand = "";
void loop() {
    if (Serial.available() > 0) //If there is data read 
        {
        char c = Serial.read(); //get byte
        if(c!='\n')
        {
          Comand =c;
        }
        else
        {
          if(Comand == "MyComand")
          {
            Serial.println("Comand 1");
          }
          //else
          //...
          Comand = "";
        }
    }
}

С boost asio Here is an example of c playback of data from the port, but what function to check if there is anything to read?

#include <boost/asio.hpp>
#include <windows.h>

//....

int main(int, char**)
{
    {
        boost::asio::io_service io;
        boost::asio::serial_port serial(io,"COM5");
        serial.set_option(boost::asio::serial_port_base::baud_rate(9600));

        std::string s = "MyComand\n";
        boost::asio::write(serial,boost::asio::buffer(s.c_str(),s.size()));
        std::string result;

        //while serial data > 0 ???  How to check
        {
            using namespace boost;
            char c;
            asio::read(serial,asio::buffer(&c,1));
            result =c;
        }

        std::cout<<result.c_str();

    }

return 0;
}

If I read in a cycle, and there is no data, the program will stop and wait for the data, it does not suit me. How to check if there is data before trying to read.

CodePudding user response:

The idea of asynchronous IO is that you donot check whether data is available. Instead, you defer the completion of the read until that is the case.

Now, you're using Asio to still do synchronous IO. And your requirement is:

If I read in a cycle, and there is no data, the program will stop and wait for the data, it does not suit me.

Synchronous IO implies blocking reads. You can make it return whatever is available:

while (auto n = serial.read_some(asio::buffer(buf))) {
    result.append(buf.data(), n);
    std::cout << "Received " << n
              << " bytes, total length: " << result.length() << "\n";
}

But read_some is still blocking:

This function is used to read data from the serial port. The function call will block until one or more bytes of data has been read successfully, or until an error occurs.

So, the only real alternative for serial ports is to use the async interface:

std::string result;
std::array<char, 32> buf;

std::function<void(error_code, size_t)> read_loop;
read_loop = [&](error_code ec, size_t n) {
    if (ec.failed())
        return;
    std::cout << "Received " << n
              << " bytes, total length: " << result.length() << "\n";
    result.append(buf.data(), n);
    serial.async_read_some(asio::buffer(buf), read_loop);
};
read_loop(error_code{}, 0);

Now you have a new "problem": how to integrate your application logic into this. The fact that you're printing the request suggests to me that you're not receiving an unbounded stream of binary data. Instead, consider simplifying for your application logic to read just what you need, perhaps with a timeout. See e.g. asio_read_some countinue reading to get all data

  • Related