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