This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28075: can't receive data from CANBUS

Part Number: TMS320F28075
Other Parts Discussed in Thread: ISO1050

Hi, I'm testing the CAN module with can analyzer. F28075+ ISO1050 to a CAN analyzer.

I can send the data to CAN analyzer with the code below, but no able to receive data from the can analyzer. (CanaRegs.CAN_IF2MCTL.bit.NewDat will never be set to 1 when CAN analyzer is sending data to F28075).

Could you please help to see what's wrong with my code?

The code was based on the example code can_loopback_bitfields.c

//

// FILE:   can_loopback_bitfields.c

//

// TITLE:  Example to demonstrate basic CAN setup and use.

//

//! \addtogroup cpu01_example_list

//! <h1>CAN External Loopback Using Bitfields (can_loopback_bitfields)</h1>

//!

//! IMPORTANT: CAN Bitfield headers require compiler v16.6.0.STS and newer!

//!

//! This example, using bitfield headers, shows the basic setup of CAN in

//! order to transmit and receive messages on the CAN bus.  The CAN

//! peripheral is configured to transmit messages with a specific CAN ID.

//! A message is then transmitted once per second, using a simple delay

//! loop for timing.  The message that is sent is a 4 byte message that

//! contains an incrementing pattern.

//! This example sets up the CAN controller in External Loopback test mode.

//! Data transmitted is visible on the CAN0TX pin and can be received with

//! an appropriate mailbox configuration.

//!

//

//###########################################################################

// $TI Release: F2807x Support Library v210 $

// $Release Date: Tue Nov  1 15:42:43 CDT 2016 $

// $Copyright: Copyright (C) 2014-2016 Texas Instruments Incorporated -

//             http://www.ti.com/ ALL RIGHTS RESERVED $

//###########################################################################

 

//

// Included Files

//

#include "F28x_Project.h"

 

//

// Defines

//

#define CAN_MSG_ID              0x1111

#define CAN_TX_MSG_OBJ          1

#define CAN_RX_MSG_OBJ          2       //      这里是定义1号邮箱是发送,2号邮箱是接收。

#define CAN_MAX_BIT_DIVISOR     (13)   // The maximum CAN bit timing divisor

#define CAN_MIN_BIT_DIVISOR     (5)    // The minimum CAN bit timing divisor

#define CAN_MAX_PRE_DIVISOR     (1024) // The maximum CAN pre-divisor

#define CAN_MIN_PRE_DIVISOR     (1)    // The minimum CAN pre-divisor

#define CAN_BTR_BRP_M           (0x3F)

#define CAN_BTR_BRPE_M          (0xF0000)

 

 

//

// Globals

//

uint32_t rec1;

unsigned char ucTXMsgData[4] = {0x1, 0x2, 0x3, 0x4}; // TX Data

unsigned char ucRXMsgData[4] = {0x5, 0x6, 0x7, 0x8};         // RX Data

uint32_t messageSize = sizeof(ucTXMsgData);          // Message Size (DLC)

volatile unsigned long msgCount = 0; // A counter that keeps track of the

                                     // number of times the transmit was

                                     // successful.

volatile unsigned long errFlag = 0;  // A flag to indicate that some

                                     // transmission error occurred.

 

static const uint16_t canBitValues[] =                      //  设置比特率的时候会用到;

{

    0x1100, // TSEG2 2, TSEG1 2, SJW 1, Divide 5

    0x1200, // TSEG2 2, TSEG1 3, SJW 1, Divide 6

    0x2240, // TSEG2 3, TSEG1 3, SJW 2, Divide 7

    0x2340, // TSEG2 3, TSEG1 4, SJW 2, Divide 8

    0x3340, // TSEG2 4, TSEG1 4, SJW 2, Divide 9

    0x3440, // TSEG2 4, TSEG1 5, SJW 2, Divide 10

    0x3540, // TSEG2 4, TSEG1 6, SJW 2, Divide 11

    0x3640, // TSEG2 4, TSEG1 7, SJW 2, Divide 12

    0x3740  // TSEG2 4, TSEG1 8, SJW 2, Divide 13

};

 

