評価ボード(QB-R5F10BMG-TB) CAN0の送信割込を使ってCAN通信

お世話になっております。

/*参考 

*

* CAN/LIN/UART/PORT Checker for RL78/F14

* Target: QB-R5F10PPJ-TB (RL78/F14, 100pin, 256KB ROM, 20KB RAM)

* Author: Yasushi Tanaka

/

移植RL78/F13 評価ボード(QB-R5F10BMG-TB)

開発環境: e2-studio7.4

toolChain: Renesas CC-RL C

デバッグツール: e2-Lite

/* CANの割込(vector.c)の設定 */

#pragma interrupt intcan0err_isr(vect=INTCAN0ERR, bank=RB1)

#pragma interrupt intcan0trm_isr(vect=INTCAN0TRM, bank=RB1)

#pragma interrupt intcangrfr_isr(vect=INTCANGRFR, bank=RB1)

#pragma interrupt intcangerr_isr(vect=INTCANGERR, bank=RB1)

現象は、

送信割り込みを使ってCAN送信しようとしますが、

CAN0のスロットにデータは入っても(確認済)、割込のルーチンintcan0trm_isr()は呼び出されません。

下記のように割り込みが許可されていて問題なさそうに見えますが。

/* CAN0送信割り込みを許可 */

MK2H &= (u1)(~RL78F_MK2H_CAN0TRMMK);

考えてられる原因は何でしょうか、ヒントをいただければ助かります。

よろしくお願いします。

(ちなみに割り込み使わずにCAN APIを使って通信は確認できています)

