UARTエラーの原因は何ですか?


8

UARTエラーが発生する理由と、そのようなエラーをチェックするタイミングを知りたいのですが。ここに、オーバーラン、パリティなどの個々のエラーの処理について尋ねる投稿があります。データオーバーランが発生する理由、パリティエラーが発生する理由は明らかですが、根本的な原因を知りたいのですが。私の質問は、これらのエラーが発生する理由(物理的な理由)と、エラーチェックをアプリケーションの要因にすべき場合に焦点を当てています。

これまでのところ、私のプログラムは(エラーチェックなしで)うまく機能しているように見えますが、ノイズによって混乱が生じる可能性があることはわかっています。UART Rx / Txポートが失敗する原因となる条件をどのようにシミュレートできますか?

回答:


8

どの回路にも、ノイズの発生源がいくつかあります。最も一般的なものは次のとおりです。

  • 安定化されていない電源;
  • スイッチング電源;
  • MCUの近くの電源レールの容量性デカップリングが不十分です。
  • 近くの電磁源の誘導結合(主電源からの50または60Hzを含む。回路が電池式の場合でも、主電源に十分近づくと、この干渉が発生します)。
  • 回路基板上のトレースの共振周波数またはその高調波の1つに近いRFソース。
  • 信号線近くの回路基板上の大電流トレースのルーティング。
  • 等。

さらに、(@ jippieが言及したように)クロックスキューは、所定のデータレートを使用するあらゆる種類のシリアル通信におけるエラーの非常に一般的な原因です。外部水晶を使用しており、正確であると合理的に期待できる別のシステムとのインターフェースを使用している場合、問題が発生する可能性は低くなります。ただし、内部発振器は、水晶よりも数桁も悪い許容誤差を持ち、温度範囲全体でさらに変動する傾向があります。

実行中のシステムで実行できる、インターフェイスの基本的なノイズ(およびスキュー)耐性を判断するためのいくつかの基本的なテストがあります。

  • 凍結(回路をそのコンポーネントの最小定格まで冷却)。
  • ベーキング(最大定格まで加熱)。
  • EMIへの暴露:
    • ランニングスペースヒーターの電源コードの上にボードを置きます。
    • ボードの近くでCBラジオをキーイングします。
    • ボードをワイヤレスルーターの隣に置きます。
    • UART接続には、(適切に構成されたシリアルケーブルの代わりに)長い接続線を使用します。

他にもたくさんあります-実際、EMC認定に特化した大規模な試験所があります。

一般に、データ損失の最小レベルが許容できる場合を除き、通信コードに何らかのエラーチェックを含めることは常に賢明です。単純なチェックサムでも、何もないよりはましです。


6

信号レベル品質(ノイズ、立ち上がり/立ち下がり時間)に加えて、UARTのエラーの一般的な原因の1つは、クロックスキューです。トランスミッタークロックとレシーバークロックが同じソースから派生していない場合(ほとんどの場合)、一方が他方より速く実行されます。タイミングエラーが大きすぎると、間違ったビットを読み取ることがあります。


マイクロコントローラがブラックボックスに一人で置かれた場合、誰がどこを知っているかの真ん中に、クロックが歪む原因は何でしょうか?
user791953 2013

1
フリーランニングのローカル時計。すべての発振器には独自の精度があります。MCUクロックはUARTで使用可能な周波数に分割できますが、わずかな割合でずれている場合があります。これは、除数が整数であることにより発生します。
ジッピー2013

例えば。MCUクロック= 16MHz、UARTボーレート= 9600Bd。次に、UARTは通常153600Hzでクロックされます。ただし、16000000/153600は整数ではないため、ボーレートはオフになります。
ジッピー2013

そう、それは小さなエラー率を与えるでしょう。エラーが発生しなかったのは幸運だったと思いますが、それが重要なデータである場合は、常にチェックを行う必要があります。
user791953 2013

ボーレートが低く、クロックレートが高い(サンプリング解像度とタイミング精度が向上)。
ジッピー2013

1

ほとんどのエラーは、次の3つの原因から生じます。(2)送信機の信号が生成されたときに受信されなかったか、(3)受信時にデータを処理する準備ができていませんでした。私が問題1で見た最も一般的な原因は、データを送信している間に再構成またはシャットダウンされるトランスミッタです。問題#2は、電波干渉などの結果として「外の世界」を移動する信号で簡単に発生する可能性があります(携帯電話は意外に厄介な場合があります!)。問題#3は、処理できるバイト数よりも速く到着するバイト数が多すぎるか、送信中にレシーバーが再構成、シャットダウン、または起動されたために発生します。

多くの場合、これらの問題をすべて完全になくすことは困難です。彼らの目標は、彼らによって行われる「損害」の合計(発生の確率、発生ごとの損害の倍数)が許容範囲内であることを確実にすることです。これは、信頼性の悲観的な見積もりを選択し、自分の見積もりと一致していた最悪の障害がシステムパフォーマンスに与える影響が許容範囲内になるようにプロトコルを設計することによって、最も簡単に行うことができます。


0

