Qu'est-ce qui cause les erreurs UART?

8

Je voudrais savoir pourquoi les erreurs UART se produisent et quand il faut vérifier ces erreurs. Il y a un article ici qui pose des questions sur la gestion des erreurs individuelles, telles que le dépassement, la parité, etc. Ma question est plus centrée sur la raison pour laquelle ces erreurs peuvent se produire (raisons physiques) et sur le moment de faire de la vérification des erreurs un facteur pour leur application.

Jusqu'à présent, mon programme semble fonctionner très bien (sans vérification d'erreur), mais je sais que le bruit peut gâcher les choses. Comment pourrais-je simuler des conditions qui pourraient entraîner l'échec des ports UART Rx / Tx?

user791953
la source

Réponses:

8

Il existe plusieurs sources potentielles de bruit dans n'importe quel circuit. Parmi les plus courants, citons:

  • Alimentations mal régulées;
  • Alimentations à découpage;
  • Découplage capacitif insuffisant des rails d'alimentation à proximité du MCU;
  • Couplage inductif de sources électromagnétiques à proximité (y compris à 50 ou 60 Hz de l'alimentation secteur; même si le circuit est alimenté par batterie, il subira cette interférence lorsqu'il sera suffisamment proche d'une source d'alimentation);
  • Sources RF proches de la fréquence de résonance d'une trace sur la carte de circuit imprimé ou de l'une de ses harmoniques;
  • Acheminement des traces de courant élevé sur la carte de circuit imprimé près des lignes de signaux;
  • Etc.

