いつもお世話になっております。
「マサ」と申します。
現在,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{ /* 送信中の場合→待機 */ }
CANそのものはある程度理解されてますか? CAN入門書( https://www.renesas.com/ja-jp/doc/products/mpumcu/apn/003/rjj05b0937_canap.pdf )を一通り読むことをお奨めします。 ACKの話も出てきます。 ボッシュの仕様書は入手が面倒で、ルネサスのCAN入門書の方が分かり易いです。