Help review S12G128 CAN code

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Help review S12G128 CAN code

675 Views
hansonhe
NXP Employee
NXP Employee

Dear,

Could you help review below code, whether it have some config problem.

Crystal: 4MHz

CAN Baud: 250Kbps

MCU: S12G128 64pin

void CAN2_NewInit(void)

{

     /* Initialise the CAN */

    CANCTL1_CANE = 1;                   /* enable CAN module */

    CANCTL0 = 0x01;                     /* enter init mode */

    while(!(CANCTL1_INITAK));                /* wait for init mode */

 

    CANCTL1 = 0x80;                              /* enable CAN module, Loopback Mode, Ext OSC */

    CANBTR0 = 0xC1;                              /* sync jump - 4 Tq clocks, prescalar = 3 */

    CANBTR1 = 0x01;                              /* Tseg = 3, Tseg1 = 10, 1 sample per bit */

    CANIDAC = 0x10;                          /* four 16-bit filters */

 

    CANIDAR0 = 0x20;                    /* Filter 0, ID=0x100 Standard Identifier */

    CANIDMR0 = 0x00;

    CANIDAR1 = 0x00;

    CANIDMR1 = 0x07;                    /* AM[2:0] = 7 to receive standard identifiers */

 

    CANIDAR2 = 0x00;                    /* Filter 1, ID=0x0000 */

    CANIDMR2 = 0x00;

    CANIDAR3 = 0x00;

    CANIDMR3 = 0x07;                    /* AM[2:0] = 7 to receive standard identifiers */

 

    CANIDAR4 = 0x00;                        /* Filter 2, ID=0x0000 */

    CANIDMR4 = 0x00;

    CANIDAR5 = 0x00;

    CANIDMR5 = 0x07;                    /* AM[2:0] = 7 to receive standard identifiers */

 

    CANIDAR6 = 0x00;                        /* Filter 3, ID=0x0000 */

    CANIDMR6 = 0x00;

    CANIDAR7 = 0x00;

    CANIDMR7 = 0x07;                    /* AM[2:0] = 7 to receive standard identifiers */

 

    CANCTL0 = 0x00;                              /* exit init mode */

    while(CANCTL1_INITAK);                                              /* wait until module exits init mode */

 

    while(!(CANCTL0_SYNCH));                           /* wait for CAN module to synch */

 

    CANRFLG = 0xC3;                                                                          /* reset Rx flags */

}

//byte CAN2_SendFrame(byte BufferNum,dword MessageID,byte FrameType,byte Length,const byte *Data)

void CAN2_NewSendFrame(byte Length, byte *Data)

{

      byte txbuffer;

      byte txCounter = 0;

     

      while(txCounter < Length)

      {

       

          while (!CANTFLG);               /* Wait for empty Tx Buffer */

          CANTBSEL = CANTFLG;                      /* Select the empty Tx Buffer */

          txbuffer = CANTBSEL;            /* Save the empty buffer */

 

          CANTXIDR0 = 0x18;               /* load message id value to ID regs */  //18FF0C20

          CANTXIDR1 = 0xFF;

          CANTXIDR2 = 0x0C;

          CANTXIDR3 = 0x20;

         

          CANTXDSR0 = *Data;                         /* load data to send */

 

          CANTXDLR = 0x01;                                    /* set data length */

          CANTXTBPR = 0x80;                       /* set data buffer priority */

 

          CANTFLG = txbuffer;             /* start transmission */

 

          while(!(CANTFLG & txbuffer));   /* wait for Tx to complete */

         

          txCounter++;

      }

}

 

//byte CAN2_ReadFrame(dword *MessageID,byte *FrameType,byte *FrameFormat,byte *Length,byte *Data)

void CAN2_NewReceiveFrame(dword *MessageID, byte Length, byte *Data)

{

      byte rxCounter = 0;

      while(rxCounter < Length)

      {

          if(CANRFLG_RXF)                 /* has a message been received ? */

          {

              *Data = CANRXDSR0;            /* Display transmitted PORTB on LEDs */

              CANRFLG_RXF = 1;            /* Clear RXF */

          }

         

          rxCounter++;

      }

}

0 Kudos
1 Reply

344 Views
lama
NXP TechSupport
NXP TechSupport

 

 

I have used easiest method to check it so I have compared your code with the code of mine which is designed for more messages prepared on background.

 

 

1) CAN bitrate. You can check in attached excel sheet I prepared for myself "a few" days ago. It considers more inputs to calculate the CANBTR registers. (CAN_setup5.xlsx)

2) Filters:

CANCTL1 – the loopback mode is not set but mentioned

CANBTR1, CANBTR0 you can check with attached file.

If I accept both data and remote frames the standard identifier 4x16 bit filter requires:

Just to check the first one:

IDE – filter standard frame(must be 0), RTR = 0 if we consider to accept the data frames only

So, for ID 0x100:

