評価ボード(QB-R5F10BMG-TB)を使用したCAN通信について

いつもお世話になっております。

「マサ」と申します。

現在,QB-R5F10BMG-TB(以下、評価ボード)を用いて、CAN通信をさせようとしております。

NAKAさんが以前に作成されたサンプルをベースにコーディングして、デバッグしているのですが、

どうにもうまくいきません。

症状としては以下のようになります。

①CANモジュール設定完了時(グローバル通信、チャンネル通信モードの切り替え完了)

・C0ERFLLが0x0000から0x20DF

・C0STSHが0x0000から0x0081になる。

 

②送信時

②-1送信要求時:

・一度送信要求を行うと、アボートするまでひたすら送信を繰り返す。

・繰り返し送信をしている最中に任意のデータが送られたり、SOFらしきものだけが送られる。

②-2ワンショット送信要求時:

・送信要求を行っていないにも関わらず、SOFらしきものがたびたび送信される。

・送信要求を行ってもバッファに入れた任意のデータが送信されない。代わりにSOFらしきものが送信される。

 

当方、CAN通信は初めてで、データシート等見比べていろいろ試したのですが、状況が変わらず苦戦しております。

何かアドバイスをいただけないでしょうか?

 

※評価ボードのP1.0,P1.1とトランシーバーICと接続しているパターンをカットして、入力ポートとしてします。

代わりにリダイレクション機能を使用してP7.3、P7,2をCANのCTXDとCRXDとして使用しており、それぞれをトランシーバICのTXDとRXDに接続しています。

P1.2は出力のLoとしております。

クロックはオンチップオシレータを使用、オプションバイトで16MHzを指定しています。

またデバッグしている環境ですが、

CS+ V4.00(CA78K0R 1.72)

E1使用 (評価ボードに5V供給しています)

 

以下、ソースになります。

//CANの設定

