CAN通信について

RL78 F13/F14を使用しています。初心者です。

CAN通信のところで躓いています。

元々受信バッファ、送信バッファを使用してCAN通信を行っていたのですが、

受信できるIDを増やすために受信FIFOを実装しました。

割り込み設定、データの取り込みまではうまくいったのですが、

受信FIFOを使用してCAN信号を取り込むと

受信したID(RFIDL/RFIDH)、データ情報(RFDF00~RFDF33)がいつの間にか

送信バッファ(TMIDH/TMIDL)、送信データ(TMDF00~TMDF33)に上書きされています。

レジスタの設定を一つ一つ見直していますが、おかしいところが見当たりません。

当然、送信バッファに受信FIFOのデータを代入する処理も行っておりません。

どのような原因が考えられるでしょうか?

今は送信の処理をコメントアウトしていますが、送信の処理を入れると

いつの間にか上書きされているため、想定外のIDとデータを稀に送信してしまいます。

以下、ソースコードです。

=============================================

#pragma interrupt INTCANGRFR CanFIFORcvInterrupt

void caninit(void) //CAN通信初期設定
{
DI(); //割り込み禁止
PM1.0 = 0;
P1.0 = 1;
PM1.1 = 1;
CAN0EN = 1; //CANモジュールイネーブル(fclk)

while((GSTS&0x0008)!=0){} //CAN用RAMクリアを待つ GRAMINITフラグが"0":RAMクリアになったか?
GCTRL = 0x0001; //GSLPR=0 グローバルリセットモードに変遷 (GMDC=01)
while((GSTS&0x0001)==0){} //CANグローバルリセットモード変遷を確認
C0CTRL &= 0x0001; //CSLPR=0 チャンネルストップモード⇒チャンネルリセットモードに変遷
while((C0STSL&0x0001)==0){} //CANチャンネルリセットモードに変遷を確認

GRWCR = 0x0001; //RPAGE=1
GCFGH = 0x0000; //タイムスタンプ/ミラー機能/DLCフィルタ/送信優先順位
GCFGL = 0x0000; //インターバルタイマプリスケーラー(FIFO時のみ)
C0CFGH = 0x012F; //SJW:2Tq/TSEG2:3Tq/TSEG1:16Tq
C0CFGL = 0x0001; //fCAN / ((BPR + 1) * 1ビットタイムのTq数)
//250Kbps=10000KHz/((BRP+1)*20Tq)
/************************************/
/*   CAN受信ルール設定 */
/************************************/
GAFLCFG = 1; /*チャネル0受信ルール数設定(r_cg_userdefine.h)*/
GRWCR = 0; /*受信ルール・アクセス用にウインドウ0に切り替え*/
/*受信ルール1*/
GAFLIDL0 = 0x0000; /*受信ルールのID設定(下位バイト)*/
GAFLIDH0 = 0x8000; /*IDE=拡張ID RTR=データ・フレーム 受信ルール対象メッセージ=他ノードからの受信時 受信ルールID設定(上位バイト)*/
GAFLML0 = 0x0000; /*IDビット(下位バイト)を比較する*/
GAFLMH0 = 0x0000; /*IDEビットを比較する RTRビットを比較する IDビット(上位バイト)を比較する*/
GAFLPL0 = 0x0001; /*受信バッファを使用しない 受信バッファ番号=0 CAN0送受信FIFOバッファを選択する 受信FIFOバッファ0を使用しない*/
GAFLPH0 = 0; /*DLCチェックしない 受信ルール・ラベル情報なし*/
GRWCR = 1; /*受信ルール・アクセス用にウインドウ1に切り替え*/

/***************************************/
/* 受信FIFOバッファの設定 */
/***************************************/
RFCCL0 = 0x1102; /*1メッセージ受信完了毎に受信FIFO割り込みを発生する。*/
CANGRFRPR0 = 1; //CAN受信割込プライオリティ設定
CANGRFRPR1 = 0; //01:レベル2
CANGFRMK = 0; //送受信FIFO受信割込マスクフラグ
/***************************************/
/* 送信バッファの設定 */
/***************************************/

※送信バッファの設定をしなくてもTMIDH/Lに値が書き込まれている確認するためにコメントアウト中

//送信バッファ設定
/* TMIEC = 0x000F; //CAN0送信バッファ0~3の割込み許可
C0CTRH |= 0x0080; //ERRD=1:エラー全表示
CAN0TRMMK = 0; //CAN送信割込マスクフラグ 0:許可
CAN0TRMPR0 = 0; //CAN送信割込プライオリティ設定
CAN0TRMPR1 = 1; //01:レベル2
*/
GCTRL &= 0xFFFC; //グローバル動作モードへ
wait();
while (GSTS & (1<<0)) //遷移待ち(GRSTSTS==0)
{;}
RFCCL0 |= 0x0001; /*受信FIFOバッファの許可*/
C0CTRL &= 0xFFFC; //チャネル通信モードへ(CSLPR=0)
//wait();
while (C0STSL & (1<<0)) //遷移待ち(CRSTSTS==0)
{;}
EI(); //割り込み許可
}

