Tous mes périphériques microcontrôleurs qui communiquent avec le PC via UART utilisent des chaînes ASCII pour envoyer des commandes et recevoir des données (comme implémenté dans Arduino). C'est ce que j'ai appris lorsque j'ai commencé à creuser dans l'électronique et j'ai toujours trouvé que l'envoi de chaînes nues était suffisant. Cependant, j'ai remarqué que la plupart des appareils que j'ai rencontrés utilisent des protocoles binaires sophistiqués qui incluent des codes de fonction, des adresses et une vérification des erreurs CRC.
Quand la communication ASCII de base est-elle acceptable et quand devrais-je envisager quelque chose de plus avancé, comme Modbus? Les appareils commerciaux utilisent-ils un tel ASCII? Industriel?
microcontroller
serial
communication
uart
protocol
Je n'ai aucune idée de ce que je fais
la source
la source
Réponses:
ASCII et CRC ne s'excluent pas mutuellement. ASCII est un codage et CRC sert à la vérification des erreurs.
N'IMPORTE QUOI peut être envoyé en ASCII. Nous les anciens, nous nous souvenons certainement de UUEncoding, qui transforme n'importe quoi en chaîne ASCII.
A) Pour moi, c'est généralement une question de vitesse et d'efficacité. L'envoi d'un grand nombre 32 bits par ASCII peut prendre beaucoup de temps, mais il ne prend que 4 octets pour l'envoyer en binaire via un protocole série.
B) L'envoi de NUMÉROS via ASCII signifie que vous devez convertir le nombre en ASCII, ce qui est une étape supplémentaire claire (cela fait partie de ce que fait "printf").
Si vous perdez votre place, visser, perdre le format, obtenir le mauvais endian, etc., un protocole de communication binaire peut certainement bousiller. Si vous envoyez de l'ASCII, il peut être plus facile de récupérer des erreurs en entrant simplement et en REGARDANT le flux de données.
la source
Voici quelques réflexions à ce sujet:
la source
Au niveau le plus simple, on pourrait dire qu'un protocole de communication simple comporte trois couches: physique, transport et application. (Il existe des modèles avec plus comme OSI avec 7 ou TCP / IP avec 4. Le nombre de couches n'est pas très important dans le contexte de cette question.)
La couche application est la couche avec laquelle vous traitez directement dans votre code et le centre de la question. En ce qui concerne la couche transport, l'octet que vous lui avez transmis dans send_data n'est qu'un modèle binaire, mais vous pouvez l'interpréter dans votre code d'application comme la lettre «A». Le CRC ou le calcul de la somme de contrôle sera le même, que vous considériez l'octet comme «A», 0x41 ou 0b01000001.
La couche de transport est le niveau du paquet, où vous avez vos en-têtes de message et la vérification des erreurs, que ce soit CRC ou une somme de contrôle de base. Dans le contexte du firmware, vous pouvez avoir une fonction telle que send_data, où vous lui passez un octet à envoyer. A l'intérieur de cette fonction, il a mis dans un paquet qui dit: "Hé, c'est un message normal, nécessite un accusé de réception, et la somme de contrôle est 0x47, l'heure actuelle est X." Ce paquet est envoyé sur la couche physique au nœud récepteur.
La couche physique est l'endroit où l'électronique et l'interface sont définies: connecteurs, niveaux de tension, synchronisation, etc. Cette couche peut aller de quelques traces exécutant des signaux TTL pour un UART de base sur un PCB à une paire différentielle entièrement isolée comme dans certains POUVEZ .
Au niveau du nœud de réception, le paquet arrive sur la couche physique, est décompressé au niveau de la couche de transport, puis votre modèle binaire est disponible pour la couche d'application. Il appartient à la couche d'application du nœud récepteur de savoir si ce modèle doit être interprété comme «A», 0x41 ou 0b01000001, et quoi en faire.
En conclusion, il est à peu près toujours acceptable d'envoyer des caractères ASCII si c'est ce que demande l'application. L'important est de comprendre votre schéma de communication et d'inclure un mécanisme de vérification des erreurs.
la source
Un point non encore mentionné est que si l'on utilise ASCII ou un protocole binaire, l'envoi d'un caractère d'effacement avant chaque paquet garantira que même si du bruit de ligne ou des erreurs de trame apparaissent avant le début d'un paquet, tous les caractères après le rub- la sortie sera correctement cadrée en l'absence de bruit supplémentaire. Sinon, si l'on envoie des paquets en continu et n'inclut aucun caractère qui est garanti pour atteindre la resynchronisation, il est possible qu'un problème puisse corrompre tout ce qui suit jusqu'à la prochaine pause de transmission. Le caractère 0xFF est agréable car il garantit que tout destinataire pourra se resynchroniser sur le caractère suivant.
(*) 0xFF - appelé effacement parce que quelqu'un qui tape un caractère erroné en tapant des données sur une bande de papier peut pousser le bouton "step tape backward" et appuyer sur effacement pour remplacer le caractère erronément perforé par 0xFF, qui ignoré par la plupart des destinataires).
la source
L'un des avantages de l'envoi de chaînes ASCII est que les codes de contrôle peuvent ensuite être utilisés pour signaler le début / la fin du message. Par exemple, STX (caractère 2) et ETX (caractère 3) peuvent signaler la transmission de début et la transmission de fin. Vous pouvez également ajouter un simple saut de ligne pour marquer la fin de la transmission.
Lors de l'envoi de données binaires, cela devient plus compliqué car aucun modèle binaire particulier ne peut être réservé à un code de contrôle (sans surcharge ou complexité supplémentaire) car un octet de données valide peut avoir le même modèle.
la source
ASCII est très bien, je l'utilise dans à peu près tous les projets. Cela facilite le débogage pour surveiller le port, et cela ne deviendrait un problème que s'il y avait beaucoup de données à envoyer.
Un autre bonus, j'utilise des appareils radio série pour faire passer des messages entre Arduinos, et je peux utiliser un moniteur série connecté à mon ordinateur portable et injecter des messages pour que certaines choses se produisent. Idéal pour les tests.
De plus, envoyer des choses en binaire n'est pas impossible à déboguer et selon vos outils, vous pouvez faire extraire et convertir le binaire en quelque chose de lisible par l'homme. Ou si vous savez ce que vous recherchez, vous pouvez inspecter visuellement le flux de données et reconnaître les valeurs là où elles devraient être et trouver des défauts de cette façon, mais pas si facilement. c'est-à-dire que vous reconnaîtrez les modèles d'octets et reconnaîtrez les valeurs attendues
la source
Au lieu de Modbus, envisagez HDLC . Vous obtenez une détection d'erreur (ce qui est important sur les lignes série bruyantes). La synchronisation est robuste, l'échappement est robuste.
J'ai utilisé HDLC dans les réseaux RS-485 sans aucun problème et PPP l'utilise également.
la source
ASCII sur l'UART est le plus populaire en partie parce que:
Il est lisible par l'homme lors du débogage (je n'ai pas encore vu un analyseur logique qui ne décode pas ASCII).
C'est très facile à mettre en œuvre, vous avez une table ASCII via google rapide qui est bien standardisée.
Il a intégré la synchronisation avec les bits de démarrage / d'arrêt.
À peu près tout le monde hobbyst s'est installé avec ASCII sur série, donc toutes les nouvelles méthodes devront y faire face, et ce n'est pas facile du tout.
Ensuite, vous vous retrouvez dans une situation où vous commencez à envoyer un codage spécifique, tel que l'envoi de la représentation en mémoire d'un flotteur par rapport à la conversion d'un flotteur en ASCII, envoyez-le sur série qui peut être bien plus de 4 octets, puis convertissez-le à nouveau. à une représentation en mémoire sur l'hôte. Au lieu de cela, vous envoyez simplement la représentation à 4 octets à chaque fois. Bien sûr, vous pouvez commencer à gérer l'encodage vous-même, mais vous devez ensuite configurer des balises de début / fin, l'ordre, etc.
Au lieu de cela, des choses comme Protobuf peuvent être utilisées. Cela a été utilisé dans un projet sur lequel je travaillais et c'était extrêmement bénéfique, il fait des messages de longueur variable, gère l'endian pour vous et quelques autres fonctionnalités intéressantes. La taille du code n'est pas aussi grande et vous pouvez spécifier tout ce qui doit être alloué statiquement au démarrage. Vous devrez cependant ajouter vous-même la somme de contrôle si vous en avez besoin.
la source