ID               10 9 8 7 6 5 4 3 2 1 0 RTR IDE X X X

IDAR0     0  1 0 0 0 0 0 0 0 0 0    0      0  0 0 0   =  0x20 00

IDMR          0  0 0 0 0 0 0 0 0 0 0    0      0  1 1 1                   = 0x 00 07

 

Your setup is OK if you do not want to accept remote frames.

 

If you want to accept the only this one then all other IDAR and IDMR should be set to the same values.

 

3) Initialization, comparing your and my code I can say OK

void init_CAN(UBYTE _canbtr0, UBYTE _canbtr1, UBYTE loop)

{

 if(loop) loop=CANCTL1_LOOPB_MASK;

CANCTL0 = CANCTL0_INITRQ_MASK;

 while(!(CANCTL1 & CANCTL1_INITAK_MASK));

 

 CANCTL1  = 0x80 | loop;                  // Enables MSCAN, oscillator clock, Loop Enabled/Disabled and Normal Operation

 CANBTR0  = _canbtr0;                     //

 CANBTR1  = _canbtr1;                     //

 

 CANIDMR0 = CANIDMR1 = CANIDMR2 = CANIDMR3 = 0xFF; // receive everything

 CANIDMR4 = CANIDMR5 = CANIDMR6 = CANIDMR7 = 0xFF;

 

 CANCTL0  = 0x00;                               // restarts MSCAN peripheral

 while(CANCTL1 & CANCTL1_INITAK_MASK);   // wait for Initialization Mode exit

 while(!(CANCTL0 & CANCTL0_SYNCH_MASK)); // waits for MSCAN synchronization with the CAN bus

 CANRFLG = 0xC3;                                     // clear flags

}

4) Sending a message – only for inspiration

//==============================================================================

void createMessage(tCAN_MSG *msg,UINT id,BOOL RTR,UBYTE len,UBYTE prty,

                   UBYTE d0,UBYTE d1,UBYTE d2,UBYTE d3,UBYTE d4,UBYTE d5,UBYTE d6,UBYTE d7 )

{

  msg->id  = id;

  msg->RTR = RTR;

  msg->data[0]= d0;

  msg->data[1]= d1;

  msg->data[2]= d2;

  msg->data[3]= d3;

  msg->data[4]= d4;

  msg->data[5]= d5;

  msg->data[6]= d6;

  msg->data[7]= d7;

  msg->len =len;      

  msg->prty=prty;

}

//==============================================================================

//typedef struct { UINT  id; BOOL  RTR; UBYTE data[8]; UBYTE len; UBYTE prty;}tCAN_MSG;

//==============================================================================

BOOL MSCANSendMsg(tCAN_MSG *msg)

{              

 UBYTE txbuffer = 0, i;

 UBYTE *can_DSR = &CANTXDSR0;

 

 if(msg->len > 8) return(0);

 if(!(CANCTL0 & CANCTL0_SYNCH_MASK)) return(0);

  

 CANTBSEL = CANTFLG;                      // Select lowest empty buffer

 txbuffer = CANTBSEL;                             // Backup selected buffer 

 

 CANTXIDR0 = (UBYTE)(msg->id>>3);         // insert ID MSB

 CANTXIDR1 = (UBYTE)(msg->id<<5);         // insert last 3 bits of ID to the msb

 

 if(msg->RTR) CANTXIDR1 |= 0x10;

 

 for(i = 0; i < msg->len; i++)

                              can_DSR[i] = msg->data[i];

 

 CANTXDLR  = msg->len;                                                                                                                                                     // set message data length

 CANTXTBPR = msg->prty;                                                                                                                                                  // set message internal priority

 CANTFLG   = txbuffer;                    // clear flag to send message

 

 return(1);

}

 

5) Receiving the message – the message is split into components only for example purpose

 

Not sure but you will still read the same data from the first data byte of the buffer. I missing increment for reading of all valid bytes.

 

BOOL MSCANGetMsg(tCAN_MSG *msg)

{

 UBYTE i;

 UBYTE *can_DSR = &CANRXDSR0;

 

 

 if(!(CANRFLG & CANRFLG_RXF_MASK)) return(0); // if no new message=>return

 if(CANRXIDR1 & 0x08)               return(0); // if not standard identifier=>return

 msg->id = ((CANRXIDR0<<3)&0x0700) | (UBYTE)(CANRXIDR0<<3) | (UBYTE)(CANRXIDR1>>5);

 

 if(CANRXIDR1 & 0x10) msg->RTR = 1;

 else                          msg->RTR = 0;

 

 msg->len = CANRXDLR;

 for(i = 0; i < msg->len; i++)

                              msg->data[i] = can_DSR[i];

 CANRFLG = CANRFLG_RXF_MASK;

 return(1);

}

 

 

6) I would suggest you to use loopback mode before you will start to communicate with other nodes. This is the first step to be sure I am correctly Tx and Rx.

   

 

Best regards,

Ladislav

0 Kudos