__interrupt void CanFIFORcvInterrupt(void) //受信完了割り込み
{
DI(); //割り込み 禁止
RFSTS0 &= 0xFFF7; //CFIF受信FIFO割り込み要求クリア
CAN_SID2 = RFIDL0; //IDを格納
CAN_DATA2[0] = RFDF00L; //Data0を格納
CAN_DATA2[1] = RFDF00L; //Data1を格納
CAN_DATA2[2] = RFDF10L; //Data2を格納
CAN_DATA2[3] = RFDF10H; //Data3を格納
CAN_DATA2[4] = RFDF20L; //Data4を格納
CAN_DATA2[5] = RFDF20H; //Data5を格納
CAN_DATA2[6] = RFDF30L; //Data6を格納
CAN_DATA2[7] = RFDF30H; //Data7を格納
RFPCTR0 = 0x00FF; //バッファポインターインクリメント
EI(); //割り込み 許可

}

  • 以前は受信バッファを使っていて、受信FIFOを使う様に変更したとのことですが、以前の受信バッファ数の設定

    RMNB=16;

    の設定が(上記には無いですが)残っていたりしないでしょうか。

    RL78/F13,F14は、受信バッファ、受信FIFO、送受信FIFOの3者のバッファ数の合計が16までとなっていたかと思います。上記ソース内では受信FIFOを4段に設定していると思いますが、受信FIFO(4)+受信バッファ(16)の場合は合計で16を超えるので、受信時にオーバフローして他の領域(どこを破壊するかは判りませんが、送信バッファかも)を破壊するでしょう。(RS-CAN系は、バッファの数に注意しないと、変な領域が壊れて、変な動作に悩まされる事があります。)

    なお、送信バッファが壊れる現象とは関係ありませんが、受信割り込みの処理で、2つ(以上)のメッセージがFIFOに溜まってから割り込みが入った場合、2つ目以降のデータがFIFOに残る事となりそうな気がします。(FIFOにメッセージが残っている状態で、割り込みを抜けた場合、直ぐに次の割り込みが入ってきてくれれば良いのですが、そうはならなかったと思います。その場合、次のメッセージを受信したタイミングで割り込みが入ってきて、割り込みが入ってきたけど、古いデータ受信したんですけど?という様な事になるかと思います。)

  • ご連絡ありがとうございます。

    確認してみましたが、その設定は残っていませんでした。

    現象的には領域を破壊しているような感じですよね。。。

    受信割り込みの処理については、1つのメッセージを受信するたびに割り込みに入れるような設定にしているため、

    このプログラムでは大丈夫な気がしますが、その設定をしていないとそうなりそうですね。

    メッセージがたまってから読み出す処理はまだ難しそうなのでやっていませんが、将来的には割り込み回数を減らしたいので実装したいと思っています。

  • 投稿されているコードをコピペして実行してみました。(クロックの設定等は一部変更。手元の環境がCC-RLでしたので、CC-RL向けに割り込み関数の記載方法は変更。)

    ・送信レジスタにテストデータを設定(*)

    ・無限ループ

    {

     ウェイト(1秒程度)

     データ送信(*で設定したデータが送信される事が期待値)

    }

    ・適当に外部からデータを送信して受信割り込みを生じさせる

    (送信割り込みの設定があったので、送信割り込み関数は適当に追加しました)

    上記の様なテストを実行してみましたが、送信データが受信データで上書きされる現象は再現しませんでした。受信データで送信デーが上書きされるというのは、結構レアなケースでしょうか。それとも、受信割り込みが何回か入ると大体再現する様な状態でしたでしょうか?

    やってみて気付いた事を参考まで。

    >GAFLML0 = 0x0000; /*IDビット(下位バイト)を比較する*/

    コメントでは、上記となっていますが、0の場合は「比較しない」でしょうか。

    >CAN_DATA2[1] = RFDF00L; //Data1を格納

    RFDF00Hの誤記ですね、大した話ではないですが。

    なお、受信割り込みに関しては、割り込み禁止中や、優先度の高い割り込み実行中に、立て続けに2つ以上のメッセージを受信した際に問題が起こるかと思いました。CANデータを送信する人が1人のみで、データの送信間隔がまばらである事が保証されていれば問題は起こらないと思います。(データ受信から受信割り込みフラグクリアまでに掛かる時間の最大値<データ送信間隔、であれば問題は無いかと思います。)

  • ご連絡遅くなってしまい、大変申し訳ございません。

    解決いたしました。

    最初にご指摘受けていたようにRMNB=16;の設定が残ってしまっていました。

    RMNBで検索をかけた時にヒットしなかったので、見受けられなかったと回答したのですが、

    CANリプロできる既成品のプログラムを盛り込んでおり、そのソース内でレジスタに直接値を書き込む処理を行っていたようです。

    #define CAN_RNB *(volatile WORD*)(CAN0BASE+0x0032)

    のような書き方をされていました。

    ろくに確認もせず申し訳ございませんでした。

  • 解決された様で良かったです。

    (バッファがあふれたことが判るステータスレジスタとかあれば良いのですが、そんな訳にもいかないのでしょうかね?)