La lecture du port série avec Boost Asio
Je veux vérifier pour la réception des paquets de données sur le port série, à l'aide de boost.asio
. Chaque paquet de données va commencer avec un en-tête qui est un octet de long, et préciser quel est le type de message a été envoyé. Chaque type de message a sa propre longueur. La fonction que je veux écrire, il doit écouter les nouveaux messages entrants en permanence, et quand il en trouve un, il devrait le lire, et d'appeler une autre fonction pour l'analyser. Mon code est comme suit:
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);
}
}
Est boost::asio::streambuf
le bon outil à utiliser? Et comment puis-je extraire les données à partir d'elle pour que je puisse analyser le message? Je veux aussi savoir si j'ai besoin d'avoir un thread qui appelle cette fonction, de sorte qu'il est appelé le plus souvent. Devrais-je être inquiet de perdre des données entre deux appels à la fonction en raison de la forte circulation et d'un port série du tampon de course? Je suis à l'aide de bibliothèques Qt pour l'interface graphique et je ne sais pas vraiment combien de temps il faut pour traiter tous les événements.
Edit: La question intéressante est: comment puis-je vérifier si il n'y a aucune données entrantes sur le port série? Si il n'y a pas de données entrantes, je ne veux pas la fonction pour bloquer les...
OriginalL'auteur HelloGoodbye | 2010-05-10
Vous devez vous connecter pour publier un commentaire.
Cet article est utile pour comprendre comment les ASIO peut être utilisé de manière asynchrone avec les ports série:
Mise à JOUR (2019-03):
L'article original, j'ai eu liée à l'est n'est plus disponible et est difficile à trouver, même dans les Archives d'Internet. (Ici est un instantané.). Il y a maintenant des articles plus récents sur l'utilisation de l'ASIO pour e/S de série trouvés facilement par la recherche, mais cette article plus ancien est toujours très utile. Je suis en train de mettre ça dans un lieu public essentiel, afin de ne pas se perdre. Le code décrit dans l'article semble avoir été copié ici:
L'auteur semble avoir mis à jour pour le C++11. Je crois que l'article a été
écrit à l'origine par la fede.tft.
J'ai trouvé que j'ai eu à lire de manière asynchrone afin de ne pas perturber le déroulement du programme. Avant, j'ai été en utilisant le
read
fonction, tandis queasync_read
était la fonction correcte. Il en va de même pour l'écriture,async_write
doit être utilisé pour empêcher le programme de congélation le programme si la lecture par une raison quelconque fait une pause.pourriez-vous partager avec moi le code source de la page web de la fede? Le site est maintenant déménagé à Internet Archive et ne peut pas cloner plus. Merci!!!!
Je m'attends à la source d'origine seront disponibles pour le clonage bientôt sur Internet Archive. Toutefois, la source de l'article original semble également être disponible sur Github: github.com/fedetft/serial-port
OriginalL'auteur kaliatech
Jason,
S'il est approprié pour votre application, je recommande fortement la mise en œuvre d'un rappel asynchrone basé sur série RX. Comment dois-je effectuer une lecture non bloquante à l'aide asio? a un peu grand exemple de la façon de mettre en œuvre asynch de série avec un délai d'attente. Comme vous l'avez reconnu, il aura besoin d'un multi-thread de mise en œuvre pour obtenir les avantages de performance, de sorte que vous aurez besoin de mettre une certaine pensée où votre reçu de données seront mis à assurez-vous que vous ne faites pas beaucoup de copie.
Autant que la
boost::streambuff
des choses, personnellement, je préfère juste pour bloquer la mémoire comme un tableau de char -char m_RXBuffer[m_RXBuffSize]
et l'utilisationboost::asio::buffer(m_RXBuffer, m_RXBuffSize)
passer la cible de la mémoire tampon dansasync_read_some
. En particulier pour RS232, j'ai toujours trouvé que le fait que les données sous-jacentes est un flux d'octets naturellement cartes beaucoup mieux sur un simple tableau de char que n'importe quel de plus de structures de données complexes.Bonne Chance!
OriginalL'auteur OcularProgrammer