Parents
  • ikkiさん おはようございます、NAKAといいます。

    送信完了の割込みの設定は

    ①送信バッファの割込み許可
    TMIEC |= 0x0001; //CAN0送信バッファ0の割込み許可 
    ②送信割込みのプライオリティ設定
    CAN0TRMPR0 = 0; //CAN送信割込プライオリティ設定
    CAN0TRMPR1 = 1; //01:レベル2
    ③送信割込みマスクフラグ許可
      CAN0TRMMK = 0; //CAN送信割込マスクフラグ 0:許可

    こんな感じで割込み(vect=INTCAN0TRM)に飛んできますよ!

    P.S.
    勘違いだったかもしれませんが、CANの割込みにレジスタバンク使うとなんか調子悪かった覚えがあります。
    しっかり覚えてませんが、無しも試してください。
  • NAKAさま、
    大変お世話になっております。

    送信時のログを取れました。下記は繰り返されます。初めのポート設定はCAN APIでテスト問題ないです。

    しかし、main()の中のcan_init()が何の原因か繰り返し呼び出される、ということは何かリセットはかかっているでしょうか。

    //-----log
    [0000.000.044]--- CAN init PIOR4 = (05)
    [0000.000.136]--- CAN init P1 = (03)
    [0000.000.224]--- CAN init PM1 = (FE)
    [0000.000.312]--- CAN init TMIEC = (000F)
    [0000.000.404]--- CAN init CAN0TRMPR0 = (00)
    [0000.000.496]--- CAN init CAN0TRMPR1 = (01)
    [0000.000.584]--- CAN init CAN0TRMMK = (01)
    [0000.000.684] (can_start) CAN0TRMMK = (00)
    [0000.000.788]CAN:can_count.tx_max=(00)
    [0000.000.916]CA[0001.000.016]CAN:can_count.tx_max=(01)
    [0001.200.012]CAN:can_count.tx_max=(02)
    [0001.400.020]CAN:can_count.tx_max=(03)
    [0001.600.012]CAN:can_count.tx_max=(04)
    [0001.800.020]CAN:can_count.tx_max=(05)
    [0002.000.008]CAN:can_count.tx_max=(06)
    [0002.200.012]CAN:can_count.tx_max=(07)
    [0002.400.020]CAN:can_count.tx_max=(08)
    [0002.600.012]CAN:can_count.tx_max=(09)
    [0002.800.020]CAN:can_count.tx_max=(0A)
    [0003.000.016]CAN:can_count.tx_max=(0B)
    [0003.200.020]CAN:can_count.tx_max=(0C)
    [0003.400.020]CAN:can_count.tx_max=(0D)
    [0003.600.016]CAN:can_count.tx_max=(0E)
    [0003.800.016]CAN:can_count.tx_max=(0F)
    [0004.000.016]CAN:can_count.tx_max=(10)
    [0004.200.016]CAN:can_count.tx_max=(11)
    [0004.400.012]CAN:can_count.tx_max=(12)
    //-----以上のログが繰り返される

    よろしくお願いします。
  • ikkiさん おはようございますNAKAです。
    漠然としすぎて、なかなか思い当たりませんが思いつくまま適当に確認します。
    関係ありませんが、CANをP10、P11で使うならリダクションの必要がないのでPIOR4を触る必要はないです。
    割込みの設定をするときのモードは正しいでしょうか?ハードマニュアルのフローチャート18.10(図18-16)
    のようにグローバルストップモード⇒グローバルリセッットモードに変遷&確認、チャンネルストップモード⇒チャンネルリセットモードに変遷&確認の後設定されてますか?設定後はグローバル動作モードへの変遷&確認、チャンネル通信モードへの変遷&確認しておきます。GRWCRのRPAGEビットは"1"にしてありますでしょうか?送信時、TMSTS0のTMTRFのクリアを確認してから送信してますでしょうか?C0ERFLLの1bitが"1"は「ADERR、B0ERR、B1ERR、CERR、AERR、FERR、SERRフラグのいずれか1つでも1になると、BEFフラグは1になります。」の何から起因しているのでしょうか?⇒でもまずはあまり関係ない気もします。物理的なところで終端処理はされてるのでしょうか?

  • NAKA様、いつもありがとうございます。

    1)グローバルストップからグローバルリセットへ遷移と確認
    2)チャンネルストップからチャンネルリセットへ遷移と確認
    3)通信ルールの設定とGWCRLのRPAGEビットセット
    4)グローバル動作モードへ遷移と確認
    5)チャンネル通信モードへ遷移と確認
    6)CAN0の送信割り込みを許可(can_start)
    7)送信バッファへ書き込み(can_tx_engue)
    8)slotへデータを準備(can_tx_deque)
    9)slotから送信要求(can_tx_req)
     ここでTMSTSのTMTRFのクリアと確認が必要でしょうか?(質問Q1)
     (元のソースではありませんが、入れても同じ結果でした)
     最後にTMCのTMTRビットをセット

    この時点で「チャンネルエラー割込みが発生!」C0ERFLLL=0x03になってしまいます。また、INTCAN0TRMの割込みにcan_tx_isr()を呼び出されるはずですが、呼び出すことはありませんでした。どうして、送信割込み発生する前にエラー割込みが発生したでしょうか?(質問Q2)

    ちなみに、bankの有無にかかわらず状況は同じです。
    #pragma interrupt intcan0trm_isr(vect=INTCAN0TRM)//, bank=RB1) // can_tx_isr()

    元のソースではcan_tx_isr()割込みルーチンの中にTMSTSのTMTRFビットを落として、can_tx_deque()そしてcan_tx_req()を呼び出して送信要求するはずでした。
     
    そこで、もう一つ質問ですが、送信割込みはTMCのTMTRビットをセットした時点で発生するでしょうか、TMCのTMTRビットをセットした時点ですか?(質問Q3)

    注*)ハードウェア構成は
    [PC]=[e2 Lit]=[RL78/F13+CAN(終端なし)]=[CANモニター(終端あり)]=[CAN-Receiver(終端あり)+RX65N]
    (同じ構成でCANApi割込みなしの通信は確認済みです。500KBPS、UART1でログ取り)

    盛り沢山の質問ですが、よろしくお願いします。

    //--- 下記は分かりやすいようにアレンジして載せておきます
    void main(){
    can_portinit(); // CANポート設定(P10,P11)

    can_init(){
    while (0 != (GSTSL & 0x08)) ; // GRAMINIT(0x08) CANのRAMがクリアされるまで待つ
    GCTRLL &= 0xF8; // &= ~GSLPR(0x04); &= ~GMDC(0x03); グローバル・ストップ・モードから
    GCTRLL |= 0x01; // GRST(0x01)                      グローバル・リセット・モードへ遷移
    while (0 == (GSTSL & 0x01)) ; // GRSTSTS(0x01) グローバル・リセット・モードに遷移するまで待つ

    C0CTRLL &= 0xF8; // &= ~CSLPR(0x04); &= ~CHMDC(0x03); チャネル・ストップ・モードからチャネル・リセット・モードへ遷移
    C0CTRLL |= 0x01; // CRST(0x01)
    while (0 == (C0STSLL & 0x01)) ; // CRSTSTS(0x01) チャネル・リセット・モードに遷移するまで待つ
    //...(他の通信速度設定)

    can_init_rule(){
    GRWCRL = 0x00; // RULE(0x01) CANグローバルRAMをウィンドウ0(ルール)に切り替える
    GAFLIDL0 = 0x0000; // ZERO(0x0000) 比較データを指定
    GAFLIDH0 = 0x0000; // ZERO(0x0000)
    GAFLML0 = 0x0000; // NOCOMP(0x0000) IDビットを比較しない
    GAFLMH0 = 0x0000; // NOCOMP(0x0000)
    GAFLPL0 = 0x0001; // GAFLFDP0(0x0001) 受信FIFO0に格納する
    GAFLPH0 = 0x0000; // GAFLPTR(0x0000) DLCチェックしない、12bitのラベルを付与
    GWCRL = 0x01; // RPAGE(0x01);
    }
    //...(他のバッファ設定)
    GCTRLH = 0x02; // MEIE(0x02) グローバル・エラー割り込みは、FIFOメッセージ・ロストのみ許可
    C0CTRLH = 0xEE; // EWIE(0x02)|EPIE(0x04)|BOEIE(0x08)|BORIE(0x10)|OLIE(0x20)|BEIE(0x40|ALIE(0x80);
    // チャネル・エラー割り込みを、チャネル・バス・エラーを除きすべて許可
    TMIECL = 0x0F; // ENABLE(0x0F) 送信バッファ割り込みを全て許可
    C0CTRHL |= 0x01;// TAIE(0x01) 送信割り込み設定(アボート許可)
    }

    can_start(){
    GCTRLL &= 0xFC; // ~GMDC(0x03) グローバル・リセット・モード or グローバル・テスト・モードからグローバル動作モードへ遷移
    while((GSTS&0x07)!=0) ; // GRSTSTS(0x01)|GHLTSTS(0x02)|GSLPSTS(0x04) グローバル動作モードに遷移するまで待つ
    timer_getinfo(&can_time_start); // ここでタイム・スタンプがスタートするので、タイマの現在時間を記憶する
    C0CTRLL &= 0xFC; // ~CHMDC(0x03) チャネル・リセット・モード or チャネル待機モードからチャネル通信モードへ遷移
    while((C0STSLL&0x07)!=0); // CRSTSTS(0x01)|CHLTSTS(0x02)|CSLPSTS(0x04) チャネル通信モードに遷移するまで待つ
    MK2H &= 0xFE; // ~CAN0TRMMK(0x01) CAN0送信割り込みを許可
    MK2L &= 0xDF; // ~CAN0ERRMK(0x20) CAN0エラー割り込みを許可
    MK2H &= 0xF9; // ~(CANGRFRMK(0x02)|CANGERRMK(0x04)) CANグローバル受信FIFO割り込みとCANグローバル・エラー割り込みを許可
    RFCC0 |= 0x0001; // RFE(0x01) 受信FIFOバッファを有効化する
    }

    can_tx_enque(){
    //... // CAN送信メッセージを用意
    can_tx_deque();
    }

    can_tx_deque(){
    MK2H |= 0x01; // CAN0TRMMK(0x01) CAN0送信割り込みをマスク

    full = 0;
    while ((0 != can_tx_num) && (4 != full)) { // 送信バッファが有効な場合
    full = 0; // fullカウンタを初期化

    for (slot=0; slot < 4; slot++) { // 送信スロットを順番に調べる
    if (NULL == can_tx_ptr[slot]) {// NULLであれば送信スロットが空いている
    can_tx_req(slot); // 送信要求
    can_tx_next(); // 送信バッファを次へ移動
    slot = 4; // このフレームは送信できたので、forループを終了させる
    } else {
    full++; // 使用中なので、fullカウンタをインクリメント
    }
    }
    }
    MK2H &= 0xFE; // ~CAN0TRMMK(0x01) CAN0送信割り込みを許可
    }

    can_tx_req(u1 slot) // 送信バッファから送信要求
    { // ※チャネル送信割り込みマスク状態で呼ばれる
    u1 loop; can_frame *ptr; u1 *dat;
    volatile u2* tmidl; volatile u1* tmdf; volatile u1* tmc;

    // 下記5行は入れても入れなくても動作しない
    volatile u1* tmsts;
    tmsts = &TMSTS0;
    tmsts += slot;
    *tmsts &= 0xF9u; // ~TMTRF 送信結果フラグクリア
    while(((*tmsts)&0x06u)!=0x00){} // TMTRF(0x06) 送信ステータス確認

    ptr = can_tx_buffer[can_tx_readp]; // 送信バッファからフレームデータへのポインタを得る
    can_tx_ptr[slot] = ptr; // 送信スロットのリンク先を設定

    tmidl = &TMIDL0; // TMIDLにポイント
    tmidl += (slot * 8);
    tmidl[0] = ptr->id_l; // IDデータの下位をセット
    tmidl[1] = ptr->id_h; // IDデータの上位をセット
    tmidl[3] = (u2)(ptr->dlc << 12); // DLCをセット(tmidl[3]なので注意)
    tmdf = (volatile u1*)&tmidl[4]; // TMDFにポイント

    dat = &(ptr->buf[0]); // 送信データを設定(DLCによらず、常に8バイト設定する)
    for (loop=0; loop < 8; loop++) { *tmdf++ = *dat++; }

    tmc = &TMC0; // TMCにポイント
    tmc += slot;
    *tmc |= 0x01; // TMTR(0x01)ビットをセット
    }
    }

    // vector.c // bankが使用か否か、どっちもOKみたい
    #pragma interrupt intcan0err_isr(vect=INTCAN0ERR)//, bank=RB1)
    #pragma interrupt intcan0trm_isr(vect=INTCAN0TRM)//, bank=RB1) // can_tx_isr()
    #pragma interrupt intcangrfr_isr(vect=INTCANGRFR)//, bank=RB1)
    #pragma interrupt intcangerr_isr(vect=INTCANGERR)//, bank=RB1)

    void can_tx_isr(){
    u1 slot; u1 tmtrf; volatile u1* tmsts;
    tmsts = &TMSTS0; // TMSTS0レジスタにポイント
    for (slot=0; slot < TX_SLOT_MAX; slot++) { // TX_SLOT_MAX=4; 送信バッファを回る
    tmtrf = (u1)(*tmsts & 0x06); // TMTRF(0x06)ビットを取得(送信中または送信要求なしビット)
    if (0x00 != tmtrf) { // 完了情報があるか
    *tmsts &= (u1)(~TMTRF); // TMTRF(0x06) 完了情報があるので、ビットを落とす
    can_tx_ptr[slot]->sts = (u1)(tmtrf | TMTSTS);
    // TMTSTS(0x01) 送信スロットに結び付けられたポインタのstsをセット
    can_tx_ptr[slot] = NULL; // 送信スロットに結び付けられたポインタを解放する

    if (ABORTED == tmtrf) { // TMSTS_ABORTED(0x02)
    can_count.abt_cnt++; // カウントアップ
    }
    if (SENT == tmtrf) { // TMSTS_SENT(0x04)
    can_count.tx_cnt[0]++; // カウントアップ
    if (0 == can_count.tx_cnt[0]) { can_count.tx_cnt[1]++; }
    }
    if (SENTABORT == tmtrf) { // TMSTS_SENTABORT(0x06)
    can_count.txabt_cnt++; // カウントアップ
    }
    }
    tmsts++; // 次のTMSTSレジスタに進める
    }
    can_tx_deque(); // 送信バッファから次の送信を行う
    }
  • ikkiさん NAKAです。
    色々分からない事が山盛りです。
    >3)通信ルールの設定とGWCRLのRPAGEビットセット
    のGWCRLのRPAGEって何でしょうか?
    一つ前の書き込みで、3)のところで割込みの設定をしたらどうか?との内容ですがグローバル動作モードとチャンネル通信モードにしてから設定しているように見えます。下の部分のことなら......
    >MK2L &= 0xDF; // ~CAN0ERRMK(0x20) CAN0エラー割り込みを許可
    MK2LっていうのはCAN0TRMMKレジスタをどこかで#defineしてるのかな?ちょっと読めません。
    質問Q1⇒TMIDL0にID、TMPTR0にDLC、TMDF***にデータを入れ、TMC0 |= 0x01;で送信要求をすると思いますがその直前で確認したほうがいいのでは?ということです。
    質問Q2⇒その理由を調べてるんですよね?こちらでそのようにならないので何ともです。
    質問Q3⇒TMC0 |= 0x01;で送信要求したあと、バッファの送信が完了したきに発生するので、ビットセットした時ではないと思いますよ。
    どこかのサンプルで難しいかもしれませんが、図18-16の設定手順にあっているかを確認してみてはどうでしょうか?
  • NAKAさま、
    間違いだらけで申し訳ございません。

    (誤)GWCRのRPAGEビットセット
    (正)GRWCRのRPAGEビットを1にセット。

    MK2L(0XFFD4)は割込マスクフラッグレジスタで、CAN0ERRMKは0x20(ビット5)です。

    また、C0ERFLLHを確認したら、値は0x20でした。即ちFERRビットが1で、フォームエラーが検出されたみたいです。

    図18-16のフローチャートをしっかり確認させていただきます。
    引き続きよろしくお願いします。
  • ikkiさん NAKAです。 午前中は出張でした!!

    特別! 出血サービス!

    下のソースをMAIN.cのファイルに張り付けてください。他は一切必要ないです。
    QB-R5F10BMG-TBボードは持ち合わせがないので、北斗電子のF14で作りました。
    なのでポートの設定部分だけをP72,P73からP10,P11にリダクションせずに使ってください。
    送信完了すると割込み関数CAN_TX_INTの中のc_TXがカウントアップしましすし、受信するとc_RXがカウントアップします。

    タイミングもあえてタイマーなど使わずfor文で回してあります。

    もぉ~~ これ以上簡単に出来ない!!!


    /***********************************************************************/
    /* */
    /* FILE :Main.c */
    /* DATE :2019/09/24 */
    /* DESCRIPTION :Main Program */
    /* CPU TYPE :RL78_F14 */
    /* */
    /* NOTE:THIS IS A TYPICAL EXAMPLE. */
    /* */
    /***********************************************************************/
    #include "iodefine.h"

    /************************************************************************/
    /* 割り込みベクタ設定 */
    /************************************************************************/
    void __near CAN_TX_INT(void);
    #pragma interrupt CAN_TX_INT(vect=INTCAN0TRM) //CAN送信割り込み宣言
    void __near CAN_RX_INT(void);
    #pragma interrupt CAN_RX_INT(vect=INTCANGRFR) //CAN受信割り込み宣言

    /************************************************************************/
    /* 関数プロトタイプ宣言 外部関数 */
    /************************************************************************/

    void main(void);

    /************************************************************************/
    /* グローバル変数定義 */
    /************************************************************************/
    unsigned char c_TX;
    unsigned char c_RX;
    unsigned short CAN_SID;
    unsigned short CAN_DLC;
    unsigned char CAN_DATA[8];

    /************************************************************************/
    /************************************************************************/
    /* メインルーチン */
    /************************************************************************/
    /************************************************************************/
    void main(void)
    {
    unsigned long i;

    __DI(); //割り込み 禁止
    //************ オンチップオシレータ32MHzの初期化 **************************/

    CMC = 0x00; //X1発振モード外部クロック入力モードは辞める
    MSTOP = 1; //X1発振回路 停止
    MCM0 = 0; //メインクロックに高速オンチップオシレータを選択
    XTSTOP = 1; //XT1(サブ)発振回路 停止
    SELLOSC = 1; //低速オンチップオシレータ 起動
    CSS = 0; //CPU/周辺をメイン/PLLクロックを選択
    MDIV = 0; //fMP/1=32MHz?
    RTCCL = 0xC2; //RTCのクロック選択 適当?
    TRD_CKSEL = 0; //TRD用クロックの選択 = 32MHz


    /*****************  CANの初期化 **************************/
    //CANポートの設定
    //P72とP73使用時
    PIOR4 = 0x40; //P72.P73をCAN用CTX.CRXに割り当てする 周辺I/Oリダイレクションレジスタ設定 
    P7 |= 0x04; //P72(CTXD)
    PM7 &= 0xFB; //CTXD0(P72pin)を"0":出力に
    PMC7 &= 0xFB; //PMCの設定CAN使用時は"0"
    PM7 |= 0x08; //CRXD0(P73pin)を"1":入力に
    PMC7 &= 0xF7; //PMCの設定CAN使用時は"0"
    //P10とP11使用時
    /*
    P1 |= 0x01; //P10(TXD)34pin
    PM1 &= 0xFE; //CTXD0(P10_34pin)を"0":出力に
    PM1 |= 0x02; //CRXD0(P35pin)を"1":入力に
    */

    //高速オンチップオシレータ32MHz使用
    CAN0EN = 1; //CANモジュールへクロックを供給
    __nop();

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

    GCFGL = 0x0000; //DCS=0:fCAN=fCLK/2=16MHzに設定 DLC配置禁止とは?
    C0CFGH = 0x0049; //SJW=1 TSEG2=5 TSEG1=10 に設定 ボーレートプリスケラ(1)分周無しの場合
    C0CFGL = 0x0001; //C0CFGL+1 = 2で分周(16MHz/2 =8MHz)=ボーレートプリスケラ = fCAN_8Mhz/((0+1)×16Tq)= 500Kbps
    //受信ルール設定
    GAFLCFG = 0x0001; //受信ルール数設定 0:ルール無し? or 1:受信バッファを使用する? 
    GRWCR = 0x0000; //受信ルール変更準備
    GAFLIDL0 = 0x0000; //受信ルール① ID設定  比較しない?
    GAFLIDH0 = 0x0000; //受信ルール② 標準ID・データフレーム
    GAFLML0 = 0x0000; //受信ルール③ 対応IDをマスクしない "0000"なので全bitチェックしないので全て受信する。
    GAFLMH0 = 0xE000; //受信ルール④ 標準IDか?とデータフレームか?他のCANノードが送信? を比較する。
    GAFLPL0 = 0x0001; //受信ルール⑤ 受信FIFOバッファ0(GAFLFDP0)をのみ選択する
    GAFLPH0 = 0x0000; //受信ルール⑥ DLCチェックしない
    GRWCR = 0x0001; //受信ルール変更完了
    //受信バッファ設定
    RFCC0 = 0xF302; //RFIGCV(001:1個でFIFO割込)、RFIM(1:1メッセージ受信毎)、RFDC(16)、RFIE(1:受信FIFO割込許可)、
    //送信バッファ設定
    TMIEC = 0x0001; //CAN0送信バッファ0の割込み許可 バッファ1~3は未使用
    C0CTRL |= 0x0008; //RTBO=1:バスオフ強制復帰させる ?
    //割込設定    割り込み名称:INTCANGRFR(グローバルFIFO受信割込み) INTCAN0TRM(チャンネル送信割込み)
    CANGRFRPR0 = 0; //CAN受信割込プライオリティ設定
    CANGRFRPR1 = 1; //01:レベル2
    CANGRFRMK = 0; //CAN受信割込マスクフラグ 0:許可
    CAN0TRMPR0 = 0; //CAN送信割込プライオリティ設定
    CAN0TRMPR1 = 1; //01:レベル2
    CAN0TRMMK = 0; //CAN送信割込マスクフラグ 0:許可

    GCTRL &= 0xFFFC; //GSLPR=0 グローバルリセットモード⇒グローバル動作モードに変遷 (GMDC=00)
    while((GSTS&0x0001)!=0){} //CANグローバル動作モード変遷を確認
    RFCC0 |= 0x0001; //RFE(1:FIFOバッファ使用許可) 注)グローバル動作モードに変更するp1264
    C0CTRL &= 0xFFFC; //CSLPR=0 チャンネルリセットモード⇒CANチャンネル通信モードに変遷 (CHMDC=00)
    while((C0STSL&0x0001)!=0){} ///CANチャンネル通信モードに変遷を確認

    __nop();

    __EI(); //割り込み 許可


    while (1)
    {

    for(i=0;i<0x01FFFFF;i++)
    {
    __nop();
    }

    //CANの定期送信テスト
    TMSTS0 &= 0xF9; //送信結果フラグクリア
    while((TMSTS0 & 0x06)!=0){} //確認

    TMIDH0 = 0x0000; //標準ID データフレーム 履歴をバッファしない
    TMIDL0 = 0x0123; //送信IDバッファ0にIDをSET!
    TMPTR0 = 0x8000; //送信DLCバッファ0にDLCをSET!
    TMDF00L = 0x01; //送信DATAバッファ0にDATAをSET!
    TMDF00H = 0x02; //送信DATAバッファ0にDATAをSET!
    TMDF10L = 0x03; //送信DATAバッファ0にDATAをSET!
    TMDF10H = 0x04; //送信DATAバッファ0にDATAをSET!
    TMDF20L = 0x05; //送信DATAバッファ0にDATAをSET!
    TMDF20H = 0x06; //送信DATAバッファ0にDATAをSET!
    TMDF30L = 0x07; //送信DATAバッファ0にDATAをSET!
    TMDF30H = c_TX; //送信DATAバッファ0にDATAをSET!
    TMC0 |= 0x01; //送信要求 TMTRを"1"に



    }
    }

    /************************************************************************/
    /* CAN送信完了割り込み関数 */
    /************************************************************************/
    void __near CAN_TX_INT(void)
    {
    c_TX++;
    }
    /************************************************************************/
    /* CAN受信完了割り込み関数 */
    /************************************************************************/
    void __near CAN_RX_INT(void)
    {
    __DI(); //割り込み 禁止
    RFSTS0 &= 0xFFF7; //RFIF受信FIFO割り込み要求クリア
    CAN_SID = RFIDL0; //IDを格納
    CAN_DLC = RFPTR0 >> 12; //DLCを格納
    CAN_DATA[0] = RFDF00L; //Data0を格納
    CAN_DATA[1] = RFDF00H; //Data1を格納
    CAN_DATA[2] = RFDF10L; //Data2を格納
    CAN_DATA[3] = RFDF10H; //Data3を格納
    CAN_DATA[4] = RFDF20L; //Data4を格納
    CAN_DATA[5] = RFDF20H; //Data5を格納
    CAN_DATA[6] = RFDF30L; //Data6を格納
    CAN_DATA[7] = RFDF30H; //Data7を格納
    RFPCTR0 = 0x00FF; //バッファポインターインクリメント
    __EI(); //割り込み 許可
    c_RX++;
    }

  • NAKAさま
    ikkiです、いつもお世話になっております。
    本当に至れり尽くせりですね、感謝!感謝!
    完璧に動いています。

    ところで、CANのフォームエラーは送信するデータに何らかのミスがあるという意味でしょうか?
  • NAKAさま、
    ikkiです、いつもお世話になっております。
    送っていただいたCAN割り込みのサンプルですが、
    他のテストやってから戻って再コンパイルして実行したら、CANモニターにエラーで止まってしまいます。
     そこで、新しいプロジェクトを作り、コード生成から同じサンプルを使うとCANエラー出るが、CAN通信は正常に動きます。

    e2 studio, e2 Liteデバッガー
    1)端子割り当て設定(そのまま)
    2)クロック設定(ほとんど変えず)
    3)オンチップデバッグ設定
    4)WDT使用しない設定
    上記のみ実施。

    コード自動生成はソース以外に何か特別処理をされてるでしょうか。
    毎回コード生成からやらないと行けませんか?

    よろしくお願いします。
  • ikkiさん NAKAです。
    ごめんなさい、見逃してました!!

    チョコ先生からアドバイスがあったので、実践しているのですが、NAKAはコード生成は初期設定を参考に覗くだけで、関数は自分で作るようにしています。新規のプロジェクトを作って、MAINに貼るだけで、CAN通信に必要な設定は全てされているため、他は必要ないはずです。僕の北斗電子のF14ボードで一度たりともCANエラーはでたことがないので、多分大丈夫だと思います。

    他の機能を使う時のクロックの設定が違ってたりしないでしょうか?以前マサさんのコードを参考にされてた時はオンチップオシレータの設定を16MHzのようでしたが、上のサンプルではオンチップオシレータ32MHzですけど良かったでしょうか?

  • NAKAさま、
    ご返事ありがとうございます。

    CANの割り込みプログラムは、CANエラーが沢山出て止まっている、って報告したが、いろいろやってる内に、動いているようです。但し、めっちゃ遅くなっています。CANエラーは出ながらも、通信が確認できました、やはり不安定のようです。

    3つのサンプルを切り替えてテストしていますか、
    (1)CAN-API: 割り込み使わないサンプル
    (2)CAN-Int: 作っていただいた割り込みサンプル
    (3)CAN-Drv: ドライバサンプル、割り込み使用

    そして(1)は安定して確認しました。
    (2)は上記の通りです。

    (3)については、いきなりCANエラー割り込み発生して(C0ERFLL=0x2003、0ビットのEWFエラー)全く通信しません。
    このサンプルは4つの送信スロットを使っています。今は原因を追究しています。

    CANのinternal-loop-backテストモードでは正常のようですが、external-loop-backテストモードとnormal-mode通常モードではEWFエラー割り込みが発生します。

    ちなみにバスに接続しているRX65のCAN送信サンプルは安定して通信を確認できていますので、ネットワークは問題ないと見ています。
    何か設定はおかしいに違いありません。
  • ikkiさん NAKAです。
    RL78/F15(CANが2ch)を使って、MAINバスをCAN0chで受信して、そのまま即座に全部ローカルバスへCAN1chから送信する。みたいなことをやってますが、全然遅くないですよ。上記の割込みの設定のままです。ikkiさんのMAINバスの占有率がどれだけギリギリかわかりませんが、車両のCAN程度なら全然大丈夫です。
