RXマイコンでのSCI通信について

現在、RXマイコンを使用してSCI通信を行っているのですが、

データの受け取りをバッファ配列のアドレス移動を行い、そこにデータを格納しています。

受信文字列の終端文字を確認するために、コールバック関数内で判定を行っているのですが、受信データの格納位置と条件式で参照しているメモリアドレスが異なり、

条件式が正となりません。

SCI通信時の受信データの格納方法が通常と異なるように思えるのですが、どのようにすればよいでしょうか。

以下に受信データのメモリ参照の画像と、コールバック関数のコードについて添付します。

よろしくお願いします。

  • ryoさん、こんにちは。NoMaYです。

    すみません。文面から何を言わんとしているのか推測出来なかったです。もうちょっと具体的に書いて頂けないでしょうか?

    そして、それはそれとして、文字列に関するデバッグをされるなら、メモリウィンドウの表示モードは、4バイト単位の表示モードでは無く、バイト単位の表示モードを使った方が、分かりやすいと思います。4バイト単位表示モードは、uint32_t型/int32_t型の配列に関するデバッグをする時に便利なように、上位バイト側が左側に表示されるようになっています。

  • あぁっ、コールバック関数内で、以下のような判定をされていますが、カウンタは既に1バイト先に進んでしまってますよ。(画面コピーからソースを起こすのに手抜きをして関数名/変数名は変えました。)

    void callbak_func(void)
    {
        if(data[pos] == 0x0a)
        {
            。。。
            R_SCI_RECV(&data[pos++], 1);
        }
        。。。

     
    [追記]

    最初はpos=0から始まると思われるのですけれども、そうすると、ポストインクリメントでは無く、プレインクリメントかな、と思いました。

  • これはスマートコンフィギュレータのSCIでコールバック機能設定の受信完了を有効化したときの状態ですよね?
    最初の条件判定が一度も真にならないということでしょうか?PC_Receive_Dataにvolatile宣言があるとうまくいくとかあるかもしれません。

    それより気になるのことですが、R_SCI_XXX_ReceiveのAPIを実行して1文字ごとユーザーコールバックr_XXX_callback_receiveendを呼び出してもらって終端判定をするという作りと思いますが、送信データが既知ならPC_Receive_Data配列(大域変数?)が同じ値を受け取っているかが気になります。というのもUART通信データは送り出す側はバッファを使うのでデータとデータの送信間隔は長くてスタートビット長くらいしか間がありませんが、このプログラムの作りですと1バイト受信して完了したら次の1バイト受信の要求をR_SCI_XXX_Receiveを使って要求しています。受信でデータが抜けているのではないかと思いました。というのも生成コードの実際のSCIの受信割込みハンドラはR_SCI_XXX_Receiveで要求されたバッファサイズの受信が完了すると一度REビットをクリアしてからr_XXX_callback_receiveendを呼び出す作りになっているためです。

    受けったと思われるデータ列

    4E 49 49 00 => 'N' 'I' 'I' null

    30 30 31 54 => '0' '0' '1' '6'

    49 0A 0D 30 => 'I' LF  CR '0'

    30 31 54 4E => '0' '1' '6' 'N'

    0A 0D 30 30 => LF CR '0' '0'

    この部分が受信データなら0016NIIというような文字列が来ているように思えますし、二回目と思われる位置のIIが抜けている。データの仕様などを推測で書いているので本当かはわかりませんが。



    あと質問からそれますがmemsetでバッファクリアをしていますね、はっきり申し上げて要らないです。割込み空間で余分な処理は極力避けるべきです。

    もし、送っているデータが既知で抜けが起こっていると思われる状況なら生成コードのr_XXX_receive_interruptでREビットを0にしている部分を一時的にコメントアウトして受信状況がどう変わるか見るのも私なら試します。あとスマートコンフィギュレータの生成コードは多重割込みが許されていない状態のものですのでSCIの他に割込み駆動で高優先度なものがあるとデータ抜けの原因になったりします。私ならDTCなどで別途、塊のデータをハード的に退避する作りにします。

  • Yamamotoさん、NoMaYさん

    回答ありがとうございます。

    レシーブ関数を使用する時にレシーブポジションをインクリメントしてしまっているので、もう一度その部分については確認したいと思います。

    受け取りの文字列はINT10、INT100、INT1000、EXT、STOPの5種類の文字列で各文字列の終端にCRLFが付与されて送信されます。

    メモリブラウザを見る限り、データの受け取りは問題なく出来ているように思います。(始めの部分はコールバック関数内でブレークポイントを入れてしまったので、文字列の読み取りが変になってしまいました。)

    文字列の長さがそれぞれ異なるため、文字数での判定が出来ず、1文字ずつ読取る方法で終端文字の判別を行おうと考えていたのですが、RXマイコンではどのようにデータの読み取りを行うのが最適なのでしょうか。

  • RXマイコンに限った話の正攻法ってのは特にありません。SCIの仕様は他社のUARTとさほど変わりません。受信完了時の割り込みハンドラでUARTの受信バッファを内部変数に退避する仕組みを導入するだけです。

    が!ことスマートコンフィギュレータは・・・私のような低レベルな者では到底理解の及ばない崇高な設計思想のためか?UARTのハンドリングは一筋縄ではいきません。一番やらかすのは多重割り込みが許可されていない点です。特にSCIの生成コードは酷いですね。私の最近の経験で言えばRS485でトランシーバICのDE端子操作をやるのに苦労しました。スマートコンフィギュレータのコードを使うと決めたら腹を据えて取り組むしかないです。

    なお、他の方がどうやってるかわかりませんが、私は多重割り込みを生成コードに直接変更を加えることで解決しています(生成のたびにその変更を適用するわけです)。RS485のDE端子とかの制御についてはDTCでPORT制御のレジスタをプロセッサを通さずに書き換えることで解決したりしました。もし、受信抜けが起きている場合は受信ハンドラを直接編集するなどで簡単にやりたいことが解決したりするかもしれません。


    FPGAと何かやってる関数がありますが、もし、これの処理時間が結構かかるものなら呼び出し順序の工夫も忘れずにしましょう。まずは受信データの仕様をよく確認ですね。

    ・データの最大サイズ
    ・データ終端後、最大送信停止時間と最小送信停止時間の確認(要するに通信サイクル)

    通信サイクルが明確に規定されているなら最大サイズで受信させて、タイマを別に用意して通信タイムアウトを監視させてそこで受信データの確認をさせれば良いように思います。

  • こんにちは。直接の回答ではありませんが。
    RXのSCI受信の攻略法、いろいろあると思いますが、私の場合、一文字だけ受信するようSCIをスタートさせ、
    callback関数内でポインタを戻し、無限に受信するようにしています。
    受信した文字はmain側コードのcallbackルーチンに渡します。添付はRX231のSCI5の場合です。
    かなり姑息な(?)手法ですが、参考になれば幸いです(^^

    // main側のルーチン
    void SCI5_Start(void)
    {
    static uint8_t rb0;
    R_Config_SCI5_Start ();
    R_Config_SCI5_Serial_Receive (&rb0, 1); // 一文字受信開始
    }

    // ジェネレータで作成されたCallbackから更に呼ばれるユーザ定義のCallback関数
    void SCI5_Callback_rx(uint8_t cc)
    {
    push_queue(cc); // 例,FIFOにプッシュする
    }

    // ユーザ定義のCallbackをr_cg_userdefine.hで宣言
    /* Start user code for function. Do not edit comment generated here */
    void SCI5_Callback_rx(uint8_t cc);
    /* End user code. Do not edit comment generated here */


    // Config_SCI5_user.c
    static void r_Config_SCI5_callback_receiveend(void)
    {
    /* Start user code for r_Config_SCI5_callback_receiveend. Do not edit comment generated here */
    // バッファのポインタを戻して1文字受信を繰り返す
    gp_sci5_rx_address--;
    g_sci5_rx_count--;
    SCI5.SCR.BIT.RIE = 1U;
    SCI5.SCR.BIT.RE = 1U;
    SCI5_Callback_rx(*gp_sci5_rx_address); // main側に作成したCallbackを呼ぶ
    /* End user code. Do not edit comment generated here */
    }

  • ryoさん、こんにちは。NoMaYです。

    その後どうでしょうか?なお、RXマイコンの場合、FITと呼ばれるライブラリで既に実装済みであるかどうか、確認するのが良いかと思いました。

    例えば、今回の、行末文字まで受信したい、というような場合、R_SCI_RXモジュールの以下の機能で出来るのではないか、と思うのです。(ごめんなさい、この機能自体は自分では使ったことが無くて、私が勘違いしていたらすみません。)

    RXファミリ SCIモジュール Firmware Integration Technology
    www.renesas.com/jp/ja/document/apn/sci-module-using-firmware-integration-technology

    Page 68

    R_SCI_Control()

    SCI_CMD_COMPARE_RECEIVED_DATA, // Compare received data with comparison data (受信データを比較対象データと比較する


    Page 46

    else if (args->event == SCI_EVT_RX_CHAR_MATCH)
    {
    //from RXI interrupt, received data match comparison data (RXI 割り込みから受信したデータが比較対象データと一致)
    //character placed in queue is in args->byte (キュー内に配置される文字は args->byte の順序)
    nop();
    }