void CAN_Init( void )
{

PM1 = 0xFBu; /* P1.2 出力*/
P1 |= 0x00; /* P1.2 Lo*/
PIOR4 = bin8(0,1,0,0,0,0,0,0); /* リダイレクションを有効 P72,P73にCANTX,CANRX */
P7 &= 0xF7u; /* P72(CTXD0)="1", P73(CRXD0)="0" */
P7 |= 0x04u; /* P72(CTXD0)="1", P73(CRXD0)="0" */
PM7 &= 0xFBu; /* CTXD0(P72pin)を"0":出力に */
PM7 |= 0x08u; /* CRXD0(P73pin)を"1":入力に */
PIM7 &= 0xF3u; /* 通常入力モード選択 */
POM7 &= 0xF3u; /* 通常出力モード選択 */


/* 高速オンチップ・オシレータ 使用時---------- */
CAN0EN = 1u; /* CANモジュールへクロックを供給 */
//CAN0MCKE = 1u; /* CANモジュールへX1クロックを供給(X1クロックを供給する場合のみ有効) */
NOP();
while((GSTS&0x0008u)!=0u){} /* CAN用RAMクリアを待つ GRAMINITフラグが"0"になればRAMクリア */

while((GSTS&0x0004u)==0u){} /* グローバルストップモードであるかを確認 GSLPSTSフラグが"1"であればグローバルストップモード */

GCTRL &= 0xFFFDu; /* GSLPR=0 グローバルストップモード⇒グローバルリセットモードに変遷 (GMDC=01) */
GCTRL |= 0x0001u;
GCTRL &= 0xFFFBu;
while(((GSTS&0x0004u)==1u) && ((GSTS&0x0001u)==0u)){} /* CANグローバルリセットモード変遷を確認 GSRSTSTが1ならグローバルリセットモード*/

while((C0STSL&0x0004u)==0u){} /* CANチャンネルストップモードかを確認 */

C0CTRL &= 0xFFFDu; /* CSLPR=0 チャンネルストップモード⇒チャンネルリセットモードに変遷 (CHMDC=01) */
C0CTRL |= 0x0001u;
C0CTRL &= 0xFFFBu;
while(((C0STSL&0x0004u)==1u) && ((C0STSL&0x0001u)==0u)){} /* CANチャンネルリセットモードに変遷を確認 */

/* クロック, ビットタイミング, 通信速度等の設定 */
GCFGL = 0x0000u; /* DCS=0:fCAN=(fCLK/2)/TSP=8MHzに設定 */

GCFGH = 0x0000u; /* 15-0bit ITRCP インターバル・タイマ・プリスケーラ設定 */

C0CFGL = 0x0000u; /* (BRP+1)で分周=プリスケーラ分周比設定ビット */
/* = fcan_8MHz/((0+1)×16Tq)=500Kbps */
C0CFGH = 0x0049u; /* SJW=1,TSEG2=5,TSEG1=10 に設定 */

/* 受信ルール設定 */
GAFLCFG = 0x0006u; /* 受信ルール数設定 */
GRWCR = 0x0000u; /* 受信ルール変更準備 */
GAFLIDL0 = 0x0000u; /* 受信ルールID設定  比較しない */
GAFLIDH0 = 0x0000u; /* 受信ルール */
GAFLML0 = 0x0000u; /* 受信ルール 対応IDをマスクしない "0000"=全bitチェックしない=全て受信 */
GAFLMH0 = 0xE000u; /* 受信ルール 標準IDか?とデータフレームか?を比較する。 */
GAFLPL0 = 0x0001u; /* 受信ルール 受信FIFOバッファ0(GAFLFDP0)をのみ選択する */
GAFLPH0 = 0x0000u; /* 受信ルール DLCチェックしない */
GRWCR = 0x0001u; /* 受信ルール変更完了 */

RMNB = 0x0010u; /* 受信バッファ数設定 = 16(仮) */
RFCC0 = 0x1300u; /* 受信FIFOバッファ利用 1メッセージ受信完了ごとに割り込み発生 */

CFCCL0 = 0x0000u; /* 送受信FIFOバッファ未使用 */
CFCCH0 = 0x0000u; /* 送受信FIFOバッファ未使用 */


/* 送信バッファ */
TMC0 = 0x00u; /* 送信禁止 */
TMC1 = 0x00u;
TMC2 = 0x00u;
TMC3 = 0x00u;

/* グローバルエラー割り込み */
GCTRL &= 0xF8FFu; /* エラー割り込み関連無効(仮) */


/* チャンネル割り込み,バスオフ,エラー表 */
C0CTRL &= 0x00FFu; /* RTBO=1:バスオフ強制復帰させる(保険) */
C0CTRL |= 0x0008u; /* エラー割り込み関連無効(仮) */
C0CTRH = 0x0000u; /* 送信アボート割り込み禁止、バスオフ復帰(ISO11898-1仕様)、通信テスト禁止 */

/* 割り込みコントローラ部の割り込み制御レジスタ */
GCTRL &= 0xFFFCu; /* GSLPR=0 グローバルリセットモード⇒グローバル動作モードに変遷 (GMDC=00) */
while((GSTS&0x0001u)!=0u){} /* CANグローバル動作モード変遷を確認 */
RFCC0 |= 0x0001u; /* RFE(1:受信FIFOバッファ使用許可) */

NOP();
C0CTRL &= 0xFFFCu; /* CSLPR=0 チャンネルリセットモード⇒CANチャンネル通信モードに変遷 (CHMDC=00) */
while((C0STSL&0x0001u)!=0u){} /* CANチャンネル通信モードに変遷を確認 */
NOP();

}

 


uchar CAN_Sendstatus( void )
{
uchar ret;
uchar tmp;

do{
tmp = TMSTS0;

if(tmp & 0x01){
ret = 1u;
}else{
switch(tmp){
case 0x00: //送信中
ret = 0;
break;
case 0x02: //アボート
ret = 0;
break;
case 0x04: //送信完了(アボートなし)
case 0x06: //送信完了(アボートあり)
ret = 0u;
break;
default:
ret = 1u;
break;

}
}

}while(0);


return ret;
}


void CAN_SendStart( void )
{
TMSTS0 &= 0xF9u; /* 送信結果フラグクリア */
while(( TMSTS0 & 0x06u ) != 0x00){} /* 送信ステータス確認 */

TMIDL0L = 0x12/* IDを格納 */
TMIDL0H = 0x34;

TMIDH0L = 0x00; /* 拡張ID */
TMIDH0H = 0x00; /* 拡張ID最上位1ビット、IDEビット、RTRビット、送信履歴データ格納許可ビットを格納 */

TMPTR0L = 0x00; /* 送信履歴バッファに格納するラベル情報 */
TMPTR0H = 0x40; /* DLCを格納 */
TMDF00L = 0xAA; /* 送信データ */
TMDF00H = 0xAA;
TMDF10L = 0xAA;
TMDF10H = 0xAA;

TMC0 |= 0x05u; /* 送信要求 TMTRを"1"に ワンショットも合わせて*/

//TMC0 |= 0x01u; /* 送信要求 TMTRを"1"に */
}