typedef enum

{

        //! Transmit message object.

        MSG_OBJ_TYPE_TRANSMIT,

 

        //! Receive message object.

        MSG_OBJ_TYPE_RECEIVE

}

msgObjType;

 

//

// Function Prototypes

//

uint32_t setCANBitRate(uint32_t sourceClock, uint32_t bitRate);    //   设置比特率;

void  setupMessageObject(uint32_t objID, uint32_t msgID, msgObjType msgType);  //   设置消息对象;

void sendCANMessage(uint32_t objID);    //  发送can信息;

bool getCANMessage(uint32_t objID);     //  接收can信息;

 

//

// Main

//

int

main(void)

{

    //

    // Initialize System Control:

    // PLL, WatchDog, enable Peripheral Clocks      //  初始化系统时钟,pll,外设时钟等

    // This example function is found in the F2807x_SysCtrl.c file.

    //

    InitSysCtrl();    //    系统初始化里就已经讲外设时钟初始化了。

 

    //

    // Initialize GPIO:

    // This example function is found in the F2807x_Gpio.c file and

    // illustrates how to set the GPIO to its default state.

    //

    InitGpio();

    GPIO_SetupPinMux(62, GPIO_MUX_CPU1, 6);  //GPIO30 - CANRXA          //  这几个函数都是在gpio.c里定义的;

    GPIO_SetupPinMux(63, GPIO_MUX_CPU1, 6);  //GPIO31 - CANTXA

    GPIO_SetupPinOptions(62, GPIO_INPUT, GPIO_ASYNC);

    GPIO_SetupPinOptions(63, GPIO_OUTPUT, GPIO_PUSHPULL);

 

    //

    // Initialize the CAN-A controller

    //

    InitCAN();

 

    //

    // Setup CAN to be clocked off the SYSCLKOUT

    //

    ClkCfgRegs.CLKSRCCTL2.bit.CANABCLKSEL = 0;      //  can clock为系统时钟;

 

    //

    // Set up the bit rate for the CAN bus.  This function sets up the CAN

    // bus timing for a nominal configuration.

    // In this example, the CAN bus is set to 500 kHz.

    //

    // Consult the data sheet for more information about

    // CAN peripheral clocking.

    //

    uint32_t status = setCANBitRate(120000000, 500000);   //   这里设置的sourceclock是200M,比特率是500k

 

    //

    // If values requested are too small or too large, catch error

    //

    if(status == 0)

    {

        errFlag++;

        ESTOP0;         // Stop here and handle error

    }

 

    //

    // Step 3. Clear all interrupts and initialize PIE vector table:

    // Disable CPU interrupts

    //

    DINT;   //  禁止中断;

 

    //

    // Initialize the PIE control registers to their default state.

    // The default state is all PIE interrupts disabled and flags

    // are cleared.

    // This function is found in the F2807x_PieCtrl.c file.

    //

    InitPieCtrl();

 

    //

    // Disable CPU interrupts and clear all CPU interrupt flags:

    //

    IER = 0x0000;

    IFR = 0x0000;

 

    //

    // Initialize the PIE vector table with pointers to the shell Interrupt

    // Service Routines (ISR).

    // This will populate the entire table, even if the interrupt

    // is not used in this example.  This is useful for debug purposes.

    // The shell ISR routines are found in F2807x_DefaultIsr.c.

    // This function is found in F2807x_PieVect.c.

    //

    InitPieVectTable();

 

    //

    // Enable test mode and select external loopback. 

    //

    /*CanaRegs.CAN_CTL.bit.Test = 1;     //  Test mode disabled by commenting out these two sentences.

    CanaRegs.CAN_TEST.bit.EXL = 1;  // EXL 外部循环使能位;*/

   /* CanaRegs.CAN_CTL.bit.Test = 0;      //  该位为0后,测试寄存器里面的功能就全部取消;*/

 

    //

    // Initialize the message object that will be used for sending CAN  //初始化将用于发送CAN的消息对象;

    // messages.  //这个实际是上是配置邮箱

    //

    setupMessageObject(CAN_TX_MSG_OBJ, CAN_MSG_ID, MSG_OBJ_TYPE_TRANSMIT);

 

    //

    // Initialize the message object that will be used for receiving CAN

    // messages.

    //

    setupMessageObject(CAN_RX_MSG_OBJ, CAN_MSG_ID, MSG_OBJ_TYPE_RECEIVE);  

 

    //

    // Enable the CAN for operation.

    //

    CanaRegs.CAN_CTL.bit.Init = 0;

 

    //

    // Enter loop to send messages.  A new message will be sent once per

    // second.  The 4 bytes of message content will be treated as an unsigned

    // long and incremented by one each time.

    //

    for(;;)

    {

        //

        // Send the CAN message using object number 1 (not the same thing as

        // CAN ID, which is also 1 in this example).  This function will cause

        // the message to be transmitted right away.     //  发送信息1,

        //

       /* sendCANMessage(CAN_TX_MSG_OBJ);   //  CAN_TX_MSG_OBJ  ID=1*/

 

        //

        // Now wait 1 second before continuing

        //

        DELAY_US(1000*1000);

 

        //

        // Get the receive message

        //

        getCANMessage(CAN_RX_MSG_OBJ);

        //

        // Ensure the received data matches the transmitted data

        //

   /*     if((*(unsigned long *)ucTXMsgData) != (*(unsigned long *)ucRXMsgData))

        {

            errFlag++;

            asm(" ESTOP0");

        }*/

 

        //

        // Increment successful message count and the value in the

        // transmitted message data.

        //

        msgCount++;

      /*  (*(unsigned long *)ucTXMsgData)++;*/

    }

}

 

