Boost asio serial port initially sending bad data

2019-08-22 21:25发布

问题:

I am attempting to use boost asio for serial communication. I am currently working in Windows, but will eventually be moving the code into Linux. When ever I restart my computer data sent from the program is not what it should be (for example I send a null followed by a carriage return and get "00111111 10000011" in binary) and it is not consistent (multiple nulls yield different binary).

However, as soon as I use any other program to send any data to the serial port and run the program again it works perfectly. I think I must be missing something in the initialization of the port, but my research has not turned anything up.

Here is how I am opening the port:

// An IOService to get the socket to work
boost::asio::io_service *io;
// An acceptor for getting connections
boost::shared_ptr<boost::asio::serial_port> port;

// Cnstructor Functions
void Defaults() {
    io = new boost::asio::io_service();

    // Set Default Commands
    command.prefix = 170;
    command.address = 3;
    command.xDot[0] = 128;
    command.xDot[1] = 128;
    command.xDot[2] = 128;
    command.throtle = 0;
    command.button8 = 0;
    command.button16 = 0;
    command.checkSum = 131;
}

void Defaults(char * port, int baud) {
    Defaults();

    // Setup the serial port
    port.reset(new boost::asio::serial_port(*io,port));
    port->set_option( boost::asio::serial_port_base::baud_rate( baud ));

    // This is for testing
    printf("portTest: %i\n",(int)port->is_open());
    port->write_some(boost::asio::buffer((void*)"\0", 1));
    boost::asio::write(*port, boost::asio::buffer((void*)"\0", 1));
    boost::asio::write(*port, boost::asio::buffer((void*)"\r", 1));
    boost::asio::write(*port, boost::asio::buffer((void*)"\r", 1));
    Sleep(2000);
}

Edit: In an attempt to remove unrelated code I accidentally deleted the the line where I set the baud rate, I added it back. Also, I am checking the output with a null-modem and Docklight. Aside from the baud rate I am using all of the default serial settings specified for a boost serial port (I have also tried explicitly setting them with no effect).

回答1:

You haven't said how you're checking what's being sent, but it's probably a baud rate mismatch between the two ends.

It looks like you're missing this:

port->set_option( boost::asio::serial_port_base::baud_rate( baud ) );

Number of data bits, parity, and start and stop bits will also need configuring if they're different to the default values.

If you still can't sort it, stick an oscilloscope on the output and compare the waveform of the sender and receiver. You'll see something like this.



回答2:

This is the top search result when looking for this problem, so I thought I'd give what I believe is the correct answer:

Boost Asio is bugged as of this writing and does not set default values for ports on the Windows platform. Instead, it grabs the current values on the port and then bakes them right back in. After a fresh reboot, the port hasn't been used yet, so its Windows-default values are likely not useful for communication (byte size typically defaults to 9, for example). After you use the port with a program or library that sets the values correctly, the values Asio picks up afterward are correct.

To solve this until Asio incorporates the fix, just set everything on the port explicitly, ie:

using boost::asio::serial_port;
using boost::asio::serial_port_base;

void setup_port(serial_port &serial, unsigned int baud)
{
    serial.set_option(serial_port_base::baud_rate(baud));
    serial.set_option(serial_port_base::character_size(8));
    serial.set_option(serial_port_base::flow_control(serial_port_base::flow_control::none));
    serial.set_option(serial_port_base::parity(serial_port_base::parity::none));
    serial.set_option(serial_port_base::stop_bits(serial_port_base::stop_bits::one));
}