Reply
  • ikkiさん NAKAです。
    RL78/F15(CANが2ch)を使って、MAINバスをCAN0chで受信して、そのまま即座に全部ローカルバスへCAN1chから送信する。みたいなことをやってますが、全然遅くないですよ。上記の割込みの設定のままです。ikkiさんのMAINバスの占有率がどれだけギリギリかわかりませんが、車両のCAN程度なら全然大丈夫です。
Children
  • NAKAさま、ありがとうございます。
    改めてテストさせていただきました。

    CAN送信した後に、待ちループを頭から移しまして。
    概ね通信を確認できましたが、
    しかし、CANモニターにエラーがいつも点灯します。
    リトライがしているような感じ、実際の送信は約数百msecから1秒ぐらいの間隔です(CANモニター)。

    試しにC0ERFLLをログに取ってみましたが、0x201Fになっていて、意味が分かりません。
    このレジスタから何のエラーか分かりますか?

    よろしくお願いします。
  • ikkiさん NAKAです。

    確認ですが新規のプロジェクトを作って、以前紹介したサンプルをMAINに張り付けただけの状態(それ以外何もしない)でエラーが起きるのでしょうか?であればハードの可能性もあります。電源が不安定とか、ノイズとか。


    >試しにC0ERFLLをログに取ってみましたが、0x201Fになっていて、意味が分かりません。
    >このレジスタから何のエラーか分かりますか?
    ⇒データシートに記載がありますよ!マイコン(CAN機能)から”H"を送信したのにCANバスでは”L”を検出しちゃったためB1ERRが立って、その状態が続いたのでバスオフになっちゃったって感じでしょうか?

    エラーの原因までは、そのステータスだけでははわかりませんけど(^^)/

    ファイト!
  • NAKAさま、ありがとうございます。

    新しいプロジェクトを作って改めてテストさせていただきました。

    結果は同じです。相変わらずCANエラーが発生しますが、通信もしています。

    カウンターを作ってCANメッセージに入れて確認したら、エラーのせいかカウンターが飛ばされたり、また連続短時間に同じ値のメッセージが表示されたりします。
    ハードウェア的にリトライがかかったりしているようです。

    配線を見直したり、電源を強化したりしましたが、やはり不安定のようなので、ノイズのせいでしょうか?
  • ikkiさん NAKAです。

    CANでトラブった経験がそんなに無いので、アドバイスが難しいかも?ですが終端処理とかしっかりしてますか?

    一応、朝から北斗電子のF14ボード引っ張り出し、プロジェクトにぺたんと貼って動かしてみましたが、やはりエラーは出ませんし、

    データに 「TMDF30H = c_TX;       //送信DATAバッファ0にDATAをSET!」とかしてモニタしても当然、カウンタ値は抜けませんし......

    ハードなのかなぁ~???

    唯一

    極まれにエラーフレームが発生する!という事例で調査したことがあって

    原因と思われるのが、

    基板実装屋さんが電源のコンデンサを指示したものと間違えてESRの高いものが実装されてたことがありました。

    電源ICのカタログでは

    のようにESR3Ω以上だと安定領域から外れる恐れがあり、ついていたアルミ電解は

    のようでさらに温度特性で低温になるとさらに悪化するらしいです。

     

    実際の波形が

    このように負荷電流の変化がトランジェント応答に現れちゃってる感じになったことがあります。

    これでも、CANの規格は十分に満足しており、実機での評価中は2日間一度もエラーフレームは発生しませんでした。

    極低温の環境だと可能性があるのかもしれません。

     

    そして、当初に設計したコンデンサを実装したところ

    このように電源も波形も安定して、その後そういった報告は無いと聞いております。

     

    もう一度確認ですが、先のサンプルに一切手を加えない状態でエラーがあるのでしょうか?

    だとやっぱり、ハード?

  • NAKAさま、
    本当にありがとうございます。

    何度も送っていただいたサンプルでトライしてみたが、エラーが必ず出ます。
    しかし、昨日は割と調子が良かったですが、
    今改めて新規のプロジェクトを作ってテストしてみますと、エラーとなって全く通信しません。

    昨日は9割以上通信できていました。
    エラーでパケットが抜けたり、ハードウェア的にリトライしたりしても。

    やはりハードウェア的な問題でしょうか、とにかく不安定です。

    手元に北斗電子の64ピンのRL78/F13ボードがあってまだ動かせていないですが、それでも確かめたいです。

    しっかりターミナルをつけるために、両端にRX65のボード(ターミナル付)を置いています。
    RX65のCANは割り込みを使わないですが、常に安定しています。

    ターゲットボードに付いてるトラシーバーを使わずに他のトラシーバーを使っても、100%通信できているとはできませんでした。
  • NAKAです。

    多分関係ないし、
    解放で大丈夫だと思いますが、TJA1050が実装されているならSpinをGNDに落としておきますか?

    一応
    Control pin S allows two operating modes to be selected:
    high-speed mode or silent mode.
    The high-speed mode is the normal operating mode and is
    selected by connecting pin S to ground. It is the default
    mode if pin S is not connected. However, to ensure EMI
    performance in applications using only the high-speed
    mode, it is recommended that pin S is connected to
    ground.
    と書いてあるので
  • NAKAさま、
    本当にありがとうございます。

    改めてターゲットボードからCTXD0(P10)とCRXD0(P11)を取り、別のトランシーバーにあげたら、送っていただいたサンプルは完璧に動き出しました\(^o^)/
    やはりハードウェアの問題でした。

    感謝感謝!
  • NAKAです。

    >サンプルは完璧に動き出しました\(^o^)/
    ⇒でしょ (^_-)-☆
  • NAKAさま、
    いつもお世話になっております、ikkiです。

    トランシーバーを交換したら、
    同じ現象でしたので、考え変えたら
    原因は電圧が足らなかったことをわかりました!
    3.3Vはトランシーバーを駆動できないみたいです。
    (エミュレータ電源供給は3.3V)5V外部から供給したらパッチリ、サクサク動き出しました。
    これで一安心眠れそうです。
    いろいろありがとうございました。