//

// setCANBitRate - Set the CAN bit rate based on device clock (Hz)

//                 and desired bit rate (Hz)

//

uint32_t setCANBitRate(uint32_t sourceClock, uint32_t bitRate)

{

    uint32_t desiredRatio;

    uint32_t canBits;

    uint32_t preDivide;

    uint32_t regValue;

    uint16_t canControlValue;

 

    //

    // Calculate the desired clock rate.

    //

    desiredRatio = sourceClock / bitRate;

 

    //

    // Make sure that the Desired Ratio is not too large.  This enforces the

    // requirement that the bit rate is larger than requested.

    //

    if((sourceClock / desiredRatio) > bitRate)

    {

        desiredRatio += 1;

    }

 

    //

    // Check all possible values to find a matching value.

    //

    while(desiredRatio <= CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR)

    {

        //

        // Loop through all possible CAN bit divisors.

        //

        for(canBits = CAN_MAX_BIT_DIVISOR;

            canBits >= CAN_MIN_BIT_DIVISOR;

            canBits--)

        {

            //

            // For a given CAN bit divisor save the pre divisor.

            //

            preDivide = desiredRatio / canBits;

 

            //

            // If the calculated divisors match the desired clock ratio then

            // return these bit rate and set the CAN bit timing.

            //

            if((preDivide * canBits) == desiredRatio)

            {

                //

                // Start building the bit timing value by adding the bit timing

                // in time quanta.

                //

                regValue = canBitValues[canBits - CAN_MIN_BIT_DIVISOR];

 

                //

                // To set the bit timing register, the controller must be

                // placed

                // in init mode (if not already), and also configuration change

                // bit enabled.  The state of the register should be saved

                // so it can be restored.

                //

                canControlValue = CanaRegs.CAN_CTL.all;

                CanaRegs.CAN_CTL.bit.Init = 1;

                CanaRegs.CAN_CTL.bit.CCE = 1;

 

                //

                // Now add in the pre-scalar on the bit rate.

                //

                regValue |= ((preDivide - 1) & CAN_BTR_BRP_M) |

                            (((preDivide - 1) << 10) & CAN_BTR_BRPE_M);

 

                //

                // Set the clock bits in the and the bits of the

                // pre-scalar.

                //

                CanaRegs.CAN_BTR.all = regValue;

 

                //

                // Restore the saved CAN Control register.

                //

                CanaRegs.CAN_CTL.all = canControlValue;

 

                //

                // Return the computed bit rate.

                //

                return(sourceClock / ( preDivide * canBits));

            }

        }

 

        //

        // Move the divisor up one and look again.  Only in rare cases are

        // more than 2 loops required to find the value.

        //

        desiredRatio++;

    }

    return 0;

}

 

