Top Page [◀◀]  2   3   4   5   6   7   8   9   ... [▶▶Last Page

CANの二チャンネル同時の実装の方法

はじめまして、サーサーです。

 

RX63Nにて、CAN0とCAN2の二つを使って二チャンネル同時の通信を実装しようと思っています。

レジスタの設定、割り込み、メールボックスを二つ用意するところまではわかったのですが、

ほかに何を二チャンネル分用意すればいいのかよくわかりません。

一チャンネルは実装されているソースに二つ目を増設しているのですが、

二つ必要なものと一つを共有できるものの区別が付かず、

エラー割り込みが頻発し、ほかのタスクが動かない状況です。

メールボックスはポインタで初期設定を行なうときに切り替えるようにしています。

 

なにかヒントを教えていただけたら幸いです。

 

/** CAN Controller address */

static volatile struct codrv_st_can __evenaccess * pCan;
static volatile struct codrv_st_can __evenaccess * CO_CONST pCan0 =
((volatile struct codrv_st_can __evenaccess *)0x90200);
static volatile struct codrv_st_can __evenaccess * CO_CONST pCan2 =
((volatile struct codrv_st_can __evenaccess *)0x92200);

 

static RET_T codrvCanInitController(
UNSIGNED16 bitRate,
int canPort
)
{
RET_T retVal;
UNSIGNED16 i,j;
UNSIGNED8 interruptSource = 0;

/* init req. variables */
canEnabled = CO_FALSE;
transmissionIsActive = CO_FALSE;

pTxBuf = NULL;

if( canPort == 0 )
pCan = pCan0;
else
pCan = pCan2;

/* error states */
codrvCanErrorInit();

/* disable sleep mode */
retVal = setCanMode(RX_CAN_MODE_LEAVE_SLEEP);
if (retVal != RET_OK) {
return(retVal);
}

/* enter reset mode */
retVal = setCanMode(RX_CAN_MODE_RESET);
if (retVal != RET_OK) {
return(retVal);
}

/*** Setting of CAN0 Control register.***/
/* BOM: Bus Off recovery mode acc. to IEC11898-1 */
pCan->CTLR.BIT.BOM = 0;


/* MBM: Select normal mailbox mode. */
pCan->CTLR.BIT.MBM = 0;

/* IDFM: Select standard and extented ID mode. */
pCan->CTLR.BIT.IDFM = 2;
// pCan->CTLR.BIT.IDFM = 0;

/* 0 = Overwrite mode: Latest message overwrites old.
1 = Overrun mode: Latest message discarded. */
pCan->CTLR.BIT.MLM = 1;

/* TPM: ID priority mode. */
pCan->CTLR.BIT.TPM = 0;

~~以下略~~

 

 

// 割り込みの設定

if ((canInterruptEnableFlags & 8) != 0) {
 IPR(CAN0, RXM0) = CAN0_INT_LVL;
 IEN(CAN0, RXM0) = 1;
 def_inh( INT_CAN0_RXM0, &dinh_can_rxm0);
}
if ((canInterruptEnableFlags & 4) != 0) {
 IPR(CAN0, TXF0) = CAN0_INT_LVL;
 IEN(CAN0, TXF0) = 1;
 def_inh( INT_CAN0_TXF0, &dinh_can_txf0);
}
 if ((canInterruptEnableFlags & 0x10) != 0) {
 IPR(CAN0, TXM0) = CAN0_INT_LVL;
 IEN(CAN0, TXM0) = 1;
 def_inh( INT_CAN0_TXM0, &dinh_can_txm0);
}
if ((canInterruptEnableFlags & 2) != 0) {
 IPR(CAN0, RXF0) = CAN0_INT_LVL;
 IEN(CAN0, RXF0) = 1;
}

if ((canInterruptEnableFlags & 1) != 0) {
 /* ICU Group 0 */
 IEN(ICU, GROUP0) = 1;
 IPR(ICU, GROUP0) = CAN0_INT_LVL;
 def_inh( INT_GROUP0, &dinh_can_err0);
 EN(CAN0, ERS0) = 1;
}

if ((canInterruptEnableFlags & 8) != 0) {
 IPR(CAN2, RXM2) = CAN2_INT_LVL;
 IEN(CAN2, RXM2) = 1;
 def_inh( INT_CAN2_RXM0, &dinh_can_rxm2);
}
if ((canInterruptEnableFlags & 4) != 0) {
 IPR(CAN2, TXF2) = CAN2_INT_LVL;
 IEN(CAN2, TXF2) = 1;
 def_inh( INT_CAN2_TXF0, &dinh_can_txf2);
}
if ((canInterruptEnableFlags & 0x10) != 0) {
 IPR(CAN2, TXM2) = CAN2_INT_LVL;
 IEN(CAN2, TXM2) = 1;
 def_inh( INT_CAN2_TXM0, &dinh_can_txm2);
}
if ((canInterruptEnableFlags & 2) != 0) {
 IPR(CAN2, RXF2) = CAN2_INT_LVL;
 IEN(CAN2, RXF2) = 1;
}

if ((canInterruptEnableFlags & 1) != 0) {
 /* ICU Group 0 */
 IEN(ICU, GROUP1) = 1;
 IPR(ICU, GROUP1) = CAN2_INT_LVL;
 def_inh( INT_GROUP1, &dinh_can_err2);
 EN(CAN2, ERS2) = 1;
}

 

// レジスタの設定

SYSTEM.PRCR.WORD = 0xA502;
MSTP_CAN2 = 0; /* CAN2 */
SYSTEM.PRCR.WORD = 0xA500;

PORT6.PODR.BIT.B6 = 1;
PORT6.PDR.BIT.B6 = 1;

MPC.PWPR.BIT.B0WI = 0;
MPC.PWPR.BIT.PFSWE = 1;
MPC.P66PFS.BIT.PSEL = 0x10;
MPC.P67PFS.BIT.PSEL = 0x10;
MPC.PWPR.BIT.PFSWE = 0;
MPC.PWPR.BIT.B0WI = 1;

PORT6.PMR.BIT.B6 = 1;
PORT6.PMR.BIT.B7 = 1;

SYSTEM.PRCR.WORD = 0xA502;
MSTP_CAN0 = 0; /* CAN0 */
SYSTEM.PRCR.WORD = 0xA500;

PORT3.PODR.BIT.B2 = 1;
PORT3.PDR.BIT.B2 = 1;

MPC.PWPR.BIT.B0WI = 0;
MPC.PWPR.BIT.PFSWE = 1;
MPC.P32PFS.BIT.PSEL = 0x10; //CTX0
MPC.P33PFS.BIT.PSEL = 0x10; //CRX0
MPC.PWPR.BIT.PFSWE = 0;
MPC.PWPR.BIT.B0WI = 1;

PORT3.PMR.BIT.B3 = 1;
PORT3.PMR.BIT.B2 = 1;

  • サーサーさん おはようございますNAKAといいます。

    >ほかに何を二チャンネル分用意すればいいのかよくわかりません。
    逆にモジュールストップのレジスタ設定以外全て必要なのではないでしょうか?

    CAN0の初期設定、関数をエディタにコピーしCAN0部分を検索し、CAN2に置換したほうが早いかも!!
    例)CAN0.CTLR.BIT.CANM = 1; ⇒ CAN2.CTLR.BIT.CANM = 1;

    ただし、ピンファンクションや割込みベクターなどはCAN2用に変更が必要ですが!!


    /*******************************************************************************
    // 関数名 : fn_Init_CAN0(void)
    // 動作 : CAN0の初期化
    // 引数 :
    // 作成 : NAKA 12.02.15
    // 改定 : NAKA 13.08.26 データフレームに初期設定
    // ****************************************************************************/
    void fn_Init_CAN0(void)
    {
    unsigned char i;
    unsigned char j;

    SYSTEM.PRCR.WORD = 0xA503; //WORDで変更しないとNG! MSTPCRBはプロテクト1
    SYSTEM.MSTPCRB.BIT.MSTPB0 = 0; //CAN0モジュールストップを0:解除 P254

    PORTD.PMR.BIT.B1 = 0; //PD1(CTX0)を汎用I/O機能にset
    PORTD.PMR.BIT.B2 = 0; //PD2(CRX0)を汎用I/O機能にset

    //マルチピンファンクションでpin設定
    MPC.PWPR.BIT.B0WI = 0; //PFSWE書込み 0:許可 P510
    MPC.PWPR.BIT.PFSWE = 1; //PFS書込み  1:許可 P510

    MPC.PD1PFS.BIT.PSEL = 0x10; //PD1⇒CTX0 set! P529
    MPC.PD2PFS.BIT.PSEL = 0x10; //PD2⇒CRX0 set! P529

    MPC.PWPR.BIT.PFSWE = 0; //PFS書込み 0:禁止
    MPC.PWPR.BIT.B0WI = 1; //PFSWE書込み 1:禁止

    PORTD.PMR.BIT.B1 = 1; //PD1(CTX0)を周辺機能にset
    PORTD.PMR.BIT.B2 = 1; //PD2(CRX0)を周辺機能にset

    CAN0.CTLR.BIT.CANM = 1; //CAN0リセット(設定)モードに変更
    while(!CAN0.STR.BIT.RSTST){} //リセットモードになったか確認

    CAN0.CTLR.BIT.SLPM = 0; //CAN0スリープモードを解除
    while(CAN0.STR.BIT.SLPST){} //スリープモード解除になったか確認

    //ビットレートの設定
    CAN0.BCR.BIT.CCLKS = 1; //メインクロック16MHzを使用
    CAN0.BCR.BIT.TSEG2 = 1; //Tseg2=2Tq
    CAN0.BCR.BIT.SJW = 0; //SJW=1Tq

    CAN0.BCR.BIT.BRP = 3; //分周比4(P+1) (16MHz/(8Tq×4))=500Kbps
    //CAN0.BCR.BIT.BRP = 7; //分周比4(P+1) (16MHz/(8Tq×8))=250Kbps
    //CAN0.BCR.BIT.BRP = 15; //分周比4(P+1) (16MHz/(8Tq×16))=125Kbps
    //CAN0.BCR.BIT.BRP = 19; //分周比4(P+1) (16MHz/(8Tq×20))=100Kbps
    CAN0.BCR.BIT.TSEG1 = 4; //Tseg1=5Tq


    以下省略




    /*******************************************************************************
    // 関数名 : fn_Init_CAN2(void)
    // 動作 : CAN2の初期化
    // 引数 :
    // 作成 : NAKA 12.02.22
    // 改定 : NAKA 13.08.26 データフレームに初期設定
    // ****************************************************************************/
    void fn_Init_CAN2(void)
    {
    unsigned char i;
    unsigned char j;

    SYSTEM.PRCR.WORD = 0xA503; //WORDで変更しないとNG! MSTPCRBはプロテクト1
    SYSTEM.MSTPCRB.BIT.MSTPB2 = 0; //CAN2モジュールストップを0:解除 P254

    PORT6.PMR.BIT.B6 = 0; //P66(CTX0)を汎用I/O機能にset
    PORT6.PMR.BIT.B7 = 0; //P67(CRX0)を汎用I/O機能にset

    //マルチピンファンクションでpin設定
    MPC.PWPR.BIT.B0WI = 0; //PFSWE書込み 0:許可 P569
    MPC.PWPR.BIT.PFSWE = 1; //PFS書込み  1:許可 P569
    MPC.P66PFS.BIT.PSEL = 0x10; //P66⇒CTX0 set! P577
    MPC.P67PFS.BIT.PSEL = 0x10; //P67⇒CRX0 set! P577
    MPC.PWPR.BIT.PFSWE = 0; //PFS書込み 0:禁止
    MPC.PWPR.BIT.B0WI = 1; //PFSWE書込み 1:禁止

    PORT6.PMR.BIT.B6 = 1; //P66(CTX0)を周辺機能にset
    PORT6.PMR.BIT.B7 = 1; //P67(CRX0)を周辺機能にset

    CAN2.CTLR.BIT.CANM = 1; //CAN2リセット(設定)モードに変更
    while(!CAN2.STR.BIT.RSTST){} //リセットモードになったか確認

    CAN2.CTLR.BIT.SLPM = 0; //CAN2スリープモードを解除
    while(CAN2.STR.BIT.SLPST){} //スリープモード解除になったか確認

    //ビットレートの設定
    CAN2.BCR.BIT.CCLKS = 1; //メインクロック16MHzを使用
    CAN2.BCR.BIT.TSEG2 = 1; //Tseg2=2Tq
    CAN2.BCR.BIT.SJW = 0; //SJW=1Tq
    CAN2.BCR.BIT.BRP = 3; //分周比4(P+1) (16MHz/(8Tq×4))=500Kbps
    CAN2.BCR.BIT.TSEG1 = 4; //Tseg1=5Tq


    以下省略
  • In reply to NAKA:

    NAKAさん

    ありがとうございます。

    なるほど、それらのレジスタの設定がいろんな関数に散らばっていたので
    気づきませんでした。

    参考にさせていただきます。

Top Page [◀◀]  2   3   4   5   6   7   8   9   ... [▶▶Last Page