Reply by Edward Karpicz January 17, 20052005-01-17
Hi,

Your SendCANMessage routine is sending 11 bit RTR messages. Only ID bits and
data length bits can be carried by RTR message. It's not possible to send
any data byte when RTR is set.

> void SendCANMessage(unsigned char NumBytes, unsigned char *BufPntr){
>
> unsigned char NACAN,C;
> while(!CAN0TFLG); // wait for available buffer
> NACAN0TFLG; // get the next available CAN buffer
> CAN0TBSEL=NACAN;
>
> CAN0TXIDR0 = 0x2D;
> CAN0TXIDR1 = 0xF0;

^^ ID2:0=7, RTR=1, IDE=0. Check the "Standard Identifier Mapping" in MSCAN
docs. > CAN0TXIDR2 = 0x00;
> CAN0TXIDR3 = 0x00;


BTW
> CAN0RFLG |=1; // clear rec flag

^^^ this line can clear more than just CAN0RFLG RXF bit. If for example
CSCIF is set it will be cleared too.

Edward
> Hello,
>
> i'm fairly new in HCS12 an CAN programming and have a problem getting
> the MSCAN Module to work properly. The problem is that i try to write
> a little CANMonitor for the MC9S12DG256 in C (using ImageCraft ICC12
> Version 6). For the first tests i adapted a code example from Steve
> Letkeman with interrupt driven CAN Receive and the MSCAN Module is
> working in Loopback Mode. But when i try to debug the program i see
> that the transmit an the recieve buffers differ. That means that the
> received data is not the same as the transmitted data.
>
> When i transmit the following:
> CANID0 = 0x2d;
> CANID1 = 0xf0;
> CANID2 = 0x00;
> CANID3 = 0x00;
> CANDATA0 = 0x01;
> CANDATA0 = 0x02;
> CANDATA0 = 0x03;
> CANDATA0 = 0x04;
> CANDATA0 = 0x05;
> CANDATALENGTH = 0x05;
>
> i get the following in the receive buffer:
> CANID0 = 0x2d;
> CANID1 = 0xf0;
> CANID2 = 0xEF;
> CANID3 = 0x8E;
> CANDATA0 = 0xF3;
> CANDATA0 = 0xC7;
> CANDATA0 = 0x00;
> CANDATA0 = 0xAF;
> CANDATA0 = 0x1D;
> CANDATALENGTH = 0x05;
>
> So the received data is partly correct - why?
>
> The CAN Initialisation is done by the following function:
>
> =========================================================
> void CANInit(void){
>
> CAN0CTL0 |= INITRQ; // set INITRQ, this will also set INITAK
> while (!(CAN0CTL1 & INITAK)); // wait for init mode to occur
>
> CAN0CTL1 = 0xA0;
>
> CAN0BTR0=0x28; // BRPR = 40, Sync = 1
> CAN0BTR1=0x32; // TSEG1 = 3, TSEG2 = 4
>
> CAN0IDAR0=0xFF;
> CAN0IDAR1=0xFF;
> CAN0IDAR2=0xFF;
> CAN0IDAR3=0xFF;
> CAN0IDAR4=0xFF;
> CAN0IDAR5=0xFF;
> CAN0IDAR6=0xFF;
> CAN0IDAR7=0xFF;
>
> CAN0IDMR0=0xFF;
> CAN0IDMR1=0xFF;
> CAN0IDMR2=0xFF;
> CAN0IDMR3=0xFF;
> CAN0IDMR4=0xFF;
> CAN0IDMR5=0xFF;
> CAN0IDMR6=0xFF;
> CAN0IDMR7=0xFF;
>
> CAN0IDAC = 0;
> CAN0CTL0 &= ~INITRQ; // clear INITRQ
> while (CAN0CTL1 & INITAK);
>
> CAN0RFLG = 0xFF;
> CAN0CTL1 = 0xA0;
>
> CAN0RIER = 1;
> }
> =======================================================
>
> I had to redirect the interrupt vectors because of the monitor
> program:
>
> =======================================================
>
> void interruptRedirect(void){
>
> // CAN 0 Recieve Interrupt
> ///////////////////////////
> *((unsigned char *)0x3F8E) = 0x06;
> *((void (**)(void))0x3F8F) = CAN_Recieve;
>
> // CAN 0 Transmit Interrupt
> //////////////////////////
> *((unsigned char *)0x3F8B) = 0x06;
> *((void (**)(void))0x3F8C) = CAN_Transmit;
>
> // CAN 0 Error Interrupt
> //////////////////////////
> *((unsigned char *)0x3F91) = 0x06;
> *((void (**)(void))0x3F92) = CAN_Error;
> }
>
> =================================================
> The ISR for CAN receive looks like this:
> =================================================
>
> #pragma interrupt_handler CAN_Recieve
> void CAN_Recieve(void){
>
> int i=0, x=0;
>
> // Find Empty MessageBuffer
> ///////////////////////////
> while(CANMess[i].messact != 0) i++;
> if (i > MAXCANMESSAGES){
> if(DEBUGPRINT) printf("CAN Trancieve Error: No Free Buffer to store
> Message !");
> CAN0RFLG |=1; // clear rec flag
> return;
> }
>
> // Set status of Message to Recieve Message
> ///////////////////////////////////////////
> CANMess[i].messact = 1;
>
> // Check for Number of Bytes in CAN Message
> ///////////////////////////////////////////
> CANMess[i].length = CAN0RXDLR & 0x0F;
>
> // Copy ID to Messagebuffer
> ///////////////////////////
> CANMess[i].id0 = CAN0RXIDR0;
> CANMess[i].id1 = CAN0RXIDR1;
> CANMess[i].id2 = CAN0RXIDR2;
> CANMess[i].id3 = CAN0RXIDR3;
>
> // Copy Data to Messagebuffer
> /////////////////////////////
> for (x=0;x<CANMess[i].length;x++)
> CANMess[i].data[x] = *(CAN0RXDATA+x);
>
> CAN0RFLG |=1; // clear rec flag
> }
>
> ====================================================
> And this is the main function:
> ====================================================
> void main(void){
>
> int i=0, j=0;
> unsigned char ch;
> unsigned char temp[5];
>
> for(i=0;i<MAXCANMESSAGES;i++) CANMess[i].messact=0;
>
> interruptRedirect(); // Redirect Interrupts
> CANInit(); // Init MSCAN
>
> asm("cli"); // Enable global Interrupts
>
> temp[0] = 1;
> temp[1] = 2;
> temp[2] = 3;
> temp[3] = 4;
> temp[4] = 5;
>
> SendCANMessage(5,temp);
> while(1){
> // Checking Messagebuffer for Entrys
> ////////////////////////////////////
> for(i=0;i<MAXCANMESSAGES;i++){
> if(CANMess[i].messact == 1){
> CANMess[i].messact = 0;
>
> SendCANMessage(5,temp);
> }
> }
> }
> }
>
> ==============================================
> The SendCANMessage looks like this:
> ==============================================
> void SendCANMessage(unsigned char NumBytes, unsigned char *BufPntr){
>
> unsigned char NACAN,C;
> while(!CAN0TFLG); // wait for available buffer
> NACAN0TFLG; // get the next available CAN buffer
> CAN0TBSEL=NACAN;
>
> CAN0TXIDR0 = 0x2D;
> CAN0TXIDR1 = 0xF0;
> CAN0TXIDR2 = 0x00;
> CAN0TXIDR3 = 0x00;
>
> if (NumBytes>8) NumBytes=8;
> for (C=0;C<NumBytes;C++)
> *(CAN0TXDATA+C)=*BufPntr++; // store the data
>
> CAN0TXDLR=NumBytes; // set number of bytes to send
> NACAN0TBSEL;
> CAN0TFLG =NACAN; // transmit
> }
>
> ===========================================================
>
> I have tested the the program an 2 different MC9S12 but the result is
> the same - the tranmsitted message is not equal to the received. Have
> i missed something?
>
> Thanks in advance.
> Greets Daniel
>
> PS: I must apologize for my bad english. >
>
> Yahoo! Groups Links >
>


Reply by Daniel Winkler January 17, 20052005-01-17

Hello,

i'm fairly new in HCS12 an CAN programming and have a problem getting
the MSCAN Module to work properly. The problem is that i try to write
a little CANMonitor for the MC9S12DG256 in C (using ImageCraft ICC12
Version 6). For the first tests i adapted a code example from Steve
Letkeman with interrupt driven CAN Receive and the MSCAN Module is
working in Loopback Mode. But when i try to debug the program i see
that the transmit an the recieve buffers differ. That means that the
received data is not the same as the transmitted data.

When i transmit the following:
CANID0 = 0x2d;
CANID1 = 0xf0;
CANID2 = 0x00;
CANID3 = 0x00;
CANDATA0 = 0x01;
CANDATA0 = 0x02;
CANDATA0 = 0x03;
CANDATA0 = 0x04;
CANDATA0 = 0x05;
CANDATALENGTH = 0x05;

i get the following in the receive buffer:
CANID0 = 0x2d;
CANID1 = 0xf0;
CANID2 = 0xEF;
CANID3 = 0x8E;
CANDATA0 = 0xF3;
CANDATA0 = 0xC7;
CANDATA0 = 0x00;
CANDATA0 = 0xAF;
CANDATA0 = 0x1D;
CANDATALENGTH = 0x05;

So the received data is partly correct - why?

The CAN Initialisation is done by the following function:

=========================================================
void CANInit(void){

CAN0CTL0 |= INITRQ; // set INITRQ, this will also set INITAK
while (!(CAN0CTL1 & INITAK)); // wait for init mode to occur

CAN0CTL1 = 0xA0;

CAN0BTR0=0x28; // BRPR = 40, Sync = 1
CAN0BTR1=0x32; // TSEG1 = 3, TSEG2 = 4

CAN0IDAR0=0xFF;
CAN0IDAR1=0xFF;
CAN0IDAR2=0xFF;
CAN0IDAR3=0xFF;
CAN0IDAR4=0xFF;
CAN0IDAR5=0xFF;
CAN0IDAR6=0xFF;
CAN0IDAR7=0xFF;

CAN0IDMR0=0xFF;
CAN0IDMR1=0xFF;
CAN0IDMR2=0xFF;
CAN0IDMR3=0xFF;
CAN0IDMR4=0xFF;
CAN0IDMR5=0xFF;
CAN0IDMR6=0xFF;
CAN0IDMR7=0xFF;

CAN0IDAC = 0;
CAN0CTL0 &= ~INITRQ; // clear INITRQ
while (CAN0CTL1 & INITAK);

CAN0RFLG = 0xFF;
CAN0CTL1 = 0xA0;

CAN0RIER = 1;
}
=======================================================

I had to redirect the interrupt vectors because of the monitor
program:

=======================================================

void interruptRedirect(void){

// CAN 0 Recieve Interrupt
///////////////////////////
*((unsigned char *)0x3F8E) = 0x06;
*((void (**)(void))0x3F8F) = CAN_Recieve;

// CAN 0 Transmit Interrupt
//////////////////////////
*((unsigned char *)0x3F8B) = 0x06;
*((void (**)(void))0x3F8C) = CAN_Transmit;

// CAN 0 Error Interrupt
//////////////////////////
*((unsigned char *)0x3F91) = 0x06;
*((void (**)(void))0x3F92) = CAN_Error;
}

=================================================
The ISR for CAN receive looks like this:
=================================================

#pragma interrupt_handler CAN_Recieve
void CAN_Recieve(void){

int i=0, x=0;

// Find Empty MessageBuffer
///////////////////////////
while(CANMess[i].messact != 0) i++;
if (i > MAXCANMESSAGES){
if(DEBUGPRINT) printf("CAN Trancieve Error: No Free Buffer to store
Message !");
CAN0RFLG |=1; // clear rec flag
return;
}

// Set status of Message to Recieve Message
///////////////////////////////////////////
CANMess[i].messact = 1;

// Check for Number of Bytes in CAN Message
///////////////////////////////////////////
CANMess[i].length = CAN0RXDLR & 0x0F;

// Copy ID to Messagebuffer
///////////////////////////
CANMess[i].id0 = CAN0RXIDR0;
CANMess[i].id1 = CAN0RXIDR1;
CANMess[i].id2 = CAN0RXIDR2;
CANMess[i].id3 = CAN0RXIDR3;

// Copy Data to Messagebuffer
/////////////////////////////
for (x=0;x<CANMess[i].length;x++)
CANMess[i].data[x] = *(CAN0RXDATA+x);

CAN0RFLG |=1; // clear rec flag
}

====================================================
And this is the main function:
====================================================
void main(void){

int i=0, j=0;
unsigned char ch;
unsigned char temp[5];

for(i=0;i<MAXCANMESSAGES;i++) CANMess[i].messact=0;

interruptRedirect(); // Redirect Interrupts
CANInit(); // Init MSCAN

asm("cli"); // Enable global Interrupts

temp[0] = 1;
temp[1] = 2;
temp[2] = 3;
temp[3] = 4;
temp[4] = 5;

SendCANMessage(5,temp);
while(1){
// Checking Messagebuffer for Entrys
////////////////////////////////////
for(i=0;i<MAXCANMESSAGES;i++){
if(CANMess[i].messact == 1){
CANMess[i].messact = 0;

SendCANMessage(5,temp);
}
}
}
}

==============================================
The SendCANMessage looks like this:
==============================================
void SendCANMessage(unsigned char NumBytes, unsigned char *BufPntr){

unsigned char NACAN,C;
while(!CAN0TFLG); // wait for available buffer
NACAN0TFLG; // get the next available CAN buffer
CAN0TBSEL=NACAN;

CAN0TXIDR0 = 0x2D;
CAN0TXIDR1 = 0xF0;
CAN0TXIDR2 = 0x00;
CAN0TXIDR3 = 0x00;

if (NumBytes>8) NumBytes=8;
for (C=0;C<NumBytes;C++)
*(CAN0TXDATA+C)=*BufPntr++; // store the data

CAN0TXDLR=NumBytes; // set number of bytes to send
NACAN0TBSEL;
CAN0TFLG =NACAN; // transmit
}

===========================================================

I have tested the the program an 2 different MC9S12 but the result is
the same - the tranmsitted message is not equal to the received. Have
i missed something?

Thanks in advance.
Greets Daniel

PS: I must apologize for my bad english.