//

// setupMessageObject - Setup message object as Transmit or Receive  

//

void setupMessageObject(uint32_t objID, uint32_t msgID, msgObjType msgType)

{

    //

    // Wait for busy bit to clear.

    //

    while(CanaRegs.CAN_IF1CMD.bit.Busy)

    {

    }

 

    //

    // Clear and Write out the registers to program the message object.  

    //

    CanaRegs.CAN_IF1CMD.all = 0;        

    CanaRegs.CAN_IF1MSK.all = 0;        

    CanaRegs.CAN_IF1ARB.all = 0;       

    CanaRegs.CAN_IF1MCTL.all = 0;        

 

    //

    // Set the Control, Mask, and Arb bit so that they get transferred to the

    // Message object.

    //

    CanaRegs.CAN_IF1CMD.bit.Control = 1;        

    CanaRegs.CAN_IF1CMD.bit.Arb = 1;            

    CanaRegs.CAN_IF1CMD.bit.Mask = 1;           

    CanaRegs.CAN_IF1CMD.bit.DIR = 1;        

 

    //

    // Set direction to transmit            //  

    //

    if(msgType == MSG_OBJ_TYPE_TRANSMIT)

    {

        CanaRegs.CAN_IF1ARB.bit.Dir = 1;        //  

    }

 

    //

    // Set Message ID (this example assumes 11 bit ID mask)     //     

    //

    CanaRegs.CAN_IF1ARB.bit.ID = msgID;             //  

    CanaRegs.CAN_IF1ARB.bit.MsgVal = 1;   //    

 

    //

    // Set the data length since this is set for all transfers.  This is

    // also a single transfer and not a FIFO transfer so set EOB bit.

    //

    CanaRegs.CAN_IF1MCTL.bit.DLC = messageSize;     // 

    CanaRegs.CAN_IF1MCTL.bit.EoB = 1;       // 

 

    //

    // Transfer data to message object RAM      //  将data传到消息RAM;

    //

    CanaRegs.CAN_IF1CMD.bit.MSG_NUM = objID;        //

}

 

//

// sendCANMessage - Transmit data from the specified message object  //传输数据;

//

void sendCANMessage(uint32_t objID)