De plus (comme @jippie l'a mentionné), le décalage d'horloge est une cause très courante d'erreurs dans tout type de communication série qui utilise un débit de données prédéterminé. Si vous utilisez un cristal externe et que vous vous connectez à un autre système dont on peut raisonnablement s'attendre à ce qu'il soit précis, il est moins susceptible de causer des problèmes. Cependant, les oscillateurs internes peuvent avoir des tolérances qui sont de plusieurs ordres de grandeur pires que les cristaux, et ont tendance à varier davantage dans les plages de températures.

Il existe plusieurs tests de base qui peuvent être effectués sur un système en cours d'exécution pour déterminer l'immunité de base au bruit (et à l'inclinaison) de votre interface, notamment:

  • Gel (refroidir le circuit à la valeur minimale de ses composants);
  • Cuisson (chauffer à la puissance maximale);
  • Exposition aux EMI :
    • Réglez la carte sur le dessus du cordon d'alimentation d'un chauffage d'appoint;
    • Clé une radio CB à proximité immédiate de la carte;
    • Placez la carte à côté de votre routeur sans fil;
    • Utilisez un long fil de raccordement (au lieu d'un câble série correctement construit) pour la connexion UART.

Il en existe de nombreux autres - en fait, il existe de grands laboratoires de test dédiés à la qualification EMC .

En général, à moins qu'un certain niveau minimal de perte de données ne soit acceptable, il est toujours prudent d'inclure une sorte de vérification d'erreur dans votre code de communication. Même une simple somme de contrôle vaut mieux que rien.

Scott Winder
la source
6

En plus de la qualité du niveau de signal (bruit, temps de montée / descente), une source d'erreur courante sur l'UART est le décalage d'horloge. Si l'horloge de l'émetteur et celle du récepteur ne proviennent pas de la même source (ce qui est le cas la plupart du temps), alors l'une fonctionnera plus rapidement que l'autre. Lorsque l'erreur de synchronisation est trop importante, vous pouvez parfois lire un mauvais bit.

jippie
la source
Qu'est-ce qui ferait déformer l'horloge si le microcontrôleur était laissé seul dans une boîte noire, au milieu de qui sait où?
user791953
1
Horloges locales gratuites. Chaque oscillateur a sa propre précision. L'horloge MCU peut être divisée en une fréquence utilisable pour UART, mais parfois elle est désactivée par un petit pourcentage. Ceci est à son tour causé par le fait que le diviseur est un nombre entier.
jippie
Par exemple. Horloge MCU = 16 MHz, vitesse de transmission UART = 9600Bd. Ensuite, l'UART est généralement cadencé à 153600Hz. Mais 16000000/153600 n'est pas un nombre entier, donc le débit en bauds sera désactivé.
jippie
Bon, cela donnera un petit pourcentage d'erreur. Je suppose que j'ai eu la chance de ne pas avoir rencontré d'erreurs, mais s'il s'agit de données critiques, les vérifications doivent toujours être effectuées.
user791953
Vitesse de transmission plus faible, fréquence d'horloge plus élevée (augmente la résolution d'échantillonnage et la précision de synchronisation).
jippie
1

La plupart des erreurs proviennent de trois causes: (1) le signal généré par l'émetteur ne représentait pas des données valides; (2) le signal de l'émetteur n'a pas été reçu tel qu'il a été généré, ou (3) le récepteur n'était pas prêt à traiter les données lors de leur réception. La cause la plus courante que j'ai vue pour le problème # 1 est un émetteur qui se reconfigure ou s'arrête pendant qu'il transmet des données. Le problème n ° 2 peut facilement se produire pour les signaux voyageant à travers le "monde extérieur" à la suite de choses comme les interférences radio (les téléphones portables peuvent être étonnamment désagréables!), Mais ne devrait généralement pas se produire pour les signaux confinés à une seule carte. Le problème n ° 3 peut se produire soit parce que trop d'octets arrivent plus rapidement qu'ils ne peuvent être traités, soit parce que le récepteur est reconfiguré, arrêté ou démarré pendant une transmission.

Dans de nombreux cas, il est difficile d'éliminer complètement tous ces problèmes; son objectif devrait être de s'assurer que le "dommage" total causé par eux (probabilité d'occurrence, multiplié par les dommages par occurrence) est suffisamment faible. Cela peut être fait le plus facilement en choisissant une estimation pessimiste de la fiabilité, puis en concevant un protocole afin que l'impact sur les performances du système, même les pires pannes qui soient cohérentes avec ses estimations, soit dans des limites acceptables.

supercat
la source
0

Les erreurs de cadrage peuvent être causées par ce que @jippie mentionne - le récepteur a détecté le bit de début et là où il attend le bit d'arrêt, les données sont inversées. Cela peut également être dû à une corruption des données causée par des interférences de ligne affectant le bit d'arrêt. Vous devez toujours vérifier cela pour chaque octet reçu.

Des erreurs de parité se produisent lorsque la parité est implémentée sur la liaison de données et qu'il y a une corruption qui provoque un décalage de parité dans les données reçues. Vous devez toujours vérifier cela pour chaque octet reçu.

La coupure de réception est également considérée comme une erreur bien que ce soit vraiment une indication que les données entrantes sont tombées à zéro logique pendant plus d'un octet de données. Normalement logique 1 est l'état "ambiant" entre les octets de données successifs et il en reste ainsi. C'est un retour aux vieux systèmes de télégraphie, je pense. Je ne prendrais pas la peine de vérifier cela à moins que vous n'utilisiez cette "fonctionnalité" pour indiquer (par exemple) une commande de réinitialisation au récepteur.

L'erreur de dépassement survient lorsqu'un nouvel octet est reçu avant que l'octet précédent n'ait été lu par une CPU. Légèrement différent lorsqu'un FIFO est impliqué, mais revient à la même chose - les données reçues valides sont perdues en raison de la lenteur du processeur. Vérifiez toujours cela avant de lire un octet et si l'octet fait partie d'un message (ou d'une commande) plus long, jetez l'ensemble du message / de la commande et demandez en quelque sorte à l'émetteur de renvoyer l'intégralité du message / de la commande.

Under run n'est pas vraiment une erreur mais indique à l'UART émetteur que son tampon de transmission est vide c'est-à-dire qu'il demande un nouvel octet à transmettre. Vous n'avez pas besoin de vérifier cela.

Andy aka
la source
Je comprends quelles sont ces erreurs et pourquoi elles se produisent, ma question est plutôt de savoir quand devrait-on fournir une vérification des erreurs pour elles.
user791953
@ user791953 - fait
Andy aka
BTW, underrun n'est pas un problème avec la plupart des protocoles, mais certains protocoles utilisent une ligne inactive pour indiquer la fin du paquet. Dans de tels cas, une sous-exécution du côté émission peut amener le récepteur à penser à tort que le paquet se termine avant qu'il ne soit censé le faire.
supercat
0

Pour gérer ces erreurs, vous devez implémenter un protocole logique de niveau supérieur. quelque chose de semblable à TCP, ou vérifiez la pile OSI pour des idées.

fondamentalement, deux parties importantes pour commencer sont les sommes de contrôle et les délais d'expiration. utiliser un algorithme pour calculer une valeur redondante qui représente, sous une forme plus petite, le contenu de chaque message. puis vérifiez cela dans le message reçu. si les sommes ne correspondent pas, vous avez peut-être obtenu une erreur de cadrage, du bruit de bits, etc., et vous devrez rejeter le message et tenter une sorte de récupération, renvoyer, signal NACK (non reconnu), etc.

assurez-vous également d'implémenter des délais d'expiration dans votre protocole de niveau supérieur. si vous obtenez une sorte d'erreur de cadrage, votre UART peut ne jamais récupérer et recommencer le traitement. il peut attendre le bit d'arrêt sur une trame que l'expéditeur pense que l'UART a déjà été envoyée, mais a été corrompu par du bruit, un décalage d'horloge, etc. cela enverra tout code d'entrée dans une boucle infinie. assurez-vous que vous avez une limite raisonnable quant au temps que votre lecture d'entrée doit attendre avant de décider d'abandonner ce message, et encore, réessayez, NACK, abandonnez, etc.

Andyz Smith
la source
Les délais d'attente doivent être mis en œuvre sur au moins un côté de tout protocole de niveau supérieur; dans de nombreux cas, il est préférable de les implémenter d'un seul côté. Avoir un côté attendant pour toujours des données qui n'arrivent jamais n'est un problème que s'il y a autre chose d'utile qu'il aurait pu faire à la place. Si X demande à Y des données, X devra être prêt à renvoyer sa demande au cas où Y ne la recevrait pas. Y, cependant, n'aura pas à se soucier de savoir si X obtient sa réponse. Si X ne l'obtient pas, X demandera à nouveau les données. Le fait que X ne demande pas à nouveau les données signifie que Y n'a pas besoin de les renvoyer.
supercat
@supercat à droite, c'est un bon schéma, mais je vise davantage le codage ligne par ligne de bas niveau. vous allez toujours avoir une boucle qui lit les données et essaie de savoir si un message complet est prêt, si un message complet n'est jamais là, il peut bloquer le sous-système d'entrée, qu'il n'y ait rien d'autre que d'attendre d'être terminé. dans ce cas, le sous-système d'entrée doit au moins se rendre compte qu'une défaillance s'est produite, vider toutes les données de gabage et être réinitialisé pour un nouvel essai.
Andyz Smith
Si chaque paquet commence par une séquence d'octets qui est toujours identifiable dans n'importe quel contexte, et si le récepteur n'a rien d'utile qu'il peut faire jusqu'à ce qu'il reçoive un paquet complet, pourquoi devrait-il s'en soucier si quelques heures s'écoulent après avoir reçu un paquet partiel? La prochaine fois que quelqu'un essaie d'envoyer un vrai paquet, le récepteur verra le marqueur de début de paquet et abandonnera le paquet partiel.
supercat
@supercat car vous avez alors une boucle qui recherche plusieurs choses. il cherche toujours la fin du paquet partiel, et il cherche le début d'un paquet frais et non corrompu. cela rend la logique beaucoup plus complexe en termes de codage pratique, si c'est le cas.
Andyz Smith
Je ne sais pas trop quelle est la difficulté. Si l'on utilise une boucle de réception d'octets, il faudra en sortir si un délai d'attente se produit ou si un octet de démarrage est vu. Les deux comportements doivent être gérés de manière identique, sauf pour le fait que la séquence de démarrage doit définir un indicateur, de sorte que le code suivant qui le recherchera ne dérangera pas.
supercat