Dans ma communication UART, j'ai besoin de connaître l'octet de début et l'octet d'arrêt du message envoyé. L'octet de début est facile mais l'octet d'arrêt, pas tellement. J'ai implémenté deux octets d'arrêt à la fin de mon message, c'est-à-dire \ n et \ r (10 et 13 décimales). UART ne fonctionne que sur les valeurs d'octets 0-255, alors à quel point est-ce sûr? Je peux imaginer, bien que peu probable, que mon message puisse contenir les valeurs "10 et 13" les unes après les autres alors qu'il ne s'agit pas des octets d'arrêt.
Existe-t-il une meilleure façon de mettre cela en œuvre?
"\x0D\x0A"
.\r\n\r\n
qui contient la\n\r
séquence au milieu ...Réponses:
Il existe différentes façons d'empêcher cela:
Si vos messages font au maximum 256 octets, envoyez:
Donc, vous savez, après avoir reçu 6 octets de données, c'est la fin; vous n'avez pas besoin d'envoyer un 10 13 par la suite. Et vous pouvez envoyer 10 13 dans un message. Si vos messages peuvent être plus longs, vous pouvez utiliser 2 octets pour la taille des données.
Mise à jour 1: une autre façon de définir les paquets
Une autre alternative consiste à envoyer des commandes qui ont une longueur spécifique et peuvent avoir de nombreux écarts, par exemple
Mise à jour 2: Mauvaise connexion / pertes d'octets
Tout ce qui précède ne fonctionne que lorsque la ligne UART envoie correctement les octets. Si vous souhaitez utiliser des moyens d'envoi plus fiables, il existe également de nombreuses possibilités. En voici quelques-uns:
Notez que tous les mécanismes ci-dessus peuvent être simples ou aussi compliqués que vous le souhaitez (ou devez) être. En cas de renvoi de message, un mécanisme d'identification des messages est également nécessaire (par exemple, l'ajout d'un numéro de séquence dans le paquet).
la source
Si vous envoyez envoyer des données arbitraires -> probablement pas assez sûr.
Une solution courante consiste à utiliser l'échappement:
Définissons que les caractères 0x02 (STX - début de trame) et 0x03 (ETX - fin de trame) doivent être uniques dans le flux de données transmis. De cette façon, le début et la fin d'un message peuvent être détectés en toute sécurité.
Si l'un de ces caractères doit être envoyé dans le cadre du message, il est remplacé par le préfixe d'un caractère d'échappement (ESC = 0x1b) et l'ajout de 0x20 au caractère d'origine.
Caractère original remplacé par
Le récepteur inverse ce processus: chaque fois qu'il reçoit un caractère d'échappement, ce caractère est supprimé et le caractère suivant est soustrait par 0x20.
Cela ne fait qu'ajouter des frais généraux de traitement mais est fiable à 100% (en supposant qu'aucune erreur de transmission ne se produise, que vous pourriez / devriez vérifier en implémentant en outre un mécanisme de somme de contrôle).
la source
'\x10'
DLE (Data Link Escape). Certaines pages de Wikipédia suggèrent que le DLE était souvent utilisé dans le sens inverse: pour dire que l'octet suivant était un caractère de contrôle plutôt qu'un octet de données. D'après mon expérience, c'est généralement le sens opposé d'une évasion.Vous savez, ASCII a déjà des octets pour ces fonctions.
Il a également des codes pour diverses utilisations à l'intérieur de la charge utile.
Votre protocole doit spécifier la granularité la plus fine de ACK (0x06) et NAK (0x15), afin que les données acquittées négatives puissent être retransmises. Jusqu'à cette granularité la plus fine, il est sage d'avoir un champ de longueur immédiatement après tout indicateur de démarrage (non échappé) et (comme expliqué dans d'autres réponses), il est sage de suivre tout indicateur d'arrêt (non échappé) avec un CRC.
la source
L'UART n'est pas à sécurité intrinsèque par sa nature même - nous parlons ici de la technologie des années 60.
La racine du problème est que l'UART ne se synchronise qu'une fois par 10 bits, ce qui permet à beaucoup de charabia de passer entre ces périodes de synchronisation. Contrairement à CAN par exemple, qui échantillonne chaque bit individuel plusieurs fois.
Toute erreur double bit se produisant à l'intérieur des données corrompra une trame UART et passera sans être détectée. Les erreurs de bits dans les bits de démarrage / d'arrêt peuvent ou non être détectées sous la forme d'erreurs de dépassement.
Par conséquent, peu importe si vous utilisez des données brutes ou des paquets, il y a toujours une probabilité que les retournements de bits causés par EMI entraînent des données inattendues.
Il existe de nombreuses façons de "charlatanisme UART traditionnel" pour améliorer légèrement la situation. Vous pouvez ajouter des octets de synchronisation, des bits de synchronisation, la parité, des bits d'arrêt double. Vous pouvez ajouter des sommes de contrôle qui comptent la somme de tous les octets (puis l'inverser - parce que pourquoi pas) ou vous pouvez compter le nombre de binaires comme une somme de contrôle. Tout cela est largement utilisé, très peu scientifique et avec une forte probabilité d'erreurs manquantes. Mais c'est ce que les gens ont fait des années 1960 aux années 1990 et beaucoup de choses étranges comme celles-ci continuent aujourd'hui.
La manière la plus professionnelle de gérer une transmission sûre sur UART est d'avoir une somme de contrôle CRC 16 bits à la fin du paquet. Tout le reste n'est pas très sûr et a une forte probabilité d'erreurs manquantes.
Ensuite, au niveau matériel, vous pouvez utiliser le différentiel RS-422 / RS-485 pour améliorer considérablement la robustesse de la transmission. C'est un must pour une transmission sûre sur de plus longues distances. L'UART de niveau TTL ne doit être utilisé que pour la communication à bord. RS-232 ne doit pas être utilisé à d'autres fins que la rétrocompatibilité avec des éléments anciens.
Dans l'ensemble, plus le mécanisme de détection d'erreur est proche du matériel, plus il est efficace. En termes d'efficacité, les signaux différentiels ajoutent le plus, suivi de la vérification des erreurs de cadrage / dépassement, etc. CRC16 en ajoute, puis le "charlatanisme UART traditionnel" en ajoute un peu.
la source
Une situation où une partie des données est égale à la séquence de terminaison doit être prise en compte lors de la conception du format d'un paquet de données série. Une autre chose à considérer est que n'importe quel personnage peut être corrompu ou perdu pendant la transmission. Un caractère de début, un caractère d'arrêt, un octet de charge utile de données, une somme de contrôle ou un octet CRC, un octet de correction d'erreur directe ne sont pas à l'abri de la corruption. Le mécanisme de tramage doit pouvoir détecter lorsqu'un paquet contient des données corrompues.
Il y a plusieurs façons d'aborder tout cela.
Je fais l'hypothèse de travail que les paquets sont encadrés uniquement avec les octets série. Les lignes de poignée de main ne sont pas utilisées pour le cadrage. Les délais ne sont pas utilisés pour le cadrage.
Envoyer la longueur du paquet
Envoyez la longueur du paquet au début, au lieu de [ou en plus de] le caractère de fin à la fin.
avantages: la charge utile est envoyée dans un format binaire efficace.
inconvénients: Besoin de connaître la longueur du paquet au début de la transmission.
Échapper aux personnages spéciaux
Échappez aux caractères spéciaux lors de l'envoi des données utiles. Ceci est déjà expliqué dans une réponse antérieure .
avantages: l' expéditeur n'a pas besoin de connaître la longueur du paquet au début de la transmission.
inconvénients: légèrement moins efficace, selon le nombre d'octets de charge utile à échapper.
Données utiles codées de manière à ne pas pouvoir contenir de caractères de début et de fin
La charge utile du paquet est codée de telle sorte qu'elle ne peut pas contenir les caractères de début ou d'arrêt. Habituellement, cela se fait en envoyant des nombres en tant que leur représentation ASCII ou Hex-ASCII.
Avantages: lisibles par l'homme avec des programmes terminaux courants. Pas besoin de code pour gérer l'échappement. Pas besoin de connaître la longueur du paquet au début de la transmission
inconvénients: efficacité moindre. Pour un octet de données utiles, plusieurs octets sont envoyés.
la source