samw
samw

Reputation: 149

Serial port receives same bytes it just sent

I'm trying to use Boost.Asio to read from and write to a serial port. Here is my code:

void async_read(boost::asio::serial_port& serial_port)
{
    auto buffer = std::make_shared<std::vector<uint8_t>>(64);
    serial_port.async_read_some(boost::asio::buffer(*buffer),
            [buffer, &serial_port](const boost::system::error_code& error, size_t bytes_read)
            {
                if (error)
                {
                    std::cout << "Error reading serial port: " << error.message() << std::endl;
                    return;
                }
                std::string message(buffer->begin(), buffer->end());
                std::cout << "Read " << bytes_read << " bytes:\t" << message << std::endl;
                async_read(serial_port);
            });
}

void async_write(boost::asio::serial_port& serial_port)
{
    auto timer = std::make_shared<boost::asio::deadline_timer>(serial_port.get_io_service(), boost::posix_time::seconds(1));
    timer->async_wait(
            [&serial_port, timer](const boost::system::error_code& error)
            {
                if (error)
                {
                    std::cout << "Timer error: " << error.message() << std::endl;
                    return;
                }

                auto message = std::make_shared<std::string>("Hello\n");
                boost::asio::async_write(serial_port, boost::asio::buffer(*message),
                        [message, &serial_port](const boost::system::error_code& error, size_t bytes_sent)
                        {
                            if (error)
                            {
                                std::cout << "Error writing to serial port: " << error.message() << std::endl;
                                return;
                            }
                            std::cout << "Wrote " << bytes_sent << " bytes" << std::endl;
                            async_write(serial_port);
                        });
            });
}

int main()
{
    boost::asio::io_service service;
    auto serial_port = boost::asio::serial_port(service, "/dev/ttyUSB0");
    serial_port.set_option(boost::asio::serial_port::baud_rate(9600));
    async_read(serial_port);
    async_write(serial_port);
    service.run();
}

At the opposite end of the serial cable, I have a separate machine running cat /dev/ttyTHS0. My issue is that whenever the program performs an async_write, those same bytes are immediately handled by the async_read completion handler - even though the remote machine isn't sending anything.

I'm not sure if the root cause is the code, or because I'm using cat at the other end. When cat is not running, I'm not having the issue.

Running the above code, (with cat /dev/ttyTHS0 at the other end) gives output like this:

Wrote 6 bytes
Read 7 bytes:   Hello

Wrote 6 bytes
Read 3 bytes:   Hel
Read 4 bytes:   lo

Wrote 6 bytes
Read 7 bytes:   Hello

Wrote 6 bytes
Read 1 bytes:   H
Read 6 bytes:   ello

Wrote 6 bytes
Read 7 bytes:   Hello

Maybe I'm missing something obvious, but any help is appreciated! Thank you!

Upvotes: 1

Views: 506

Answers (1)

meuh
meuh

Reputation: 12255

This is the expected behaviour for a serial port. These were typically used to connect a terminal like a vt100 to a computer. When you type on the keyboard, the character is sent to the computer, and the serial port echoes it back to the vt100 screen where it is displayed.

If you run stty -a -F /dev/ttyTHS0 on the remote you will see the setting echo is on (before you ran your program on the remote). You can switch it off with stty -echo -F /dev/ttyTHS0, when it will show as -echo.

Typically, when serial ports are used for comms between computers, the application will set the port to raw, noecho. This is to avoid certain translations being done by the serial port driver, so the data arrives unchanged at the application.

Upvotes: 2

Related Questions