Laurence McLean

56F8037 CAN TX problems

Discussion created by Laurence McLean on Apr 2, 2012
Latest reply on Apr 19, 2012 by Laurence McLean

Hi there,

 

I am having a bit of trouble with the MSCAN module in the 56F8037. In particular, I am currently trying to get it to transmit data.

I have this sort of working, in that I can transmit data ok at various speeds and recieve it on my PC but I am having trouble with sending more than 3 lots of data and I think it is related to the transmit buffers.

For example, I have set up my controller to just send some static data over the CAN module to test if it was working. This was something like: (I populated all bytes in between - they are just omitted for clarity)

 

outData[0] = 11;  to outData[7] = 18;        // Populate tx data

can_Send_Pkt(outData, toID, fromID);   // Send it off

outData[0] = 21;  to outData[7] = 28;

can_Send_Pkt(outData, toID, fromID);

outData[0] = 31;  to outData[7] = 38;

can_Send_Pkt(outData, toID, fromID);

outData[0] = 41;  to outData[7] = 48;

can_Send_Pkt(outData, toID, fromID);

 

And so on, up to 71,...,78.

All I recieve on the other end of the CAN bus is the data from

11,...,18

21,...,28

31,...,38

 

And it will just keep repeating this. (ie 11, 12, 13, 14, 16, 17, 18)

 

It seems as though I can write to the tx data buffer once, then that is all. The datasheet says that the only way to clear out a tx data buffer is by writing to it. I do think something is screwy in the way I am putting data into the tx Buffers and I also think my selection of TX buffer is a bit suspect, but I cannot put my finger on it.

I wonder if anyone could take a quick look at my code below and see if they can see something I cannot.

The code is based on the Quickstart example and some other stuff I lifted from the depths of the Codewarrior directory.

 

I have included 2 versions of my testing code below. The top one gives the above results. The bottom one just transmits one register. I believe the bottom one is a step in the right direction.

 

 

1st try:

 

 
// ------------------------------------------------ CAN - TX READY ISR -----------------------------------
#pragma interrupt on
void CAN_TxRdy_ISR(void)  
{
 
    
    // what tx buffers are empty?  
    UWord16 tint = ioctl(MSCAN, MSCAN_READ_TINT_FLAGS, NULL);        // AVailable buffers
 
 
    // disable interrupts handled
    ioctl(MSCAN, MSCAN_TINT_DISABLE, tint);
 
}
 
#pragma interrupt off
 
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 
 
 
static void send_CAN_Pkt(UWord16 outMode, UWord16 txCmd, UWord16 outID, UWord16* sndData) {
    static UWord32 outIdCAN;
    static UWord16 txbuff;
    
    // Select the next available TX buffer
    txbuff = ioctl(MSCAN, MSCAN_SELECT_NEXT_TXBUFF, NULL);
 
    if(txbuff) {
        // Pointer to TX buffer
        register UWord16* pdT = ioctl(MSCAN_TB, MSCANMB_GET_DATAPTR, NULL);
 
                
        pdT[0] = sndData[0];
        pdT[1] = sndData[1];
        pdT[2] = sndData[2];
        pdT[3] = sndData[3];
        pdT[4] = sndData[4];
        pdT[5] = sndData[5];
        pdT[6] = sndData[6];
        pdT[7] = sndData[7];
 
        outID = ((ecID << 4) & FROM_MASK) | (outMode << 8);    // (1 << 8) is the Mode part. Change to (Mode << 8)
         
        ioctl(MSCAN_TB, MSCANMB_SET_ID, outID);
        ioctl(MSCAN_TB, MSCANMB_SET_LEN, 8);
 
        // transmit buffer
        ioctl(MSCAN, MSCAN_TRANSMIT, txbuff);  
 
        // enable tx-finished interrupt
        ioctl(MSCAN, MSCAN_TINT_ENABLE, txbuff);         
    }
}

 

 

 

-------------------------

2nd try

 

 

 

 

 

// ------------------------------------------------ CAN - TX READY ISR -----------------------------------
#pragma interrupt on
void CAN_TxRdy_ISR(void)  
{
    register UWord16 txbNum;
    register UWord16 bflag;

    
    UWord16 tEmpty = ioctl(MSCAN, MSCAN_READ_TINT_FLAGS, NULL);        // AVailable buffers
 
    
    for (txbNum=0; txbNum<3; txbNum++) {

        register UWord16* pdT = ioctl(MSCAN_TB, MSCANMG_GET_DATAPTR, NULL);
        bflag = 1 << txbNum;    
 
        if(ioctl(MSCAN, MSCAN_SELECT_TXBUFF, bflag)){  // Is the current buffer empty?
            pdT[0] = outData[0];
            pdT[1] = outData[1];
            pdT[2] = outData[2];            // outData is defined up top as a global var for now.
            pdT[3] = outData[3];
            pdT[4] = outData[4];
            pdT[5] = outData[5];
            pdT[6] = outData[6];
            pdT[7] = outData[7];
            ioctl(MSCAN, MSCAN_TRANSMIT, bflag);
            tEmpty &= ~bflag;        // this buffer is no longer empty
            
        }
 
    
    }
   
    // disable interrupts handled
    ioctl(MSCAN, MSCAN_TINT_DISABLE, tEmpty);
}
 
#pragma interrupt off






 //-------------------------------------
static void send_CAN_Pkt(UWord16 outMode, UWord16 txCmd, UWord16 outID, UWord16* sndData) {
    static UWord32 outIdCAN;
    static UWord16 txbuff;
    
    outData[0] = sndData[0];
    outData[1] = sndData[1];
    outData[2] = sndData[2];
    outData[3] = sndData[3];
    outData[4] = sndData[4];
    outData[5] = sndData[5];
    outData[6] = sndData[6];
    outData[7] = sndData[7];
 
    outID = ((ecID << 4) & FROM_MASK) | (outMode << 8);    // (1 << 8) is the Mode part. Change to (Mode << 8)
      
    ioctl(MSCAN_TB, MSCANMB_SET_ID, outID);
    ioctl(MSCAN_TB, MSCANMB_SET_LEN, 8);            // just 8 bytes at the moment
 
    ioctl(MSCAN, MSCAN_TINT_ENABLE, MSCAN_TXEMPTY_ALL);     // Enable the interrupt
 
}

 

 

 

 

Apologies for the wall of text....

Thanks in advance!

 

Laurence M

Outcomes