Pergunta

Quero verificar os pacotes de dados recebidos na porta serial, usando boost.asio. Cada pacote de dados começará com um cabeçalho com um byte de comprimento e especificará que tipo da mensagem foi enviada. Cada tipo diferente de mensagem tem seu próprio comprimento. A função que quero escrever deve ouvir novas mensagens recebidas continuamente e, quando encontrar uma, deve lê -la e chamar outra função para analisá -la. Meu código atual é o seguinte:

void check_for_incoming_messages()
{
    boost::asio::streambuf response;
    boost::system::error_code error;
    std::string s1, s2;
    if (boost::asio::read(port, response, boost::asio::transfer_at_least(0), error)) {
        s1 = streambuf_to_string(response);
        int msg_code = s1[0];
        if (msg_code < 0 || msg_code >= NUM_MESSAGES) {
            // Handle error, invalid message header
        }
        if (boost::asio::read(port, response, boost::asio::transfer_at_least(message_lengths[msg_code]-s1.length()), error)) {
            s2 = streambuf_to_string(response);
            // Handle the content of s1 and s2
        }
        else if (error != boost::asio::error::eof) {
            throw boost::system::system_error(error);
        }
    }
    else if (error != boost::asio::error::eof) {
        throw boost::system::system_error(error);
    }
}

É boost::asio::streambuf a ferramenta certa para usar? E como faço para extrair os dados dele para poder analisar a mensagem? Também quero saber se preciso ter um encadeamento separado que apenas chama essa função, para que seja chamada com mais frequência. Devo estar preocupado em perder dados entre duas chamadas para a função devido ao buffer de alto tráfego e porta serial acabando? Estou usando as bibliotecas do QT para a GUI e realmente não sei quanto tempo leva para processar todos os eventos.

Editar: A pergunta interessante é: como posso verificar se existem dados recebidos na porta serial? Se não houver dados recebidos, não quero que a função bloqueie ...

Foi útil?

Solução

Este artigo é útil para entender como o ASIO pode ser usado de forma assíncrona com portas seriais:

Atualização (2019-03):

O artigo original que eu havia vinculado não está mais disponível e é difícil de encontrar, mesmo no arquivo da Internet. (Aqui está um instantâneo.). Agora existem artigos mais recentes sobre o uso da ASIO para E/S em série encontrados facilmente pesquisando, mas este artigo mais antigo ainda é muito útil. Estou colocando isso em uma essência pública para que não se perca:

O código descrito no artigo parece ter sido copiado aqui:

O autor parece ter atualizado para C ++ 11. Eu acredito que o artigo foi originalmente escrito por fede.tft.

Outras dicas

Jason,

Se for adequado para o seu aplicativo, eu recomendo implementar um RX serial assíncrono baseado em retorno de chamada. Como faço para executar uma leitura sem bloqueio usando o ASIO? Tem um ótimo exemplo de como implementar a série de assíncrios com um tempo limite. Como você reconheceu, ele exigirá uma implementação multithread para obter as vantagens de desempenho; portanto, você precisará pensar em onde seus dados recebidos serão em buffer para garantir que você não esteja cópia.

Na medida em que boost::streambuff As coisas vão, eu pessoalmente prefiro apenas bloquear alguma memória como uma matriz de char - char m_RXBuffer[m_RXBuffSize] E use boost::asio::buffer(m_RXBuffer, m_RXBuffSize) Para passar o buffer de destino para async_read_some. Em particular para o RS232, sempre descobri o fato de que os dados subjacentes são um fluxo de bytes naturalmente mapeia muito melhor em uma simples matriz de char do que qualquer uma das estruturas de dados mais complexas.

Boa sorte!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top