お世話になります。
RX71MでCAN通信の環境構築をしようとしているものです。
今回CANの送信時にいくつかの疑問が生じてしまったので、お力添えいただいただけないかと投稿させていただきました。
まず、今回使用しているmain関数のPCへのCAN送信部分を以下に示させていただきます。
//送信処理(キーボード0-7がMB[0]-[7]に対応) xc=sciRead(); s_mb=0xff; switch(xc) { case '0': s_mb=0; //使用するメールボックス番号 s_dlc=1; //送信バイト数 break; case '1': s_mb=1; s_dlc=2; break; case '2': s_mb=2; s_dlc=3; break; case '3': s_mb=3; s_dlc=4; break; case '4': s_mb=4; s_dlc=5; break; case '5': s_mb=5; s_dlc=6; break; case '6': s_mb=6; s_dlc=7; break; case '7': s_mb=7; s_dlc=8; break;#if (LED_PORT_NUM > 0) case 'z': //ボード識別向けLED点滅 sciPrintBuf("LED blink test(for board identify).\n"); led=LED1_PORT; for(l=0; l<3; l++) { LED1_PORT=1; for(x=0; x<1000000; x++) nop(); LED1_PORT=0; for(x=0; x<1000000; x++) nop(); } LED1_PORT=led; break;#endif case 'c': for(l=0; l<CAN_CH; l++) { send_can_ch++; if(send_can_ch>=CAN_CH) send_can_ch=0; if(varid_can_ch[send_can_ch] == 1) break; } sciPrintBuf("CAN send channel -> CAN"); sciWriteBuf(send_can_ch+0x30); sciPrintBuf("\n"); break; default: break; } if(s_mb != 0xff) { switch(send_can_ch) { case 0:#if (CAN0_VALID == 1) s_ret = can0_send(s_mb, s_dlc, &s_data[0]);#endif break; case 1:#if (CAN1_VALID == 1) s_ret = can1_send(s_mb, s_dlc, &s_data[0]);#endif break; case 2:#if (CAN2_VALID == 1) s_ret = can2_send(s_mb, s_dlc, &s_data[0]);#endif break; default: break; } sciPrintBuf("CAN"); sciWriteBuf(send_can_ch+0x30); sciPrintBuf(" data send, MB=0x"); sciPrintByteBuf(s_mb); sciPrintBuf(" ret=0x"); sciPrintWordBuf(s_ret); if(s_ret==0) { sciPrintBuf(" id=MB "); sciPrintBuf(" data=0x"); for(j=0; j<s_dlc; j++) { if(j>=8) break; sciPrintByteBuf(s_data[j]); } } sciPrintBuf("\n"); }
ざっくりいうと
・もともと用意していたデータを用意していたメールボックスにいれ(送信処理前に行っています)
・switch関数を用いてキーボードの0~7に対応するメールボックスの番号とデータ量を指定
・switch文を抜けた後に、s_retで送信関数を呼び出してPCへの送信を行う
というような流れになっていると理解しています。
送信用の関数は以下のようになっています。
int can0_send(unsigned char mb, unsigned char dlc, unsigned char *data){ //CAN0 送信関数 //戻り値 // 0 : 正常終了 // -1 : 引数チェックエラー // -2 : レジスタ値設定変更タイムアウト // -3 : メールボックスが受信に設定されている // -4 : メールボックス送信中 //引数 // mb : メールボックス番号(0-31) // dlc : 送信バイト数(1-8) // *data : 送信データ unsigned short i, loop; unsigned char reg8; if(mb>31) return -1; if((dlc == 0) || (dlc>8)) return -1; //メールボックスが受信モードに設定されているときはエラーとする if(CAN0.MCTL[mb].BIT.RX.RECREQ == 1) { return -3; } if(CAN0.MCTL[mb].BIT.TX.TRMACTIVE == 1) { //メールボックス送信中 return -4; } //TRMREQ=0 reg8 = CAN0.MCTL[mb].BYTE; reg8 &= ~0x80; CAN0.MCTL[mb].BYTE = reg8; loop=0; while(CAN0.MCTL[mb].BIT.TX.TRMREQ != 0) { loop++; if(loop > CAN_LOOP_TIMEOUT) return -2; } //SENTDATA=0 reg8 = CAN0.MCTL[mb].BYTE; reg8 &= ~0x01; CAN0.MCTL[mb].BYTE = reg8; loop=0; while(CAN0.MCTL[mb].BIT.TX.SENTDATA != 0) { loop++; if(loop > CAN_LOOP_TIMEOUT) return -2; } //メールボックスにデータセット for(i=0; i<dlc; i++) { CAN0.MB[mb].DATA[i] = *data++; } CAN0.MB[mb].DLC = dlc; CAN0.MCTL[mb].BIT.TX.TRMREQ = 1; //メールボックスを送信モードに設定 return 0;}
キーボードを押すと、それに対応したCAN通信先のPCで送られてきたデータに対する応答用の表示が確認できています。
ここでキーボード入力をしないとデータ送信ができないとなるとなにかと不便ではないかと考え、まずswitch文を用いないでデータの送信をやろうと考え以下のようしました。
//送信処理(キーボード0-7がMB[0]-[7]に対応) s_mb=0xff; s_mb=0; s_dlc=1; s_ret = can0_send(s_mb, s_dlc, &s_data[0]); /*xc=sciRead(); switch(xc) { case '0': s_mb=0; //使用するメールボックス番号 s_dlc=1; //送信バイト数 break; case '1': s_mb=1; s_dlc=2; break; case '2': s_mb=2; s_dlc=3; break; case '3': s_mb=3; s_dlc=4; break; case '4': s_mb=4; s_dlc=5; break; case '5': s_mb=5; s_dlc=6; break; case '6': s_mb=6; s_dlc=7; break; case '7': s_mb=7; s_dlc=8; break;#if (LED_PORT_NUM > 0) case 'z': //ボード識別向けLED点滅 sciPrintBuf("LED blink test(for board identify).\n"); led=LED1_PORT; for(l=0; l<3; l++) { LED1_PORT=1; for(x=0; x<1000000; x++) nop(); LED1_PORT=0; for(x=0; x<1000000; x++) nop(); } LED1_PORT=led; break;#endif case 'c': for(l=0; l<CAN_CH; l++) { send_can_ch++; if(send_can_ch>=CAN_CH) send_can_ch=0; if(varid_can_ch[send_can_ch] == 1) break; } sciPrintBuf("CAN send channel -> CAN"); sciWriteBuf(send_can_ch+0x30); sciPrintBuf("\n"); break; default: break; }*/ /*if(s_mb != 0xff) { switch(send_can_ch) { case 0:#if (CAN0_VALID == 1) s_ret = can0_send(s_mb, s_dlc, &s_data[0]);#endif break; case 1:#if (CAN1_VALID == 1) s_ret = can1_send(s_mb, s_dlc, &s_data[0]);#endif break; case 2:#if (CAN2_VALID == 1) s_ret = can2_send(s_mb, s_dlc, &s_data[0]);#endif break; default: break; } */ sciPrintBuf("CAN"); sciWriteBuf(send_can_ch+0x30); sciPrintBuf(" data send, MB=0x"); sciPrintByteBuf(s_mb); sciPrintBuf(" ret=0x"); sciPrintWordBuf(s_ret); if(s_ret==0) { sciPrintBuf(" id=MB "); sciPrintBuf(" data=0x"); for(j=0; j<s_dlc; j++) { if(j>=8) break; sciPrintByteBuf(s_data[j]); } } sciPrintBuf("\n"); //}
最初にメールボックスの番号とデータ量を指定し、送信関数を呼び出してしてswitch文をコメントアウトしました。
しかし、ここで以前のような表示がCAN通信先のPCで見られなくなり、一回分だけ表示ができる時とできない場合があったりします。
ここで疑問なのですが、
・switch文のcase0と私が書いたコードは同義ではないのでしょうか
・そもそもmain自体がwhile(1)でまわっている(まわしています)のに一回分しか送信されないことはどこか私が書いたコードに問題があるのでしょうか
初歩的なプログラムの疑問ですみません、どなたかお力添えいただけないでしょうか。
よろしくお願い致します。
makiさん、こんにちは。NoMaYです。すみません、リプライが前後してしまいますが、改造したプログラムでは、
//送信処理(キーボード0-7がMB[0]-[7]に対応) s_mb=0xff; s_mb=0; s_dlc=1; s_ret = can0_send(s_mb, s_dlc, &s_data[0]);
↑が↓の代わりだったのですね、今、理解しました。勘違いして、御免なさい。
/*if(s_mb != 0xff) { switch(send_can_ch) { case 0:#if (CAN0_VALID == 1) s_ret = can0_send(s_mb, s_dlc, &s_data[0]);#endif break; case 1:#if (CAN1_VALID == 1) s_ret = can1_send(s_mb, s_dlc, &s_data[0]);#endif break; case 2:#if (CAN2_VALID == 1) s_ret = can2_send(s_mb, s_dlc, &s_data[0]);#endif break; default: break; } */
NoMaYさん、こんにちはmakiです。
いえいえ、改造したプログラムがわかりにくく、説明も不足していた私が悪いです。
丁寧にありがとうございます。