rl78F14のUART受信の問題点について

こんにちは TTです。

 

現在、下記のような処理を行おうとしています。

A:自分(RL78F14)

B:通信相手(Aからもらったデータ内容に応じて返信してくる)

1. A→Bへデータを送信する

2.  自分(A)は自分で送信したデータを受信してしまうので、送信したデータと受信したデータが同じならデータを破棄する

3. Bからの返信を受信するまで待つ

4. Bからの返信を受信出来たら、データを取り出す。

 

しかし、上記処理中の3でBからのデータを受信することが出来ません。

通信ログを確認したところ、

・A→Bへ正しくデータを送信できている事、B→Aへデータが正しく送信されていることは確認できています。

・BはAからのデータをもらって15ms程度で返信を返してきています。

現在の不具合の仮説としては、「自分の送信データ受信→受信完了の間にBからの返信が来てしまっている?」と考えています。

そこで、EUARTの受信データの受信完了にはどれくらい時間がかかるものなのでしょうか?

また、ほかに考えられる原因等あればご教授ください。

  • > 2. 自分(A)は自分で送信したデータを受信してしまうので、

    なんでですか? 説明に足りない部分があると思います。
  • はじめまして、TTさん。Hosです。

    > 2. 自分(A)は自分で送信したデータを受信してしまうので
    まず、通常はこのような動作にはなりません。
    回路上でループバックしていないか確認するとよいと思います。

    RL78F14は触ったことがありませんが、マニュアルを読む限りではLINセルフテストモードに入れるとループバックするになるようです。
    こちらも確認するとよいと思います。

    > ・A→Bへ正しくデータを送信できている事、B→Aへデータが正しく送信されていることは確認できています。
    この通信ログはAとBどちらで確認したものですか?
    一番良いのは、信号として出力されているかをオシロなりロジアナなりで確認することです。
  • チョコです。
    >そこで、EUARTの受信データの受信完了にはどれくらい時間がかかるものなのでしょうか?
    通常UARTは,STOPビットの中央(サンプリング・タイミング)で受信は完了するはずです。
    そこで,UART受信完了の割り込みが発生するので,後はソフトでの処理になります。
    UARTには受信結果を示すエラーフラグがあります。そこがどうなっているかも参考になるはずです。

    なお,RL78F14には,2種類(SAUのUARTとLIN/UART)のUARTが存在します。
    どちらのUARTかを明確にしてください。また,Hosさんもコメントしているように,ループバックなど
    どのような使い方をしているかを明確にしてください。
  • ご返信ありがとうございます。

    >まず、通常はこのような動作にはなりません。
    通信のICの仕様を確認したところ、送信したデータも含めバス上のデータをすべて受信する様でした。

    >LINセルフテストモードに入れるとループバックするになるようです。
    ありがとうございます。確認します

    >この通信ログはAとBどちらで確認したものですか?
    通信のログはマルチランテスタで確認したものなので間違いはないと思います。
  • 情報不足についてご指摘いただきましたので、追記します.
    ・ループバックはトランシーバICの仕様でした。
    ・使用しているUARTはSAU1のUART1です。

    至らぬところが多々ありますが、引き続きよろしくお願いします
  • 回答ありがとうございます。
    >UARTには受信結果を示すエラーフラグがあります。そこがどうなっているかも参考になるはずです。
    確認してみます.
  • > 現在の不具合の仮説としては、「自分の送信データ受信→受信完了の間にBからの返信が来てしまっている?」と考えています。

    受信割り込み処理の中で他に重いこともされていて受信オーバーランが発生してる辺りが可能性高い気がします。
  • ご返信ありがとうございます。

    ご指摘の通り、受信オーバーランが発生しているようです。
    (CS+自動生成コードにて r_uart1_callback_softwareoverrun(rx_data); が呼ばれる)

    データとデータの間が15ms程度しか空いていないので発生しているのかと思います。
    DMAを使用するなどほかの方法を考えます。

    ありがとうございます。
  • TTさん、こんにちは。NoMaYと申します。

    r_uartXX_callback_softwareoverrun()関数のソースを見ただけなのですが、UARTの普通のオーバーランとは少し違うものだという気がします。例えば、以下のケースで呼び出されるものかと思います。

    ・例えば、通信パケットが、先頭4バイトを読めば、後何バイト来るか分かる、ような構造になっている
    ・なので、まずrecieve関数で4バイト受信して、その受信データをもとにrecieve関数で残りNバイト受信する、ようにした
    ・ところが、4バイト受信のrecieveが完了した後、Nバイト受信のrecieveを起動する前に、もうデータが来てしまった
    ⇒こういうケースでr_uartXX_callback_softwareoverrun()関数がコールバックされる

    ですので、4バイト受信やNバイト受信の部分をDMAなどで行うようにしても、それでは解消されないと思います。

    ちなみに、「3でBからのデータを受信することが出来ません」とのことですが、2は正しく受信出来ているのですよね?思うに、1のデータ数と3のデータ数の合計分を受信するようにrecieve関数を起動させておき、合計分受信完了後に1のデータを比較後に破棄する、などの対策が必要になるのではないかな?という気がします。

    > 1. A→Bへデータを送信する
    > 2. 自分(A)は自分で送信したデータを受信してしまうので、送信したデータと受信したデータが同じならデータを破棄する
    > 3. Bからの返信を受信するまで待つ
    > 4. Bからの返信を受信出来たら、データを取り出す。

    また、r_uartXX_callback_softwareoverrun()関数の動作を逆手にとって、以下のようにしてみるのも手かも知れません。

    ・(上記1のデータ数 - 1)のデータ数を受信するようにrecieve関数を起動する
    ・素朴なrecieve完了コールバックは使わない
    ・r_uartXX_callback_softwareoverrun(rx_data)コールバック(割り込みルーチンから呼ばれている)関数内で、(上記1のデータ数 - 1)分のデータにその後のrx_dataデータを加えたデータを使って上記2を行い、正常であれば、そのコールバック関数内で上記3のrecieve関数を起動する

    すみません、上のは私が何か勘違いしたような気がしますが、素朴にrecieve完了コールバック内で記3のrecieve関数を起動する、ので良いような気がします。

  • > データとデータの間が15ms程度しか空いていないので発生しているのかと思います。
    > DMAを使用するなどほかの方法を考えます。

    データとデータの間が 15ms 程度「も」あって受信オーバーランが発生するというのはそれだけ長い期間割り込みを受け付けない期間があるということでありプログラムの構造の問題でしょう。DMA の使用で解決すべきものでもないと思います。