Conexão Serial

A conexão serial é um tipo de conexão de comunicação que permite que dois dispositivos se comuniquem por meio de uma porta serial. A porta serial é uma interface física que permite que um dispositivo envie e receba dados por meio de um par de fios. Ela é comumente usada para se comunicar com dispositivos externos, como Arduinos, dispositivos de comunicação industrial e dispositivos de automação.

Asio

A biblioteca Asio inclui suporte para trabalhar com portas seriais, o que permite aos programadores escrever aplicativos que se comunicam com dispositivos seriais, como Arduino e dispositivos de comunicação industrial. Isso é útil quando é preciso enviar ou receber dados de um dispositivo por meio de uma porta serial, como em aplicativos de automação industrial ou em projetos de robótica.

Para usar a biblioteca Asio para trabalhar com portas seriais, é necessário incluir o cabeçalho #include <boost/asio.hpp> no início do seu código. Em seguida, é preciso criar uma instância de um objeto serial_port, que representa a porta serial a ser usada, e passar a ela as informações sobre a porta, como o nome da porta (por exemplo, "COM1" no Windows ou "/dev/ttyUSB0" no Linux) e a taxa de transmissão (baud rate).

Aqui está um exemplo de código que abre uma porta serial e envia uma mensagem pelo Arduino:

#include <boost/asio.hpp>
#include <iostream>

namespace asio = boost::asio;

int main() {
  // Cria um objeto boost::asio::io_context para gerenciar as operações de entrada/saída.
  asio::io_context io;

  // Cria um objeto boost::asio::serial_port para representar a porta serial.
  asio::serial_port serial(io, "/dev/ttyUSB0");

  // Configura a porta serial com a taxa de transmissão desejada.
  serial.set_option(asio::serial_port_base::baud_rate(9600));

  // Envia uma mensagem pelo Arduino.
  asio::write(serial, asio::buffer("Hello, Arduino!\n"));

  return 0;
}

Além de enviar e receber dados, você também pode configurar várias opções da porta serial usando a biblioteca Asio. Por exemplo, você pode definir o número de bits de dados, a paridade e o número de bits de parada usando as opções serial_port_base::character_size, serial_port_base::parity e serial_port_base::stop_bits, respectivamente. Aqui está um exemplo de como fazer isso:

serial.set_option(boost::asio::serial_port_base::character_size(8));
serial.set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none));
serial.set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one));

Você também pode definir o modo de fluxo de dados da porta serial usando as opções serial_port_base::flow_control. Por exemplo, para habilitar o controle de fluxo hardware (RTS/CTS), você pode usar o seguinte código:

serial.set_option(boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::hardware));

Além disso, a biblioteca permite que você trate eventos de interrupção da porta serial usando a classe serial_port_service. Isso é útil quando você precisa ser notificado quando a porta serial for interrompida, por exemplo, quando um dispositivo conectado à porta envia um sinal de interrupção. Para usar essa funcionalidade, você precisa criar um objeto serial_port_service e registrar um manipulador de eventos de interrupção usando a função async_wait_for_interrupt(). Aqui está um exemplo de como fazer isso:

#include <boost/asio/serial_port_service.hpp>

// Define uma função de callback para ser chamada quando a interrupção ocorrer.
void interrupt_callback(const boost::system::error_code& error) {
  if (!error) {
    // A interrupção ocorreu. Faça alguma coisa aqui.
    std::cout << "Interrupt received!" << std::endl;
  }
}

int main() {
    // Cria um objeto boost::asio::io_context para gerenciar as operações de entrada/saída.
    boost::asio::io_context io;

    // Cria um objeto boost::asio::serial_port para representar a porta serial.
    boost::asio::serial_port serial(io, "/dev/ttyUSB0");

    // Cria um objeto boost::asio::serial_port_service para tratar eventos de interrupção da porta serial
    boost::asio::serial_port_service serial_service(io);

    // Registra o manipulador de eventos de interrupção.
    serial_service.async_wait_for_interrupt(serial, interrupt_callback);

    // Executa o loop de eventos da biblioteca Asio. Isso fará com que o manipulador de interrupção seja chamado quando a interrupção ocorrer.
    io.run();
}

Essa é uma maneira de tratar eventos de interrupção da porta serial usando a biblioteca Asio. Note que você precisa executar o loop de eventos (chamando a função io_context::run()) para que os manipuladores de eventos sejam chamados quando os eventos ocorrerem.