Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save JuriPospelow/fde68fea8361eeac0244010902ed7cbb to your computer and use it in GitHub Desktop.
Save JuriPospelow/fde68fea8361eeac0244010902ed7cbb to your computer and use it in GitHub Desktop.
Serial communication with boost::asio

Introduction

Here are a few simple examples that I use in practice. In both examples (synchronous and asynchronous) output can be seen as follows:

[2025-05-14 16:15:09.325792] [0x0000007f7f94f180] [debug]   data:  0x7e
[2025-05-14 16:15:09.342615] [0x0000007f7f94f180] [debug]   data:  0x5b 0
[2025-05-14 16:15:09.343628] [0x0000007f7f94f180] [debug]   data:  0x70 1
[2025-05-14 16:15:09.358392] [0x0000007f7f94f180] [debug]   data:  0x5b 0
[2025-05-14 16:15:09.358617] [0x0000007f7f94f180] [debug]   data:  0x7a 1
[2025-05-14 16:15:09.374358] [0x0000007f7f94f180] [debug]   data:  0x5b 0
[2025-05-14 16:15:09.374516] [0x0000007f7f94f180] [debug]   data:  0x79 1
[2025-05-14 16:15:09.391371] [0x0000007f7f94f180] [debug]   data:  0x5b 0
[2025-05-14 16:15:09.391552] [0x0000007f7f94f180] [debug]   data:  0x7f 1
[2025-05-14 16:15:09.391664] [0x0000007f7f94f180] [debug]   data:  0x64 2
[2025-05-14 16:15:09.914328] [0x0000007f7f94f180] [debug]   data:  0x7e
[2025-05-14 16:15:10.441791] [0x0000007f7f94f180] [debug]   data:  0x7e
[2025-05-14 16:15:10.970205] [0x0000007f7f94f180] [debug]   data:  0x7e
[2025-05-14 16:15:11.498423] [0x0000007f7f94f180] [debug]   data:  0x7e

each recived byte is displayed.

The packets from pc: 0x7e (1 Byte); 0x5b, 0x7f 0xDATA (3 Bytes); 0x5b, 0x70 (2 Bytes); 0x5b, 0x79 (2 Bytes); 0x5b, 0x7a (2 Bytes).

PC requests status with 0x7e and waits for status packet (0xaa, 0x89, 0x86, 0x00, 0x00, 0xf0). Packet (0x5b, 0x7f) is a set cmd and others must be acknowledged with ACK (0xaa in buf[0]).

Part 1: A synchronous example

#include <boost/asio/io_service.hpp>
#include <boost/asio/serial_port.hpp>
#include <boost/asio/read.hpp>
#include <boost/asio/write.hpp>
#include <boost/thread.hpp>
#include <boost/log/trivial.hpp>
#include <boost/format.hpp>

using namespace boost::asio;

uint8_t tmp_buf[8];
unsigned i {0};

void rs232Thr(){
    io_service io;
    serial_port serial(io);
    uint8_t data;
    std::size_t size = 0;

    serial.open("/dev/serial0");

    for(;;) {
        size = read(serial, buffer(&data, 1));

        if(size){
            uint8_t buf[] = {0xaa, 0x89, 0x86, 0x00, 0x00, 0xf0};
            if(0x7e == data){
                write(serial, buffer(buf, 6));
                BOOST_LOG_TRIVIAL(debug) << "data: " << (boost::format(" 0x%02x") % (int)data).str();
            }
            else if (tmp_buf[0] == 0x5B && (tmp_buf[1] == 0x70 || tmp_buf[1] == 0x79 || tmp_buf[1] == 0x7a) && i == 2 ) {
                i=0;
                write(serial, buffer(buf, 1));
            }
            else if (tmp_buf[0] == 0x5B && tmp_buf[1] == 0x7f && i == 3 ) {
                i=0;
                write(serial, buffer(buf, 1));
            }
            else {
                BOOST_LOG_TRIVIAL(debug) << "data: " << (boost::format(" 0x%02x") % (int)data).str() << " " << i;
                tmp_buf[i] = data;
                ++i;
            }
            size = 0;
        }
    }
}

int main () {

    boost::thread thr_serial{rs232Thr};

    thr_serial.join();

    return 0;
}

Part 2: An asynchronous example

void handler(const boost::system::error_code& error, long unsigned int size){
    if(error) printf("ERROR\n");
    // BOOST_LOG_TRIVIAL(debug) << __LINE__;
}

uint8_t tmp_buf[8];
unsigned i {0};

void rs232Thr(){
    io_service io;
    serial_port serial(io);
    uint8_t data;
    uint8_t tmp_data;
    std::size_t size = 0;
    boost::system::error_code ec{};

    serial.open("/dev/serial0");
    thr_nr = boost::this_thread::get_id();

    for(;;) {

        async_read(serial, buffer(&data, 1), [&ec, &size, &tmp_data, &data] (auto& err, auto s) {
            size = s;
            tmp_data = data; // data gehört zu "anderen Thread", deswegen Daten sollen schnell wie möglich ausgelesen werden
            handler(ec,s);
        });

        if(size){
            uint8_t buf[] = {0xaa, 0x89, 0x86, 0x00, 0x00, 0xf0};
            if(0x7e == tmp_data){
                // write(serial, buffer(buf, 6));
                async_write(serial, buffer(buf, 6), handler);
                BOOST_LOG_TRIVIAL(debug) << "data: " << (boost::format(" 0x%02x") % (int)tmp_data).str();
            }
            else if (tmp_buf[0] == 0x5B && (tmp_buf[1] == 0x70 || tmp_buf[1] == 0x79 || tmp_buf[1] == 0x7a) && i == 2 ) {
                i=0;
                // write(serial, buffer(buf, 1));
                async_write(serial, buffer(buf, 1), handler);
            }
            else if (tmp_buf[0] == 0x5B && tmp_buf[1] == 0x7f && i == 3 ) {
                i=0;
                // write(serial, buffer(buf, 1));
                async_write(serial, buffer(buf, 1), handler);
            }
            else {
                BOOST_LOG_TRIVIAL(debug) << "data: " << (boost::format(" 0x%02x") % (int)tmp_data).str() << " " << i;
                tmp_buf[i] = tmp_data;
                ++i;
            }
            size = 0;
        }

        io.reset();
        io.run();
    }
}

int main () {

    boost::thread thr_serial{rs232Thr};

    thr_serial.join();

    return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment