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.

CCS/TMS320F28379D: TMS320F28379D

Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE

Tool/software: Code Composer Studio

Hi,

I am trying to connect C2000 launchpad XL TMS320F28379D to elmo driver. 

So I started step by step

I wanted to check how does CAN work 

So I pulled up the external CAN example and as mentioned in the example 

GPIO 30 (CAN A RX) was connected to directly to GPIO 8 (CAN B TX) using jumper

 GPIO 31 (CAN A TX) was connected to directly to GPIO 10 (CAN B RX) using jumper

Is this approach correct? 

Do I have to change frequency or anything else 

Also the pin numbers I have used is as below, I have pulled them from schematic 

GPIO 30   - pin 46

GPIO 31   - pin 45

GPIO 10   - pin 76

GPIO 8   - pin 78

  • This is not a valid approach. Please read section 3.2 of my app.note SPRA876.

  • Dear Hareesh J, 

    Thankyou for your reply. As per the article I need a transceiver to connect to the TXA and RXA pins which can convert the signals to CAN H and CAN L (the can bus) to which all the can devices can be connected. 

    I had a couple of doubts: 

    1. There are CAN H , CAN L and GND pins on the F28379D launchpad ver. 2 which implies it has an inbuilt transceiver. Is my assumption correct?

    2. If my assumption is correct, how do I Code those pins to send data over CAN H and CAN L pins, here my intention is to connect two F28379D boards with CAN H and CAN L lines and watch CAN communication (send and receive the data over CAN bus) . How do I code it? Is there an example of the same?

    3. If my assumption is incorrect then I would use transceiver to convert TXA and RXA signals to CAN H and CAN L. Is this right? 

    4. Once I am able to properly work with CAN communication with two boards my final aim is to connect one launchpad to elmo driver solo gold twitter which supports CANopen communication 

    Thanks in advance 

  • 1. There are CAN H , CAN L and GND pins on the F28379D launchpad ver. 2 which implies it has an inbuilt transceiver. Is my assumption correct?

    Correct. You can see the transceiver in the schematics in C:\ti\c2000\C2000Ware_1_00_06_00\boards\LaunchPads\LAUNCHXL_F28379D\R2.0 directory of C2000Ware.

    2. If my assumption is correct, how do I Code those pins to send data over CAN H and CAN L pins, here my intention is to connect two F28379D boards with CAN H and CAN L lines and watch CAN communication (send and receive the data over CAN bus) . How do I code it? Is there an example of the same?

    Please take a look at can_ex3_external_transmit example in C:\ti\c2000\C2000Ware_1_00_06_00\driverlib\f2837xd\examples\cpu1\can

    3. If my assumption is incorrect then I would use transceiver to convert TXA and RXA signals to CAN H and CAN L. Is this right? 

    Transceiver is part of the Launchpad.

  •  Dear Hareesh J,

    Thankyou for the reply

    I have couple of doubts more

    as seen in the above screenshot, the connection come to D and R of the transceiver come from GPIO12 and GPIO17, 

    Hence I need to include the above GPIO pin numbers instead of GPIO 30,31 which is used by default in the code. Right?

     Secondly I am trying to find the pin map which shows me the GPIO pin to pin number mapping on the physical board?

    I have referred schematic and datasheet. 

    My approach is to find GPIO pin 10 in below diagram and since its pin 6 in J8 it would be pin 76 on the physical board. Is this approach correct?

    and last one, 

    Since I have to start CAN communication on two boards I will program GPIO 12 and GPIO 17 in board 1 and send TX msg from it and write similar code in other board to receive the messages sent. Is this understanding of CAN correct. 

    Thank you in advance sir!!

  • Hence I need to include the above GPIO pin numbers instead of GPIO 30,31 which is used by default in the code. Right?

    Correct.

    My approach is to find GPIO pin 10 in below diagram and since its pin 6 in J8 it would be pin 76 on the physical board. Is this approach correct?

    Sorry, I don’t understand. How did you arrive at pin 76 and which "physical board" are you talking about?

    Since I have to start CAN communication on two boards I will program GPIO 12 and GPIO 17 in board 1 and send TX msg from it and write similar code in other board to receive the messages sent. Is this understanding of CAN correct.

    You can do that. Note that for successful transmission, the receiving node simply needs to be configured for the same bit-rate. (more details in my app.note). So, technically, you could use the same code on the receiver, but no need to enable transmission. After you configure the node for the correct bit-rate, you could simply loop there.
  •  Dear sir,

    As shown in the above screenshot the physical board I am referring to is above one. As I was saying on schematic it shows GPIO 10  corresponds to 6th pin in J8 that means on the physical board it means pin 76. Is this understanding correct? 

    Just confirming GPIO12 and GPIO17 would have to be programmed to generate CANH and CANL signals. These waveforms  could be watched on oscilloscope by connecting the probe to CANH and probe GND to CAN GND?

    Can I just code the transmission part and program on one board and just monitor the CAN waveforms on the output before writing a code for receiving end. This should work right?  Or does the receive code must and all the CAN bus needs to connected? 

    Thank you in advance 

  • As shown in the above screenshot the physical board I am referring to is above one. As I was saying on schematic it shows GPIO 10 corresponds to 6th pin in J8 that means on the physical board it means pin 76. Is this understanding correct?

    The answer to your question is in the bottom side of the board. The silkscreen is clearly marked.

    Just confirming GPIO12 and GPIO17 would have to be programmed to generate CANH and CANL signals. These waveforms could be watched on oscilloscope by connecting the probe to CANH and probe GND to CAN GND?

    It is easier to probe the CANTX pin. Make sure you use a scope that can trigger on CAN signals. Such scopes will allow you configure the bit-rate and also define which signal you are using for trigger. If you use the CANTX signal, make sure you specify it. Else the scope won't trigger correctly. You could use a scope w/o CAN trigger, but you won't get a stable waveform.

    Can I just code the transmission part and program on one board and just monitor the CAN waveforms on the output before writing a code for receiving end. This should work right? Or does the receive code must and all the CAN bus needs to connected?

    Yes, you can do that. Note, however, that a transceiver must be connected to the CAN port for you to this. The Launchpad has it so you are good. But bear this in mind if you design your own board tomorrow.
  • Dear Sir,
    I have been tweak the external transmit code on the transmission board and was able to transmit data and the waveforms are visible on oscilloscope. Similarly I tried tweaking the external transmit code on the receive side but the data shown in RxMSGdata is some garbage value.
    I checked the code and using step in debug tried to analyse how the code runs. Its not able to process the received data even I tried to force it (set status = RX_MSG_OBJ_ID). Hence I believe it does not go in the loop of receiving the can messages and shows some garbage values.
    Kindly guide how I can troubleshoot the code
    I have also function called CANB_ISR in the main loop as without it it was giving errors.
    I Can send my if it helps

    Thanks In Advance
  • Shubham,
    Very hard to debug issues like this remotely, but I can suggest a few steps:

    Send just 1 frame and capture it at the CANRX pin of the receiver. Analyze the waveform and ensure that the receiver is indeed receiving what you expect. If you notice that the same frame is sent over and over again, it means ACK is not received. It is likely there is a H/W connection issue.

    Take it to the next step and capture the waveform in both CANRX and CANTX pins. See if the receiver generates an ACK. I have explained this in page 4 of my app.note SPRA890 (Note: this is a different app.note than SPRA876. I originally wrote it for LF240xA devices, but I have explained the ACK process with a figure). If you do see an ACK, that means data is reaching the CANRX pin correctly.

    The original example was written to be run on the same MCU. Meaning, it expects CAN-A & CAN-B of the same MCU to be connected together. You need to make significant changes to the code to split it into two and run it on two different nodes.
  • Dear Sir, 

    Thankyou for the reply. From the waveform, I can conclude the transmitter is sending the same frame again and again. As you have said and also I have read in your note SPRA876b and SPRA890, the transmitter is not receiving any ACK bits.

    Now I have a couple of doubts:

    1.  Is the ACK generation  done by writing a separate code or is it taken care of by the CAN protocol itself? (ofcourse after successful connection is established)

    2. I have single stepped my receive side code in debug mode and the code does not enter CANbISR, so is my conclusion of wrong logic in receive side correct or am I missing something else .Code is written below. 

    3. Can you share any document on how to write mailboxes in transmit and receive side. My understanding of CAN is whatever mailboxes I write in CAN on transmit side the same mailboxes have to written on receive side by making appropriate changes. Is this understanding correct.

    4. What exactly is the difference of CAN msg object and CAN mailboxes. 

    Dear Sir, I am new to this communication. Thankyou in advance 

    #include "driverlib.h"
    #include "device.h"


    #define TXCOUNT  100
    #define MSG_DATA_LENGTH    4
    #define TX_MSG_OBJ_ID    1
    #define RX_MSG_OBJ_ID    1

    volatile unsigned long i;
    //volatile uint32_t txMsgCount = 0;
    volatile uint32_t rxMsgCount = 0;
    volatile uint32_t errorFlag = 0;
    uint16_t rxMsgData[4];
    //
    // Function Prototypes
    //
    __interrupt void canbISR(void);
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize device clock and peripherals
        //
        Device_init();
        //
        // Initialize GPIO and configure GPIO pins for CANTX/CANRX
        // on module A and B
        //
        Device_initGPIO();
    // using GPIO 17 as CANRXB and GPIO 12 as CANTXB as these are hardwired to onboard transceiver in TMS320F28379D
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXB);
        GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXB);
        //
        // Initialize the CAN controllers

        CAN_initModule(CANB_BASE);
        //
        // Set up the CAN bus bit rate to 500kHz for each module
        // Refer to the Driver Library User Guide for information on how to set
        // tighter timing control. Additionally, consult the device data sheet
        // for more information about the CAN module clocking.

        CAN_setBitRate(CANB_BASE, DEVICE_SYSCLK_FREQ, 500000, 16);
        //
        // Enable interrupts on the CAN B peripheral.
        //
        CAN_enableInterrupt(CANB_BASE, CAN_INT_IE0 | CAN_INT_ERROR |
                            CAN_INT_STATUS);
        //
        // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        //
        Interrupt_initModule();
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
        //
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        //
        EINT;
        ERTM;
        //
        // 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.
        //
        Interrupt_register(INT_CANB0, &canbISR);
        //
        // Enable the CAN-B interrupt signal
        //
        Interrupt_enable(INT_CANB0);
        CAN_enableGlobalInterrupt(CANB_BASE, CAN_GLOBAL_INT_CANINT0);
        // Initialize the receive message object used for receiving CAN messages.
        // Message Object Parameters:
        //      CAN Module: B
        //      Message Object ID Number: 1
        //      Message Identifier: 0x95555555
        //      Message Frame: Extended
        //      Message Type: Receive
        //      Message ID Mask: 0x0
        //      Message Object Flags: Receive Interrupt
        //      Message Data Length: 4 Bytes
        //
        CAN_setupMessageObject(CANB_BASE, RX_MSG_OBJ_ID, 0x95555555,
                               CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, 0,
                               CAN_MSG_OBJ_RX_INT_ENABLE, MSG_DATA_LENGTH);

        CAN_startModule(CANB_BASE);
    __interrupt void
    canbISR(void)
    {
        uint32_t status;
        //
        // Read the CAN-B interrupt status to find the cause of the interrupt
        //
        status = CAN_getInterruptCause(CANB_BASE);

        //
        // 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 = CAN_getStatus(CANB_BASE);
            //
            // Check to see if an error occurred.
            //
            if(((status  & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_MSK) &&
               ((status  & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_NONE))
            {
                //
                // 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
            //
            CAN_readMessage(CANB_BASE, RX_MSG_OBJ_ID, rxMsgData);
            status = 0;
            //
            // 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.
            //
            CAN_clearInterruptStatus(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
        //
        CAN_clearGlobalInterruptStatus(CANB_BASE, CAN_GLOBAL_INT_CANINT0);
        //
        // Acknowledge this interrupt located in group 9
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    }

    //
    // End of File
    //

     

  • From the waveform, I can conclude the transmitter is sending the same frame again and again. As you have said and also I have read in your note SPRA876b and SPRA890, the transmitter is not receiving any ACK bits.

    OK. This is what I suspected. Your first order of business is to ensure that an ACK is received. Unless this happens, any further debug is pointless.

     

    Is the ACK generation  done by writing a separate code or is it taken care of by the CAN protocol itself? (of course after successful connection is established)

    It is taken care of by the protocol. Any receiver that received the frame successfully will generate an ACK.

     

    I have single stepped my receive side code in debug mode and the code does not enter CANbISR, so is my conclusion of wrong logic in receive side correct or am I missing something else .Code is written below. 

    If code does not enter the ISR, the frame is not received. Not surprising since you don’t even see an ACK.

     

    Can you share any document on how to write mailboxes in transmit and receive side. My understanding of CAN is whatever mailboxes I write in CAN on transmit side the same mailboxes have to written on receive side by making appropriate changes. Is this understanding correct.

    I don’t have any "document", but this is the reason we have the C2000Ware examples. Your understanding is incorrect. Any MBX can transmit to any other MBX (or mailboxes across different nodes). For example, MBX1 on node A can transmit to MBX23 on node B.

     

    What exactly is the difference of CAN msg object and CAN mailboxes. 

    No difference. They are one and the same.

  • The fact that you don't even get an ACK tells me there is a H/W problem. Please post your CAN bus wiring diagram. (Hand-drawn is OK). Are you sure your code configures the correct GPIO pins you use for CAN function (on both Tx & Rx side)?
  • I haven't heard from you in a while. I presume you were able to resolve your issue. If this is not the case, please re-open the thread.
  • I haven't heard from you in a while. I presume you were able to resolve your issue. If this is not the case, please re-open the thread