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.

TMS320F28035: Can Bus Example code

Part Number: TMS320F28035
Other Parts Discussed in Thread: C2000WARE

Hello is there any interrupt based CAN Example code for 28035?

Thanks,

Sagar Shah

  • //###########################################################################
    //
    // FILE:   can_external_transmit.c
    //
    // TITLE:  Example to demonstrate CAN external transmission
    //
    //! \addtogroup cpu01_example_list
    //! <h1>CAN-A to CAN-B External Transmit (can_external_transmit)</h1>
    //!
    //! This example initializes CAN module A and CAN module B for external
    //! communication. CAN-A module is setup to transmit incrementing data for "n"
    //! number of times to the CAN-B module, where "n" is the value of TXCOUNT.
    //! CAN-B module is setup to trigger an interrupt service routine (ISR) when
    //! data is received. An error flag will be set if the transmitted data doesn't
    //! match the received data.
    //!
    //! \note Both CAN modules on the device need to be
    //!       connected to each other via CAN transceivers.
    //!
    //! \b External \b Connections \n
    //!  - CANA is on GPIO31 (CANTXA) and GPIO30 (CANRXA)
    //!  - CANB is on GPIO8 (CANTXB) and GPIO10 (CANRXB)
    //!
    //! \b Watch \b Variables \n
    //!  - TXCOUNT - Adjust to set the number of messages to be transmitted
    //!  - txMsgCount - A counter for the number of messages sent
    //!  - rxMsgCount - A counter for the number of messages received
    //!  - txMsgData - An array with the data being sent
    //!  - rxMsgData - An array with the data that was received
    //!  - errorFlag - A flag that indicates an error has occurred
    //!
    //
    //###########################################################################
    // $TI Release: F2837xD Support Library v200 $
    // $Release Date: Tue Jun 21 13:00:02 CDT 2016 $
    // $Copyright: Copyright (C) 2013-2016 Texas Instruments Incorporated -
    //             http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "F28x_Project.h"     // Device Headerfile and Examples Include File
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_can.h"
    #include "driverlib/can.h"
    
    //
    // Defines
    //
    #define TXCOUNT  100
    #define MSG_DATA_LENGTH    4
    #define TX_MSG_OBJ_ID    1
    #define RX_MSG_OBJ_ID    1
    
    //
    // Globals
    //
    volatile unsigned long i;
    volatile uint32_t txMsgCount = 0;
    volatile uint32_t rxMsgCount = 0;
    volatile uint32_t errorFlag = 0;
    unsigned char txMsgData[4];
    unsigned char rxMsgData[4];
    tCANMsgObject sTXCANMessage;
    tCANMsgObject sRXCANMessage;
    
    //
    // Function Prototypes
    //
    __interrupt void canbISR(void);
    
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize System Control:
        // PLL, WatchDog, enable Peripheral Clocks
        //
        InitSysCtrl();
    
        //
        // Initialize GPIO and configure GPIO pins for CANTX/CANRX
        // on module A and B
        //
        InitGpio();
    
        //
        // Setup GPIO pin mux for CAN-A TX/RX and CAN-B TX/RX
        //
        GPIO_SetupPinMux(30, GPIO_MUX_CPU1, 1); //GPIO30 -  CANRXA
        GPIO_SetupPinOptions(30, GPIO_INPUT, GPIO_ASYNC);
        GPIO_SetupPinMux(31, GPIO_MUX_CPU1, 1); //GPIO31 - CANTXA
        GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSHPULL);
        GPIO_SetupPinMux(10, GPIO_MUX_CPU1, 2); //GPIO10 -  CANRXB
        GPIO_SetupPinOptions(10, GPIO_INPUT, GPIO_ASYNC);
        GPIO_SetupPinMux(8, GPIO_MUX_CPU1, 2);  //GPIO8 - CANTXB
        GPIO_SetupPinOptions(8, GPIO_OUTPUT, GPIO_PUSHPULL);
    
        //
        // Initialize the CAN controllers
        //
        CANInit(CANA_BASE);
        CANInit(CANB_BASE);
    
        //
        // Setup CAN to be clocked off the PLL output clock
        //
        CANClkSourceSelect(CANA_BASE, 0);   // 500kHz CAN-Clock
        CANClkSourceSelect(CANB_BASE, 0);   // 500kHz CAN-Clock
    
        //
        // Set up the CAN bus bit rate to 500kHz for each module
        // This function sets up the CAN bus timing for a nominal configuration.
        // You can achieve more control over the CAN bus timing by using the
        // function CANBitTimingSet() instead of this one, if needed.
        // Additionally, consult the device data sheet for more information about
        // the CAN module clocking.
        //
        CANBitRateSet(CANA_BASE, 200000000, 500000);
        CANBitRateSet(CANB_BASE, 200000000, 500000);
    
        //
        // Enable interrupts on the CAN B peripheral.
        //
        CANIntEnable(CANB_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    
        //
        // 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.
        //
        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.
        //
        InitPieVectTable();
    
        //
        // Interrupts that are used in this example are re-mapped to
        // ISR functions found within this file.
        // This registers the interrupt handler in PIE vector table.
        //
        EALLOW;
        PieVectTable.CANB0_INT = canbISR;
        EDIS;
    
        //
        // Enable the CAN-B interrupt on the processor (PIE).
        //
        PieCtrlRegs.PIEIER9.bit.INTx7 = 1;
        IER |= M_INT9;
        EINT;
    
        //
        // Enable the CAN-B interrupt signal
        //
        CANGlobalIntEnable(CANB_BASE, CAN_GLB_INT_CANINT0);
    
        //
        // Initialize the transmit message object used for sending CAN messages.
        // Message Object Parameters:
        //      Message Identifier: 0x5555
        //      Message ID Mask: 0x0
        //      Message Object Flags: None
        //      Message Data Length: 4 Bytes
        //      Message Transmit data: txMsgData
        //
        sTXCANMessage.ui32MsgID = 0x5555;
        sTXCANMessage.ui32MsgIDMask = 0;
        sTXCANMessage.ui32Flags = 0;
        sTXCANMessage.ui32MsgLen = MSG_DATA_LENGTH;
        sTXCANMessage.pucMsgData = txMsgData;
    
        //
        // Initialize the receive message object used for receiving CAN messages.
        // Message Object Parameters:
        //      Message Identifier: 0x5555
        //      Message ID Mask: 0x0
        //      Message Object Flags: Receive Interrupt
        //      Message Data Length: 4 Bytes
        //      Message Receive data: rxMsgData
        //
        sRXCANMessage.ui32MsgID = 0x5555;
        sRXCANMessage.ui32MsgIDMask = 0;
        sRXCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE;
        sRXCANMessage.ui32MsgLen = MSG_DATA_LENGTH;
        sRXCANMessage.pucMsgData = rxMsgData;
        CANMessageSet(CANB_BASE, RX_MSG_OBJ_ID, &sRXCANMessage,
                      MSG_OBJ_TYPE_RX);
    
        //
        // Initialize the transmit message object data buffer to be sent
        //
        txMsgData[0] = 0x12;
        txMsgData[1] = 0x34;
        txMsgData[2] = 0x56;
        txMsgData[3] = 0x78;
    
        //
        // Start CAN module A and B operations
        //
        CANEnable(CANA_BASE);
        CANEnable(CANB_BASE);
    
        //
        // Transmit messages from CAN-A to CAN-B
        //
        for(i = 0; i < TXCOUNT; i++)
        {
            //
            // Check the error flag to see if errors occurred
            //
            if(errorFlag)
            {
                asm("   ESTOP0");
            }
    
            //
            // Verify that the number of transmitted messages equal the number of
            // messages received before sending a new message
            //
            if(txMsgCount == rxMsgCount)
            {
                //
                // Transmit Message
                //
                CANMessageSet(CANA_BASE, TX_MSG_OBJ_ID, &sTXCANMessage,
                              MSG_OBJ_TYPE_TX);
    
                txMsgCount++;
            }
            else
            {
                errorFlag = 1;
            }
    
            //
            // Delay 0.25 second before continuing
            //
            DELAY_US(1000 * 250);
    
            //
            // Increment the value in the transmitted message data.
            //
            txMsgData[0] += 0x01;
            txMsgData[1] += 0x01;
            txMsgData[2] += 0x01;
            txMsgData[3] += 0x01;
        }
    
        //
        // Stop application
        //
        asm("   ESTOP0");
    }
    
    //
    // CAN B ISR - The interrupt service routine called when a CAN interrupt is
    //             triggered on CAN module B.
    //
    __interrupt void
    canbISR(void)
    {
        uint32_t status;
    
        //
        // Read the CAN-B interrupt status to find the cause of the interrupt
        //
        status = CANIntStatus(CANB_BASE, CAN_INT_STS_CAUSE);
    
        //
        // If the cause is a controller status interrupt, then get the status
        //
        if(status == CAN_INT_INT0ID_STATUS)
        {
            //
            // Read the controller status.  This will return a field of status
            // error bits that can indicate various errors.  Error processing
            // is not done in this example for simplicity.  Refer to the
            // API documentation for details about the error status bits.
            // The act of reading this status will clear the interrupt.
            //
            status = CANStatusGet(CANB_BASE, CAN_STS_CONTROL);
    
            //
            // Check to see if an error occurred.
            //
            if(((status  & ~(CAN_ES_RXOK)) != 7) &&
               ((status  & ~(CAN_ES_RXOK)) != 0))
            {
                //
                // Set a flag to indicate some errors may have occurred.
                //
                errorFlag = 1;
            }
        }
        //
        // Check if the cause is the CAN-B receive message object 1
        //
        else if(status == RX_MSG_OBJ_ID)
        {
            //
            // Get the received message
            //
            CANMessageGet(CANB_BASE, RX_MSG_OBJ_ID, &sRXCANMessage, true);
    
            //
            // Getting to this point means that the RX interrupt occurred on
            // message object 1, and the message RX is complete.  Clear the
            // message object interrupt.
            //
            CANIntClear(CANB_BASE, RX_MSG_OBJ_ID);
    
            //
            // Increment a counter to keep track of how many messages have been
            // received. In a real application this could be used to set flags to
            // indicate when a message is received.
            //
            rxMsgCount++;
    
            //
            // Since the message was received, clear any error flags.
            //
            errorFlag = 0;
        }
        //
        // If something unexpected caused the interrupt, this would handle it.
        //
        else
        {
            //
            // Spurious interrupt handling can go here.
            //
        }
    
        //
        // Clear the global interrupt flag for the CAN interrupt line
        //
        CANGlobalIntClear(CANB_BASE, CAN_GLB_INT_CANINT0);
    
        //
        // Acknowledge this interrupt located in group 9
        //
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
    }
    
    //
    // End of File
    //
    

  • 1)So in the Code for 28739D there is example code with all the driver API. Is there any way I could find an example for 28379D without the driver API for external transmit and external receive.

    2)Also, GPIO 12 (txb) and GPIO 17 (rxb) are shown in the schematic of the launchpad of 28379D while if I look into header file of can.h its different GPIO combination.

    3) IS there any sample basic code with TI for28379D without any API? Thanks.

    //
    // FILE: can.h
    //
    // TITLE: Defines and Macros for the CAN controller.
    //
    //###########################################################################
    // $TI Release: F2837xD Support Library v200 $
    // $Release Date: Tue Jun 21 13:00:02 CDT 2016 $
    // $Copyright: Copyright (C) 2013-2016 Texas Instruments Incorporated -
    // http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################

    #ifndef __CAN_H__
    #define __CAN_H__

    //*****************************************************************************
    //! \addtogroup can_api
    //! @{
    //*****************************************************************************

    //*****************************************************************************
    // If building with a C++ compiler, make all of the definitions in this header
    // have a C binding.
    //*****************************************************************************
    #ifdef __cplusplus
    extern "C"
    {
    #endif


    #define CAN_INDEX_TO_BASE(idx) ((idx == 0) ? CAN_A_BASE : CAN_B_BASE)

    #define CAN_INDEX_TO_MSG_RAM_BASE(idx) ((idx == 0) ? CAN_A_MSG_RAM : CAN_B_MSG_RAM)

    #define CAN_REG_WORD_MASK (0xFFFFU)

    //****************************************************************************
    // These are the Defines to select CAN pin muxing when calling the functions
    // ConfigCanPinMuxing(), ConfigGpioCanA() & ConfigGpioCanB() in F2837x_Can.c
    //****************************************************************************
    #define CAN_A_GPIO4_GPIO5 1 //switch case 1
    #define CAN_A_GPIO19_GPIO18 2 //switch case 2
    #define CAN_A_GPIO31_GPIO30 3 //switch case 3
    #define CAN_A_GPIO37_GPIO36 4 //switch case 4
    #define CAN_A_GPIO63_GPIO62 5 //switch case 5
    #define CAN_A_GPIO71_GPIO70 6 //switch case 6

    #define CAN_B_GPIO6_GPIO7 1 //switch case 1
    #define CAN_B_GPIO8_GPIO10 2 //switch case 2
    #define CAN_B_GPIO12_GPIO13 3 //switch case 3
    #define CAN_B_GPIO16_GPIO17 4 //switch case 4
    #define CAN_B_GPIO20_GPIO21 5 //switch case 5
    #define CAN_B_GPIO38_GPIO39 6 //switch case 6
    #define CAN_B_GPIO72_GPIO73 7 //switch case 7
  • My Test task I want to do is use onboard CAN hi and CAN LO connected to GPio 12 and GPio 17 and communicate using two launchpads as two different nodes.
  • ALSO, I could not find a header file of Ecan.h for 28379D like 28035 device. I understand the document you have shared has information but its different for 28379D. So could you help locate me?
  • 1)So in the Code for 28739D there is example code with all the driver API. Is there any way I could find an example for 28379D without the driver API for external transmit and external receive.

    No. We only have Driverlib examples.

    2)Also, GPIO 12 (txb) and GPIO 17 (rxb) are shown in the schematic of the launchpad of 28379D while if I look into header file of can.h its different GPIO combination.

    You can change the GPIOs to any pin you desire.

    3) IS there any sample basic code with TI for28379D without any API? Thanks.

    No.

    My Test task I want to do is use onboard CAN hi and CAN LO connected to GPio 12 and GPio 17 and communicate using two launchpads as two different nodes.

    OK. That is fairly straightforward and doable.

    ALSO, I could not find a header file of Ecan.h for 28379D like 28035 device. I understand the document you have shared has information but its different for 28379D. So could you help locate me?

    The CAN module is completely different between these devices. The TI-provided support files follow a different programming approach for these devices, so you won't find such "common" files.
  • So you mean to say that 2803x and 28379D have a different approach for the Can peripheral.  I was able to communicate between two launchpads but I am wondering if I can do without the driver. The document you have shared TMS320x28xx eCAN applies to 280379 as well right?

    Like the code snippet as below for 2803x is there a way for 28379D-

    ECanbShadow.CANTRS.all = 0;
    ECanbShadow.CANTRS.bit.TRS25 = 1; // Set TRS for mailbox under test
    ECanbRegs.CANTRS.all = ECanbShadow.CANTRS.all;

    ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;
    do {ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;} // Wait for TA25 bit to be set..
    while(ECanbShadow.CANTA.bit.TA25 == 0 );

    ECanbShadow.CANTA.all = 0;
    ECanbShadow.CANTA.bit.TA25 = 1; // Clear TA5
    ECanbRegs.CANTA.all = ECanbShadow.CANTA.all;

  • So you mean to say that 2803x and 28379D have a different approach for the Can peripheral.

    Yes, the modules do conform to the CAN protocol, but the implementation is completely different between the devices.

    I was able to communicate between two launchpads but I am wondering if I can do without the driver.

    Whether or not to use a driver like the C2000ware API is completely up to you. If you decide not to use it, you need to come up with your own way of writing to the registers/bits.

    The document you have shared TMS320x28xx eCAN applies to 280379 as well right?

    No, it is applicable only for the 28xx devices with eCAN.

    Like the code snippet as below for 2803x is there a way for 28379D

    You *can* do 32-bit R/W with HWREG()
  • So if I have 16 Mailbox set as transmit and 16 MAilbox as Receive.   

    1) If I want to transmit 16 mailboxes do I have to send the below command 16 times (with different mailbox param?

    CANMessageSet(CANB_BASE, 2, &sTXCANMessage, MSG_OBJ_TYPE_TX);

    2) Also when I transmitting from node A and the other Can bus node B sends a mailbox with lower msg id(higher priority), will the protocol in the driver will manage to transmit it again after collision? or do I need to use CANMessageSet to transmit again?

    3) For polling based code what register should I check to see if I have received a Message?

    Thanks.

  • 1) If I want to transmit 16 mailboxes do I have to send the below command 16 times (with different mailbox param)?
    CANMessageSet(CANB_BASE, 2, &sTXCANMessage, MSG_OBJ_TYPE_TX);

    Yes, every transmission must be initiated the same way. Transferring the contents using IFx registers and requesting the transfer. I urge you to download the most recent version of c2000ware (C2000Ware_1_00_06_00 )and take a look at the examples.

    2) Also when I transmitting from node A and the other Can bus node B sends a mailbox with lower msg id(higher priority), will the protocol in the driver will manage to transmit it again after collision? or do I need to use CANMessageSet to transmit again?

    This will be done automatically by the CAN module as this feature is protocol related. This has nothing to do with the drivers.

    3) For polling based code what register should I check to see if I have received a Message?

    NewDat. Please refer to the TRM for details.