return ret;

}

//ここまでCAN設定

 

////メインルーチン

main(){

 

while( 1u ){

WDT_Reset(); /* ウォッチドッグタイマクリア */

if( TMIF07 ){ //1ms毎のイベント(TRD7-コンペアマッチ)
TM07_START_1ms();
i++;
if( i >= 100u ){ //100ms毎のタイミング
i = 0u;
//★★★送信バッファ0の送信★★★★★★★★★★★★★★★
if( CAN_Sendstatus() == 0u ){
/* 先の送信データがない場合→送信開始 */
CAN_SendStart(); /* 送信開始 */
}
else{
/* 送信中の場合→待機 */
}

}

}

}

 

 

 

 

  • マサさんこんにちはNAKAといいます。

    F14のCANは何年か前に1週間くらい悩んでデバイスドライバ作ったきり、その後は関数使うだけなのでレジスタの詳細は大分忘れちゃっているのですが、少し拝見すると例えば初期設定手順も18.10のフローになってないような気がします。CAN用RAMクリア⇒グローバルリセットモード⇒CANチャンネルリセットモードへ変遷させていくのもレジスタ変更⇒モード変遷を確認という手順になっているでしょうか?上の設定をみるとモードの確認⇒レジスタ設定の順になっているように見えます。18.10のフローチャートの順で設定していったら、動作しましたよ。

    ★高速オンチップを使った部分の設定例
    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に設定 
    C0CFGH = 0x0049;        //SJW=1 TSEG2=5 TSEG1=10 に設定 ボーレートプリスケラ(1)分周無しの場合
    C0CFGL = 0x0001;        //C0CFGL+1 = 2で分周(16MHz/2 =8MHz)=ボーレートプリスケラ = fCAN_8Mhz/((0+1)×16Tq)= 500Kbps
  • NAKAさん

    マサです。
    アドバイスありがとうございます。

    処理としては以下のことを想定してコーディングを行ったつもりでしたが、不備があったでしょうか?見直したのですが、わかりませんでした。

    どこかご指摘いただけると助かるのですがお願いできないでしょうか?

    また、今の処理でも動作はしています。ただ、考えていた挙動と違う挙動になっております。
    考えていた挙動:送信要求を出したたら任意のデータが出力される。
    実際の挙動:送信要求を出していないのにデータらしきもの(SOF)がたびたび出力される。



    ①RAMクリア処理
    ②念のため、グローバルストップモードにいることをステータスで確認
    ③グローバルストップモードからグローバルリセットモードに遷移させるためレジスタを設定
    ④レジスタ設定後、グローバルリセットモードに遷移したかを確認
    ⑤グローバルリセットモードに遷移したことを確認した後、チャンネルストップモードになっていることを念のため確認
    ⑥チャンネルストップモードからチャンネルリセットモードに遷移させるためレジスタを設定
    ⑦レジスタ設定後、チャンネルリセットモードに遷移したかを確認
    ⑧チャンネルリセットモードに遷移したことを確認した後、各種レジスタを設定

    ①RAMクリア処理
    while((GSTS&0x0008u)!=0u){} /* CAN用RAMクリアを待つ GRAMINITフラグが"0"になればRAMクリア */


    ②念のため、グローバルストップモードにいることをステータスで確認
    while((GSTS&0x0004u)==0u){} /* グローバルストップモードであるかを確認 GSLPSTSフラグが"1"であればグローバルストップモード */

    ③グローバルストップモードからグローバルリセットモードに遷移させるためレジスタを設定
    GCTRL &= 0xFFFDu; /* GSLPR=0 グローバルストップモード⇒グローバルリセットモードに変遷 (GMDC=01) */
    GCTRL |= 0x0001u;
    GCTRL &= 0xFFFBu;

    ④レジスタ設定後、グローバルリセットモードに遷移したかを確認
    while(((GSTS&0x0004u)==1u) && ((GSTS&0x0001u)==0u)){} /* CANグローバルリセットモード変遷を確認 GSRSTSTが1ならグローバルリセットモード*/

    ⑤グローバルリセットモードに遷移したことを確認した後、チャンネルストップモードになっていることを念のため確認
    while((C0STSL&0x0004u)==0u){} /* CANチャンネルストップモードかを確認 */

    ⑥チャンネルストップモードからチャンネルリセットモードに遷移させるためレジスタを設定
    C0CTRL &= 0xFFFDu; /* CSLPR=0 チャンネルストップモード⇒チャンネルリセットモードに変遷 (CHMDC=01) */
    C0CTRL |= 0x0001u;
    C0CTRL &= 0xFFFBu;


    ⑦レジスタ設定後、チャンネルリセットモードに遷移したかを確認
    while(((C0STSL&0x0004u)==1u) && ((C0STSL&0x0001u)==0u)){} /* CANチャンネルリセットモードに変遷を確認 */


    ⑧チャンネルリセットモードに遷移したことを確認した後、各種レジスタを設定
    /* クロック, ビットタイミング, 通信速度等の設定 */
    GCFGL = 0x0000u; /* DCS=0:fCAN=(fCLK/2)/TSP=8MHzに設定 */
    ~以下略~
  • 追伸

    NAKAさんに示してもらった一例でデバッグをしてみました。
    挙動は上記に挙げた内容と変わりませんでした。

    現状、評価ボード単体で自己ループするように終端抵抗をつけているのですが、
    もしかしてそれがおかしい挙動をしている可能性もでてきました。。。
  • マサさん NAKAです。

    確認ですが終端抵抗だけですか?CANバスに何か受信するデバイス(もう一つのマイコンボード、あるいはvectorのCAN-CASEなんかのモニタTOOL)ってついてます?ACKが返らないので再送しちゃうんじゃないでしょうか?終端抵抗は自己ループさせるものじゃなくて、CANバスのインピーダンスを下げ信号の反射を抑制する目的です。当たり前すぎたらごめんなさい!

  • NAKAさん

    マサです。

    終端抵抗だけです。受信するデバイスはついていません。
    現状、こんな感じにしています。

    |~~抵抗~~|
    CANL | |
    ~~~~~~~~~~~|===========● |
    評価ボード | | |
    ~~~~~~~~~~~|===========|========●
    CANH |~~抵抗~~|


    送信要求を一回だすとACKが返らないので、リトライし続けているのですかね。。。
    自己ループがそもそも間違いなような気がしてきました。
  • マサさん NAKAです。

    オシロで波形をモニタしているんでしょうか?

    こんな感じで受信してACKを返す何かをつないでおかないとモニタできませんよ。

    お手軽なのは、もう一枚評価ボードを用意することでしょうか?

    そうすれば、オシロじゃなくても、メッセージBOXの内容を確認すれば受信できたか?とか確認できますものね!

     

  • NAKAさん

    マサです。

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

    そもそも単体で確認しようとしていたこと自体が間違いだったのですね・・・

    単純にCANはUARTみたいなもので、送信ラインと受信ラインを繋げれば
    確認できるものだと認識でいました。

    勉強になりました。ありがとうございます。環境を整えてやってみます。

    不明点がありましたら、また質問させて頂きたいと思いますので、
    その時はまたよろしくお願いいたします。

    状況が変わりましたら、報告にまいります。
  • マサさん NAKAです。

    RXとかだと、トランシーバに物理的に信号を出さずにマイコン内部だけでループさせてデバッグできたと思います。
    RL78はどうだったかわかりません。幸いNAKAはすぐCAN信号をモニタできる環境があるので、直接ドライバー作って繋いで確認しちゃいます。環境整備もちょっとめんどくさいですが頑張ってくださいね!NAKAはたよりないですがもしお力になれればうれしいです。
    北斗電子さん¥7,800-でF14評価ボードを売ってます。僕も本番用基板が完成してからドライバ作る時間がなかったので、お手軽にボードを買って先に動作確認をしておきました。

  • >当方、CAN通信は初めてで、データシート等見比べていろいろ試したのですが

     初めて作るのに、いきなり複雑なプログラムを作っているのではないですか。
     順序としては次のようになるでしょう。
    ・簡単な送信プログラムを作り、波形を観測。フラグもチェック
    ・簡単な受信プログラムを作り、ACKを返すことを確認
  • CANそのものはある程度理解されてますか?
    CAN入門書( https://www.renesas.com/ja-jp/doc/products/mpumcu/apn/003/rjj05b0937_canap.pdf )を一通り読むことをお奨めします。
    ACKの話も出てきます。
    ボッシュの仕様書は入手が面倒で、ルネサスのCAN入門書の方が分かり易いです。