フレーミングエラーは、@ jippieが言及していることによって発生する可能性があります-レシーバーはスタートビットを検出し、ストップビットが予期される場所でデータが反転します。これは、ストップビットに影響を与えるライン干渉によって引き起こされるデータ破損が原因である可能性もあります。受信したバイトごとに常にこれを確認する必要があります。

パリティエラーは、データリンクにパリティが実装されていて、受信データにパリティの不一致を引き起こす破損がある場合に発生します。受信したバイトごとに常にこれを確認する必要があります。

受信ブレークもエラーと見なされますが、これは実際には、着信データが1バイトを超えるデータの間に論理ゼロに落ちたことを示しています。通常、論理1は、連続するデータバイト間の「周囲の」状態であり、このままです。それは私が思う古い電信システムへの回帰です。この "機能"を使用して(たとえば)リセットコマンドをレシーバーに示す場合を除いて、私はこれをチェックしません。

オーバーランエラーは、前のバイトがCPUによって読み取られる前に新しいバイトが受信された場合です。FIFOが含まれる場合は少し異なりますが、同じことになります。有効な受信データはCPUの速度低下により失われます。バイトを読み取る前に必ずこれを確認し、バイトが長いメッセージ(またはコマンド)の一部である場合は、メッセージ/コマンド全体を破棄し、何らかの方法でトランスミッターにメッセージ/コマンド全体を再送信するように要求します。

アンダーランは実際にはエラーではありませんが、送信バッファに空であること、つまり新しいバイトを送信するよう要求していることを送信UARTに示します。これを確認する必要はありません。


私はこれらのエラーが何であり、なぜ発生するかを理解しています。私の質問は、いつエラーチェックを提供する必要があるのか​​ということです。
user791953 2013

@ user791953-完了
Andy aka

ところで、ほとんどのプロトコルではアンダーランは問題になりませんが、一部のプロトコルはアイドルラインを使用してパケットの終わりを示します。このような場合、送信側のアンダーランにより、受信者はパケットが想定されているよりも前に終了すると誤って判断することがあります。
スーパーキャット2013

0

これらのエラーに対処するには、より高いレベルの論理プロトコルを実装する必要があります。TCPに似たもの、またはOSIスタックのアイデアを確認してください。

基本的に、最初に開始する2つの重要な部分は、チェックサムとタイムアウトです。アルゴリズムを使用して、各メッセージの内容をより小さな形式で表す冗長値を計算します。次に、受信したメッセージでこれを確認します。合計が一致しない場合は、フレーミングエラー、ビットノイズなどが発生している可能性があります。メッセージを破棄して、なんらかの回復、再送信、NACK(確認応答されていない)信号などを試行する必要があります。

また、上位レベルのプロトコルにタイムアウトを実装してください。何らかのフレーミングエラーが発生した場合、UARTが回復せず、再び処理を開始する場合があります。送信側UARTが送信済みであると考えるフレームでストップビットを待機している可能性がありますが、ノイズやクロックスキューなどによって破損しています。これにより、入力コードが無限ループに送信されます。このメッセージを破棄することを決定するまで入力の読み取りを待機する必要がある時間について、適切な制限があることを確認し、再度、再試行、NACK、破棄などを行います。


タイムアウトは、上位レベルのプロトコルの少なくとも片側に実装する必要があります。多くの場合、正確に片側に実装するのが最善です。片方が到着しないデータを永久に待機することは、代わりに何か有用なことがあった場合にのみ問題になります。XがYにデータを要求した場合、Yがデータを受信しない場合に備えて、Xが要求を再送信する準備をする必要があります。ただし、YはXが応答を受け取るかどうかを心配する必要はありません。Xがそれを取得しない場合、Xはデータを再度要求します。Xがデータを再度要求しないという事実は、Yがデータを再送信する必要がないことを意味します。
スーパーキャット2013

@supercat正しい、これは良いパターンですが、私は低レベルの行ごとのコーディングにもっと向けています。常にデータを読み取るループがあり、完全なメッセージの準備ができているかどうかを把握しようとします。完全なメッセージがそこにない場合、それ以外に何もないかどうかに関係なく、入力サブシステムがハングする可能性があります。完了しました。この場合、入力サブシステムは、少なくとも障害が発生したことを認識し、ガベージデータをフラッシュして、再試行のためにリセットする必要があります。
Andyz Smith 2013

各パケットが任意のコンテキストで常に識別可能なバイトシーケンスで始まり、レシーバーが完全なパケットを受信するまで何もできない場合は、部分的なパケットを受信して​​から数時間経過しても問題ないのはなぜですか?次に誰かが実際のパケットを送信しようとすると、受信者はパケット開始マーカーを確認し、部分的なパケットを破棄します。
スーパーキャット2013

@supercatは、複数のものを探すループがあるためです。まだ部分的なパケットの終わりを探しており、破損していない新しいパケットの始まりを探しています。これにより、実際にコーディングしている場合でも、実際的な意味でロジックがより複雑になります。
Andyz Smith 2013

何が難しいのかよくわかりません。受信バイトループを使用している場合、タイムアウトが発生するか、開始バイトが表示されると、ループから抜け出す必要があります。両方の動作は同じように処理する必要があります。開始シーケンスでフラグを設定する必要があるという事実だけを保存して、それを探す次のコードが邪魔にならないようにします。
スーパーキャット2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.