AVR UART同期問題

私は組み込みプログラミングを学んでいます(私は電気技師ではありません)。 これが適切な場所ではない場合、またはこの質問を誤っている場合は、申し訳ありませんが、解決策を見つけようとするのは非常に困難でした。 私はGPSモジュールと16x2のLCDを搭載したATMega32を使用しています。 UARTでNMEAセンテンスを読み、解析したデータをLCDに送信したいだけです。バッファ内の文を読み、それをディスプレイに吐き出します。ただし、データに矛盾が生じることがあります。 GPSは常にオンになっており、AVRは途中で起動し、文の開始を待ってから受信を続けます。

私の質問は、1つが常に送信している場合(GPSは1 Hzのレートでデータを送信する)、もう1つはランダムな時間に受信する場合、2つのデバイスはどのように同期できるかです。 UARTの同期はどのように達成されますか?スタートビットとストップビットについては知っていますが、UARTが不良パケットを受け取った場合(たとえばフレーミングエラーが発生した場合)、UARTはどのように回復し同期することができますか?

ハードウェアレベルでも何が起こるのか説明してください。できれば、オンラインリソースを参照してください。探しているものが見つかりません。

本当にありがとう!

ルカ

0
nl ru de

4 答え

あなたの直感は正しいです - UARTハードウェアはバイトレベルを超えていかなる同期も持っていません。 (ここ

1バイトよりも長い「パケット」を同期させるために、ほとんどの高レベルシリアル通信プロトコルはメッセージに現れないことが保証されているバイトの特別な「プリアンブル」を持っています。それから、パケットの終わりを知らせるためのさまざまな方法があります:いくつかのプロトコルはメッセージの中に現れることが許されないバイトの特別な "停止"シーケンスでメッセージの終わりを示します。他の人は、メッセージの正確な長さを示す固定長メッセージヘッダを使用します。

私は個人的にNMEAプロトコルを使ったことはありませんが、このガイドに基づいていますパケットの開始を知らせる特殊文字として '$'を使っているようです。パケット内に出現することは許可されていません。

それで、あなたのプログラムでこのデータを受け取るために、私はあなたがこのような何かをする必要があると思います:

  1. 「$」が表示されるまですべてのバイトを無視します。
  2. 次に、各バイトを0から始まる配列に記録します(配列が、有効な最長メッセージを保持するのに十分な長さであることを確認してください。 >
  3. 「CR」に続けて「LF」が表示されたら停止します(これはNMEAパケットの終わりを知らせるようです)
  4. チェックサムを計算し、それが送信されたチェックサムと一致することを確認します。そうでない場合は、手順1に戻ります。
  5. あなたの配列のデータを使う
  6. 手順1に戻ります。

This discussion has a lot of good links: https://stackoverflow.com/questions/1445387/how-do-you-design-a-serial-command-protocol-for-an-embedded-system

6
追加された
nmeaデータはさまざまでバースト間にギャップがあるため、ハードウェアは同期します。大丈夫な数文字、数十文字、または100文字を見逃した場合は、上記のステートマシンに従い、パケットの開始($)を待って収集パケットの終わり(CR、LF)が見つかるまでデータをチェックしてからパケットをチェックサムし、一致しない場合は破棄します。1秒以内に別のパケットを受け取るので気にしないでください。
追加された 著者 Bartosz Radaczyński,
私は昔の仕事でカスタムフォーマットのシリアルデータにインターフェースする必要がありました。エラー(フレーミングを含むすべてのエラー)に対して行ったことは、エラーフラグを毎回クリアしてからステップ1に戻る必要があります。使用したマイクロには、UARTを制御するための複数のフラグを持つ複数のレジスタがあります。すべてのアクションがフラグ(特にエラーフラグ)をクリアするわけではありません。それはドキュメンテーションの中にあります。
追加された 著者 RhysC,
RS-232プロトコルの@Lucaは、ハードウェアレベルでバイトフレーミングを処理します。あなたのAVRのUARTはあなたに送信されたバイトの中央で始まるデータを決して与えません。それを私の説明に加えます。 (マイクロコントローラのUARTがバイトの途中でオンになると、通常受信したビットを破棄し、Spoonが言ったようにエラーフラグを立てます)
追加された 著者 js92,
しかし、文の途中とバイトの途中に入った場合はどうなりますか?それは間違ったビットをサンプリングし始め、フレーミングエラーを取得しますがゴミデータを提示しますか?それはどのように再同期するのでしょうか?
追加された 著者 loislo,

NMEAメッセージの形式を見ると、開始文字($)と終了文字(CR + LF)が定義されています。ウィキペディアからこのように:

$ GPAAM、A、A、0.10、N、WPTNME * 32

あなたのソフトウェアは$文字を探し、それがCR + LFを受け取るまでバッファに以下のすべての文字を保存する必要があります。その後、チェックサムを計算し、それをメッセージ内のチェックサムと比較することによって、メッセージが有効かどうかを確認できます(例では* 32がチェックサムです)。チェックサムが一致した場合にのみ、メッセージがLCDに送信されます。

1
追加された
$の後の文字列がゴミである場合は、単に文字列全体を破棄して別の文字列を待つ。
追加された 著者 Bartosz Radaczyński,
これが起動時にのみ期待されている場合(最初の$自体はおそらくゴミ)、これは起動後に定期的に発生しますが、通常は実行中に除数が正しく設定されていません。
追加された 著者 Bartosz Radaczyński,
そのおならのTX側にダム端末を置いてください。チェックサムを計算するだけのコードを作成し、見つかったすべての文字列に対してそれを実行します。 0を出力すると失敗したパケット、1を出力すると成功します。起動して同期した後で失敗することはないでしょう、あなたが永遠に失敗のパーセンテージを再び見ているなら、おそらくあなたの時計の正確さまたはuartのための約数
追加された 著者 Bartosz Radaczyński,
私のソフトウェアでは、ドル記号を待って、(便利なサイズの)バッファのように振る舞う配列の中に($を含む)文字を格納し始めました。しかし、時には$に続いてゴミが出ることもありますが(通信の開始時にランダムに2、3回だけ)、PCにシリアルリンクを接続しても(RealTerm)、表示されません
追加された 著者 loislo,

あなたの投稿には、実際には2つの質問があります。

1)同期はどのように達成されますか?そうではない。 2つのデバイスに共通する唯一の共通要素は時間です。これはボーレートによって指定されているものです。 2つのデバイスに異なるボーレートを指定すると、ゴミが出ます。ほとんどのハードウェアUART(そしてあなたがあなたのコントローラに専用のハードウェアを使っていることを望む)はスタート/ストップビットと実際のデータのデコードを提供します。そのため、ここでは1バイト(この場合は1文字のASCII文字)について話しています。 GPSはスタートビット、データ、ストップビットを送信します。これは非常に単純で信頼性の低いデータチェックですが、UART送信で実際に使用できるのはこれだけです。正直に言うと、あなたがあなたの設定を正しくしたならば、これは通常ずっとうまくいくでしょう。私は115200でシングルビットエラーもなくテスト用にメガバイトを転送しました。

2)あなたはゴミを受け取ることがあると言います。私にはこれには2つの理由があります:あなたが既に破損したバイトを受け取る(あなたはその場合マイクロコントローラのUARTエラーレジスタにいくつかのエラーがあるはずです)。私たちはあなたが実際に何を得るのかについてのより詳細な説明を必要とするでしょう。通常これらのGPSモジュールはかなりよくテストされて来ますので、私は問題があなたの側にあると思います。各文字を受け取った後は、コントローラのエラーレジスタをチェックして問題を検出してください。ボーレートを確認するもう1つの方法は、スコープをTX回線に接続し、ビットタイムが設定したものと一致するかどうかを確認することです。あなたのシナリオをもう少し詳しく説明できますか。どのコントローラを使用していますか、外部水晶を使用していますか。コントローラをどのくらいの速度で実行していますか。UARTレジスタの設定は何ですか?転送中にエラーが発生しましたか?

0
追加された

UARTの同期はどのように行われますか?スタートビットとストップビットについては知っていますが、UARTが不正なパケットを受け取った場合(たとえばフレーミングエラーが発生した場合)、どのようにして回復および同期を行えますか。

信頼性のある同期は、送信間に少なくとも1文字期間の「デッドタイム」を残すことによって達成することができる。受信側のUARTがトランスミッタから同期解除された(または非同期になった)場合、送信が停止して再開したときに再同期します。

(NMEAの文脈では、シリアル回線速度はシリアルリンクが常にアクティブであるというわけではないほど十分に高くなければならないので、これは自然に起こるべきです。 )

信頼性の低い同期を得るための、信頼性は低いがそれでも効果的な方法は、シリアルリンクに1.5または2ストップビットを使用することです。非同期になった受信UARTは、送信内のスペースを単一のストップビットとして読み始める可能性があり、最終的には拡張されたストップビットとの正しい同期に「ドリフト」するはずです。

0
追加された