{

    //

    // Wait for busy bit to clear.

    //

    while(CanaRegs.CAN_IF1CMD.bit.Busy)

    {

    }

 

    //

    // Write data to transfer into DATA-A and DATA-B interface registers

    //

 

    uint16_t index;

    for(index = 0; index < messageSize; index++)

    {

        switch(index)

        {

            case 0:

                CanaRegs.CAN_IF1DATA.bit.Data_0 = ucTXMsgData[index];   //  

                break;

            case 1:

                CanaRegs.CAN_IF1DATA.bit.Data_1 = ucTXMsgData[index];

                break;

            case 2:

                CanaRegs.CAN_IF1DATA.bit.Data_2 = ucTXMsgData[index];

                break;

            case 3:

                CanaRegs.CAN_IF1DATA.bit.Data_3 = ucTXMsgData[index];

                break;

            case 4:

                CanaRegs.CAN_IF1DATB.bit.Data_4 = ucTXMsgData[index];

                break;

            case 5:

                CanaRegs.CAN_IF1DATB.bit.Data_5 = ucTXMsgData[index];

                break;

            case 6:

                CanaRegs.CAN_IF1DATB.bit.Data_6 = ucTXMsgData[index];

                break;

            case 7:

                CanaRegs.CAN_IF1DATB.bit.Data_7 = ucTXMsgData[index];

                break;

        }

    }

 

    //

    // Set Direction to write and set DATA-A/DATA-B to be transfered to

    // message object

    //

    CanaRegs.CAN_IF1CMD.all = 0x830000;  //     DIR=1;dataA,dataB=1;   

 

    //

    // Set Tx Request Bit

    //

    CanaRegs.CAN_IF1CMD.bit.TXRQST = 1;    

 

    //

    // Transfer the message object to the message object specified by

    // objID.

    //

    CanaRegs.CAN_IF1CMD.bit.MSG_NUM = objID;        ;

}

 

//

// getCANMessage - Check the message object for new data.

//                 If new data, data written into array and return true.

//                 If no new data, return false.

//

 

bool getCANMessage(uint32_t objID)

{

    bool status;

 

    //

    // Set the Message Data A, Data B, and control values to be read

    // on request for data from the message object.

    //

    CanaRegs.CAN_IF2CMD.all = 0;

    CanaRegs.CAN_IF2CMD.bit.Control = 1;        ;

    CanaRegs.CAN_IF2CMD.bit.DATA_A = 1;       

    CanaRegs.CAN_IF2CMD.bit.DATA_B = 1;         

 

    //

    // Transfer the message object to the message object IF register.

    //

    CanaRegs.CAN_IF2CMD.bit.MSG_NUM = objID;

 

    //

    // Wait for busy bit to clear.

    //

    while(CanaRegs.CAN_IF2CMD.bit.Busy)

    {

    }

 

    //

    // See if there is new data available.

    //

    if(CanaRegs.CAN_IF2MCTL.bit.NewDat == 1)        //  有新的消息写入;

    {

        //

        // Read out the data from the CAN registers.

        //

        uint16_t index;

        for(index = 0; index < messageSize; index++)

        {

            switch(index)

            {

                case 0:

                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_0;

                break;

                case 1:

                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_1;

                break;

                case 2:

                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_2;

                break;

                case 3:

                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATA.bit.Data_3;

                break;

                case 4:

                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATB.bit.Data_4;

                break;

                case 5:

                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATB.bit.Data_5;

                break;

                case 6:

                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATB.bit.Data_6;

                break;

                case 7:

                    ucRXMsgData[index] = CanaRegs.CAN_IF2DATB.bit.Data_7;

                break;

            }

        }

 

        //

        // Clear New Data Flag

        //

        CanaRegs.CAN_IF2CMD.bit.TxRqst = 1;         //  clear newDATA bit;

 

 

        // Wait for busy bit to clear.

        //

        while(CanaRegs.CAN_IF2CMD.bit.Busy)

        {

        }

 

        //

        // Transfer the message object to the message object IF register.

        //

        CanaRegs.CAN_IF2CMD.bit.MSG_NUM = objID;

 

        status = true;

    }

    else

    {

        status = false;

    }

 

    return(status);

}


  • The fact that you are able to send data to CAN bus analyzer suggests that there is likely no H/W issue and the bit-rates are identical between nodes. Make sure the MSGID is identical between nodes. (Take a look at the Debug tips in SPRA876 for details). Also try using the RxOK bit in CANES. Note that it would be set for *any* frame on the bus, but at least it is a good indication if a complete frame was monitored.

     

    On a different note, if you insert a code snippet in your post, always paste it using the “Syntax Highlighter” option. That makes the code easier to read.