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.

EK-TM4C129EXL: CAN Bus Transmit,Tx is Not Working

Part Number: EK-TM4C129EXL
Other Parts Discussed in Thread: EK-TM4C1294XL, TPS2052, TPS2052B

Hi All. I am very new to CAN Bus protocol and TM4C. I am given a task to transmit CAN messages from 1 TM4C129EXL to another TM4C129EXL launchpad. Since I am new to this and I need to start from somewhere, I have decided to adapt the code and the hardware from the link below : http://ohm.ninja/tiva-c-series-can-bus-with-mcp2551/  and also by refering to the sample code from C:\ti\TivaWare_C_Series-2.1.4.178\examples\peripherals\can.

I have added severel UARTprintf to the void CANIntHandler(void) to help my debugging. I have also used the oscilloscope to check CANH,CANL and TX but there are no output (hence, scope caps are not attached in this post). The JP4 and JP5 jumpers are in default configuration since CAN1 is used instead of CAN0. Please do assist.

Attached is my code for Master:

#include <stdbool.h>
#include <stdint.h>
#include <math.h>

#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "driverlib/can.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/uart.h"
#include "driverlib/pin_map.h"

#include "utils/uartstdio.h"

#define PI 3.14159265359f

volatile bool errFlag = 0; // transmission error flag
unsigned int sysClock; // clockspeed in hz

void delay(unsigned int milliseconds) {
	SysCtlDelay((sysClock / 3) * (milliseconds / 1000.0f));
}

// CAN interrupt handler
void CANIntHandler(void) {

	unsigned long status = CANIntStatus(CAN1_BASE, CAN_INT_STS_CAUSE); // read interrupt status
	UARTprintf("Triggered\n");
	if(status == CAN_INT_INTID_STATUS) { // controller status interrupt
		status = CANStatusGet(CAN1_BASE, CAN_STS_CONTROL); // read back error bits, do something with them?
		errFlag = 1;
		UARTprintf("Triggered1\n");
	} else if(status == 1) { // message object 1
		CANIntClear(CAN1_BASE, 1); // clear interrupt
		errFlag = 0; // clear any error flags
		UARTprintf("Triggered2\n");
	} else { // should never happen
		UARTprintf("Unexpected CAN bus interrupt\n");
		UARTprintf("Error is-- %lu\n",status);
	}
}

int main(void) {

	tCANMsgObject msg; // the CAN message object
	unsigned int msgData; // the message data is four bytes long which we can allocate as an int32
	unsigned char *msgDataPtr = (unsigned char *)&msgData; // make a pointer to msgData so we can access individual bytes

	// Run from the PLL at 120 MHz.
	sysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);

	// Set up debugging UART
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // enable UART0 GPIO peripheral
	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
	GPIOPinConfigure(GPIO_PA0_U0RX);
	GPIOPinConfigure(GPIO_PA1_U0TX);
	GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
	UARTStdioConfig(0, 115200, sysClock); // 115200 baud

	// Set up CAN1
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // enable CAN1 GPIO peripheral
	GPIOPinConfigure(GPIO_PB0_CAN1RX);
	GPIOPinConfigure(GPIO_PB1_CAN1TX);
	GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN1);
	CANInit(CAN1_BASE);
	CANBitRateSet(CAN1_BASE, sysClock, 500000);
	CANIntRegister(CAN1_BASE, CANIntHandler); // use dynamic vector table allocation
	CANIntEnable(CAN1_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
	IntEnable(INT_CAN1);
	CANEnable(CAN1_BASE);

	// Set up msg object
	msgData = 0;
	msg.ui32MsgID = 1;
	msg.ui32MsgIDMask = 0;
	msg.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
	msg.ui32MsgLen = sizeof(msgDataPtr);
	msg.pui8MsgData = msgDataPtr;

	unsigned int t = 0; // loop counter
	float freq = 0.3; // frequency scaler

	while(1) {

		// set up next colour (scale sinf (0-1) to 0-255)
		msgDataPtr[0] = (0.5 + 0.5*sinf(t*freq)) * 0xFF;
		msgDataPtr[1] = (0.5 + 0.5*sinf(t*freq + (2*PI/3))) * 0xFF; // 120 degrees out of phase
		msgDataPtr[2] = (0.5 + 0.5*sinf(t*freq + (4*PI/3))) * 0xFF; // 240 degrees out of phase
		msgDataPtr[3] = 128; // 50% intensity

		UARTprintf("Sending colour\tr: %d\tg: %d\tb: %d\n", msgDataPtr[0], msgDataPtr[1], msgDataPtr[2]); // write colour to UART for debugging
		CANMessageSet(CAN1_BASE, 1, &msg, MSG_OBJ_TYPE_TX); // send as msg object 1

		delay(100); // wait 100ms

		if(errFlag) { // check for errors
			UARTprintf("CAN Bus Error\n");
		}

		t++; // overflow is fine
	}

	return 0;
}

Attached is my circuit diagram:

Attached is the output from the terminal:

  • Hi,
    I don't really spot anything wrong with your code. What type of errors are you getting when you call CANStatusGet() in the ISR? The type of errors can provide some clues.

    What do you see on the CAN1_TXD pin on the scope?

    On your schematic you have the PB0 and PB1 directly connected to the transceiver. The transceiver is 5V while the MCU is 3.3V. Do you have level shifter in between?
  • Two things of note:

    • Poster reports "CAN Bus not working" - which is highly unlikely - it is poster's implementation which is, "Not Working!"
    • Poster chose some (little known/tested) "ninja code."      Would not vendor's "long proven" and eased, "Simple CAN TX & Simple CAN RX" prove a superior choice?

  • Hi Charles.

    Attached is the pics of the ISR and scope probed to CAN1_TXD (PB1) directly. Regarding the level shifter, do I actually nee one as from what I see in the link (ohm.ninja/.../), the author did not use any level-shifters for his TM4C1294 to transceiver connection. How can I confirm this ? 

  • hi cb1_mobile,
    Agreed. I have edited the tittle to "CAN Bus Transmit,Tx is Not Working". I hope the title is more relevent now. I think the ninja code is just a slight modification of simple_tx.c whereby the author used CAN1 instead of CAN0 and his custom messages. I did went through ti's example and choosed to implement the ninja code instead since CAN1 doesnt require me to play around with the jumpers and I can still use UART0 for debugging. Correct me if I am wrong :)
  • I think the problem may be your bus transceiver. From the Microchip datasheet, if you leave Rs open, the transceiver is in standby mode and will not transmit.

    If this solves your problem, tell my friends at Microchip they owe me one.

  • A few comments.

    As Charles says the use of a 5V IC on a 3V bus is iffy. It may work with careful attention to logic levels, especially if the IC is designed to accept 3V levels or it may fail completely.

    Second that wiring hookup is trouble prone especially for 500kBaud. Breadboard is best avoided.

    Third as cb1 has noted it would help to know what the status returns were. Not all are errors IIRC (I don't have a reference handy), and even if you are getting an error knowing which one matters.

    Fourth, you don't mention whether you have a receiver up and running on the other TM4C, that is required.

    Fifth, it is a characteristic of CAN that if the connection is faulty then the transmitter will shut down after a short period. You ned to scope immediately after starting. If you wait you may miss signs of activity.

    Robert
  • What is the encoding of the returned value after you call CANStatusGet? You are showing just "ERROR" on the terminal. It should be one of the following or perhaps you are getting multiple errors. Also before you start the transmission, clear the status register first. Please be noted of comments from other folks. 

    #define CAN_STATUS_BUS_OFF      0x00000080
    
    //
    //! CAN controller error level has reached warning level.
    //
    #define CAN_STATUS_EWARN        0x00000040
    
    //
    //! CAN controller error level has reached error passive level.
    //
    #define CAN_STATUS_EPASS        0x00000020
    
    //
    //! A message was received successfully since the last read of this status.
    //
    #define CAN_STATUS_RXOK         0x00000010
    
    //
    //! A message was transmitted successfully since the last read of this
    //! status.
    //
    #define CAN_STATUS_TXOK         0x00000008
    
    //
    //! This is the mask for the last error code field.
    //
    #define CAN_STATUS_LEC_MSK      0x00000007
    
    //
    //! There was no error.
    //
    #define CAN_STATUS_LEC_NONE     0x00000000
    
    //
    //! A bit stuffing error has occurred.
    //
    #define CAN_STATUS_LEC_STUFF    0x00000001
    
    //
    //! A formatting error has occurred.
    //
    #define CAN_STATUS_LEC_FORM     0x00000002
    
    //
    //! An acknowledge error has occurred.
    //
    #define CAN_STATUS_LEC_ACK      0x00000003
    
    //
    //! The bus remained a bit level of 1 for longer than is allowed.
    //
    #define CAN_STATUS_LEC_BIT1     0x00000004
    
    //
    //! The bus remained a bit level of 0 for longer than is allowed.
    //
    #define CAN_STATUS_LEC_BIT0     0x00000005
    
    //
    //! A CRC error has occurred.
    //
    #define CAN_STATUS_LEC_CRC      0x00000006
    
    //
    //! This is the mask for the CAN Last Error Code (LEC).
    //
    #define CAN_STATUS_LEC_MASK     0x00000007

  • Bob Crosby said:
    ... if you leave Rs open, the transceiver is in standby mode and will not transmit.

    May I note that vendor's Bob provided a great service by "digging up" such detail.    Good that.

    However - staff (seriously) combed MCP2551 data - and they could find "NO/ZERO" detailing of the (default) voltage level - impressed upon (unconnected) pin Rs!    (slope resistor)

    Instead - with all of our digging - we find (and present):

    Red highlight reveals that it is (likely) that a high-level "must be applied to pin Rs - to force it into standby mode!"    

    Such is not a "sure thing" again "Nowhere" was the "unconnected voltage impressed upon pin Rs listed - w/in vendor's 24 pg. spec.     It is my belief that if pin Rs was "pulled up" - then the language (w/in 1.4.3 above) is superfluous - there would exist "no need" to "apply a high-level."

    In addition - should the Xcvr (actually) "default to standby" - it is likely that (many) would have been impaled - and poster reports (another's) success!

    It is my recommendation that user tie a 43K R between pin Rs and Gnd - such insures "active xcvr mode" w/reasonable signal transitions.

    Note separately - that the TXD connection between MCU & Xcvr - "will work" - spec accepts voltage down to 2V0 (thus TTL compatible) as "logic high."      RXD (xcvr output) may prove too high (nearly 5V) thus a 3:5 voltage divider should be considered.

    As to vendor agent's (outside) "friends" - they noted that their "mal de mer" has (almost) passed - and their (multiple) "rope burns" (from their enforced crewing) are expected (some day) to heal...   (maybe)

  • Hi Charles,

    When I tried my code today, I did not receive any errors (the error flag is not triggered). However, when I probed Tx (PB1) to the oscilloscope directly with reference to GND (without connecting to the transciever), I am unable to see any output on the scope. My JP4 & JP5 jumpers are in default condition (configured for UART). Are my oscilloscope settings correct (edge triggered, DC coupling) ? Attached is the screen shot of the code and the scope cap.

  • Hi CB1,

    Thank you and thank "staff" for also digging into the MCP2551 datasheet. (For once I am glad that it is not my datasheet in which it is hard to find important information.)

    I drew my conclusion from table 1-1 which states that if -Irs (current out of the RS pin) is less than 10uA the voltage on RS will be greater than 0.75Vdd. If there is no resistor on RS, the current out of the pin should be zero. Then from table 1-2, it shows that if Vrs > 0.75Vdd, that the can bus will be in the recessive state regardless of the state of the TXD pin. This is the issue the original poster is seeing.

    Bottom line, I am once again in total agreement with you. The original poster should try adding a pull-down resistor to the RS pin.

  • Hi Bob,

    As always - great to receive your "reasoned" response.      

    While your writing IS logical - it does not address the datasheet's "highly specific" dictate to, "Apply a "HIGH LEVEL" to the Rs pin!"

    And - in addition (and as stated) would it not prove "unwise" to have such CAN device "Default to Standby" - which would (predictably) IMPEDE - most all users?

    A final "tack" - our poster reported "success" of the "ninja user" - who he (emulated) (i.e. copied) in avoiding the use of any connection to (devil) pin Rs!   (as revealed by poster's schematic)

    In conclusion - use of (suggested) ~43K pull down R - AND "dialing down the CAN Data Rate" (at least temporarily) should (soon) see our poster, "On the Air!"   (CAN-AIR to be clear)

  • Hi Bob and cb1, although the error flag is not triggered anymore (the error i had previosly ), there seems to be no output from Tx pin of the launchpad. From the scope cap, the output stays high at 5V and doesnt seems to transmit any signal. (At this point I did not attempt anything with the transciever).
  • Hi,
    It seems like you initialize the errFlag to 0 to begin with and somehow the ISR is not entered and hence you think there is no error. If ISR is entered then you would have printed out Triggered and Triggered2. Did you disconnect the MCU from the transceiver? The CAN module needs to monitor the RX pin so it can arbitrate the bus. As mentioned earlier you need to have a level shifter on the RX pin.
  • Gowtham said:
    From the scope cap, the output stays high at 5V

    It's troublesome that the output from a 3V device is at 5V.

    Robert

  • Hello Robert,

    Indeed - yet staff's "deep dive" into Xcvr spec reveals (~75K pull-up) impressed upon Xcvr's TX pin!

    This appears to suggest that poster's connection (MCU TX to CAN TX) is "non-existent and/or faulty" or the MCU has been improperly configured into CAN mode...
  • 75K pull-up might do it. Not sure how the output drive of the TM4C will react to that with its 5V tolerance.

    The OP should be seeing transitions even w/o a transceiver but only if the scope is attached before the program starts and there is not a significant post trigger hold-off.

    Robert
  • Do keep in mind - use of "Simple RX/TX" has been "rejected" (due to the necessity to "Change the CAN Port" in SW) in favor of (surely) well tested "ninja code" - thus EVEN the Set-Up/Config of (everything) proves suspect!

    Use of KNOWN GOOD, Vendor supplied Programs (simpler the better) ALWAYS proves BEST...    (even if - and especially if - the "Port of interest/focus" must be altered!)

  • //*****************************************************************************
    //
    // simple_tx.c - Example demonstrating simple CAN message transmission.
    //
    // Copyright (c) 2010-2017 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    //   Redistribution and use in source and binary forms, with or without
    //   modification, are permitted provided that the following conditions
    //   are met:
    //
    //   Redistributions of source code must retain the above copyright
    //   notice, this list of conditions and the following disclaimer.
    //
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the
    //   documentation and/or other materials provided with the
    //   distribution.
    //
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    //
    // This is part of revision 2.1.4.178 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_can.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/can.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    //*****************************************************************************
    //
    //! \addtogroup can_examples_list
    //! <h1>Simple CAN TX (simple_tx)</h1>
    //!
    //! This example shows the basic setup of CAN in order to transmit 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.  A CAN interrupt
    //! handler is used to confirm message transmission and count the number of
    //! messages that have been sent.
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - CAN0 peripheral
    //! - GPIO Port B peripheral (for CAN0 pins)
    //! - CAN0RX - PB4
    //! - CAN0TX - PB5
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of CAN.
    //! - GPIO port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - INT_CAN0 - CANIntHandler
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // A counter that keeps track of the number of times the TX interrupt has
    // occurred, which should match the number of TX messages that were sent.
    //
    //*****************************************************************************
    volatile uint32_t g_ui32MsgCount = 0;
    
    //*****************************************************************************
    //
    // A flag to indicate that some transmission error occurred.
    //
    //*****************************************************************************
    volatile bool g_bErrFlag = 0;
    
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA6_U2RX);
        GPIOPinConfigure(GPIO_PA7_U2TX);
    
        //
        // Enable UART0 so that we can configure the clock.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2);
    
        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        UARTClockSourceSet(UART2_BASE, UART_CLOCK_PIOSC);
    
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(2, 115200, 16000000);
    }
    
    //*****************************************************************************
    //
    // This function provides a 1 second delay using a simple polling method.
    //
    //*****************************************************************************
    void
    SimpleDelay(void)
    {
        //
        // Delay cycles for 1 second
        //
        SysCtlDelay(16000000 / 3);
    }
    
    //*****************************************************************************
    //
    // This function is the interrupt handler for the CAN peripheral.  It checks
    // for the cause of the interrupt, and maintains a count of all messages that
    // have been transmitted.
    //
    //*****************************************************************************
    void
    CANIntHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Read the CAN interrupt status to find the cause of the interrupt
        //
        ui32Status = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
    
        //
        // If the cause is a controller status interrupt, then get the status
        //
        if(ui32Status == CAN_INT_INTID_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.  If the
            // CAN peripheral is not connected to a CAN bus with other CAN devices
            // present, then errors will occur and will be indicated in the
            // controller status.
            //
            ui32Status = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);
    
            //
            // Set a flag to indicate some errors may have occurred.
            //
            g_bErrFlag = 1;
        }
    
        //
        // Check if the cause is message object 1, which what we are using for
        // sending messages.
        //
        else if(ui32Status == 1)
        {
            //
            // Getting to this point means that the TX interrupt occurred on
            // message object 1, and the message TX is complete.  Clear the
            // message object interrupt.
            //
            CANIntClear(CAN0_BASE, 1);
    
            //
            // Increment a counter to keep track of how many messages have been
            // sent.  In a real application this could be used to set flags to
            // indicate when a message is sent.
            //
            g_ui32MsgCount++;
    
            //
            // Since the message was sent, clear any error flags.
            //
            g_bErrFlag = 0;
        }
    
        //
        // Otherwise, something unexpected caused the interrupt.  This should
        // never happen.
        //
        else
        {
            //
            // Spurious interrupt handling can go here.
            //
        }
    	UARTprintf("Int Handler complete..\n");
    }
    
    //*****************************************************************************
    //
    // Configure the CAN and enter a loop to transmit periodic CAN messages.
    //
    //*****************************************************************************
    int
    main(void)
    {
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        uint32_t ui32SysClock;
    #endif
    
        tCANMsgObject sCANMessage;
        uint32_t ui32MsgData;
        uint8_t *pui8MsgData;
    
        pui8MsgData = (uint8_t *)&ui32MsgData;
    
        //
        // Set the clocking to run directly from the external crystal/oscillator.
        // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
        // crystal on your board.
        //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
    #else
        SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);
    #endif
    
        //
        // Set up the serial console to use for displaying messages.  This is
        // just for this example program and is not needed for CAN operation.
        //
        InitConsole();
    
        //
        // For this example CAN0 is used with RX and TX pins on port B4 and B5.
        // The actual port and pins used may be different on your part, consult
        // the data sheet for more information.
        // GPIO port B needs to be enabled so these pins can be used.
        // TODO: change this to whichever GPIO port you are using
        //
        //SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
        //
        // Configure the GPIO pin muxing to select CAN0 functions for these pins.
        // This step selects which alternate function is available for these pins.
        // This is necessary if your part supports GPIO pin function muxing.
        // Consult the data sheet to see which functions are allocated per pin.
        // TODO: change this to select the port/pin you are using
        //
        GPIOPinConfigure(GPIO_PA0_CAN0RX);
        GPIOPinConfigure(GPIO_PA1_CAN0TX);
    
        //
        // Enable the alternate function on the GPIO pins.  The above step selects
        // which alternate function is available.  This step actually enables the
        // alternate function instead of GPIO for these pins.
        // TODO: change this to match the port/pin you are using
        //
        GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // The GPIO port and pins have been set up for CAN.  The CAN peripheral
        // must be enabled.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
    
        //
        // Initialize the CAN controller
        //
        CANInit(CAN0_BASE);
    
        //
        // Set up the bit rate for the CAN bus.  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.
        // In this example, the CAN bus is set to 500 kHz.  In the function below,
        // the call to SysCtlClockGet() or ui32SysClock is used to determine the
        // clock rate that is used for clocking the CAN peripheral.  This can be
        // replaced with a  fixed value if you know the value of the system clock,
        // saving the extra function call.  For some parts, the CAN peripheral is
        // clocked by a fixed 8 MHz regardless of the system clock in which case
        // the call to SysCtlClockGet() or ui32SysClock should be replaced with
        // 8000000.  Consult the data sheet for more information about CAN
        // peripheral clocking.
        //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        CANBitRateSet(CAN0_BASE, ui32SysClock, 500000);
    #else
        CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000);
    #endif
    
        //
        // Enable interrupts on the CAN peripheral.  This example uses static
        // allocation of interrupt handlers which means the name of the handler
        // is in the vector table of startup code.  If you want to use dynamic
        // allocation of the vector table, then you must also call CANIntRegister()
        // here.
        //
        // CANIntRegister(CAN0_BASE, CANIntHandler); // if using dynamic vectors
        //
        CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    
        //
        // Enable the CAN interrupt on the processor (NVIC).
        //
        IntEnable(INT_CAN0);
    
        //
        // Enable the CAN for operation.
        //
        CANEnable(CAN0_BASE);
    
        //
        // Initialize the message object that will be used for sending CAN
        // messages.  The message will be 4 bytes that will contain an incrementing
        // value.  Initially it will be set to 0.
        //
        ui32MsgData = 0;
        sCANMessage.ui32MsgID = 1;
        sCANMessage.ui32MsgIDMask = 0;
        sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
        sCANMessage.ui32MsgLen = sizeof(pui8MsgData);
        sCANMessage.pui8MsgData = pui8MsgData;
    
        //
        // 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 uint32_t
        // and incremented by one each time.
        //
        while(1)
        {
            //
            // Print a message to the console showing the message count and the
            // contents of the message being sent.
            //
            UARTprintf("Sending msg: 0x%02X %02X %02X %02X",
                       pui8MsgData[0], pui8MsgData[1], pui8MsgData[2],
                       pui8MsgData[3]);
    
            //
            // 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.
            //
            CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX);
    
            //
            // Now wait 1 second before continuing
            //
            SimpleDelay();
    
            //
            // Check the error flag to see if errors occurred
            //
            if(g_bErrFlag)
            {
                UARTprintf(" error - cable connected?\n");
            }
            else
            {
                //
                // If no errors then print the count of message sent
                //
                UARTprintf(" total count = %u\n", g_ui32MsgCount);
            }
    
            //
            // Increment the value in the message data.
            //
            ui32MsgData++;
        }
    
        //
        // Return no errors
        //
        return(0);
    }
    
    Hi Cb1,

    Since you worship the " Vendor supplied Programs", you have convinced me to try the "Simple TX". Therefore I have made few changes to the original "Simple TX" code to adapt with EK-TM4C129EXL and also to use UART2 ICDI virtual UART when CAN jumpers are configured. With this I have few questions:

    1) Is my init function for UART2 correct ? if yes, can I still use the USB debug on the lauchpad for UART2 or I must use a USB to UART cable connected to PA6 & PA7 instead?

    2) Can I run the clock from PLL at 120 MHz for CAN bus ?

    Attached is my modified Simple TX.

  • It looks fine to me except you need to specify 120MHz as the source clock for UARTSdioConfig instead of 16MHz. CAN module can take 120MHz as the source clock. The API will take the source clock and generate the corresponding bit timing. You need the USB to UART converter for UART2.

    I will also suggest you add the below two lines to place the CAN in loopback mode just to make sure the code is working before connecting to the transceiver so you can better isolate if the problem is with the code setup or not. The driver library does not have API to put into loopback mode. You need to do this manually.

    HWREG(CAN1_BASE+CAN_O_CTL) |= CAN_CTL_TEST;
    HWREG(CAN1_BASE+CAN_O_TST) |= CAN_TST_LBACK;
  • Sorry, the 16MHz is fine as you are using the PIOSC (16MHz) as the clock source for UART2.
  • Gowtham said:
    Since you worship the " Vendor supplied Programs", you have convinced me to try the "Simple TX".

    SO ... GOOD that!   (your convincing)    Although - in all fairness - my "worship" is of the famed and so effective guiding technique, "KISS."   (highlighted, colored, boldened - so "Like-less" Vendor - would not miss!)

    Recall - literally thousands here have employed "Simple_RX/TX" - to great success!   (to include moi)    Such cannot be said for "ninja werks."

    KISS argues for "Simplicity" - which is best provided by that KNOWN - and PROVEN - by MANY!    Systematic, Well Measurable, Small/Focused code blocks - exercised "one at a time" - well represent KISS...

    Note that KISS is well represented (world wide) - vendor agnostic - and is employed (perhaps (your word now) "worshiped") across the most complex of fields. 

  • //*****************************************************************************
    //
    // simple_tx.c - Example demonstrating simple CAN message transmission.
    //
    // Copyright (c) 2010-2017 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    //   Redistribution and use in source and binary forms, with or without
    //   modification, are permitted provided that the following conditions
    //   are met:
    //
    //   Redistributions of source code must retain the above copyright
    //   notice, this list of conditions and the following disclaimer.
    //
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the
    //   documentation and/or other materials provided with the
    //   distribution.
    //
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    //
    // This is part of revision 2.1.4.178 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_can.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/can.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    //*****************************************************************************
    //
    //! \addtogroup can_examples_list
    //! <h1>Simple CAN TX (simple_tx)</h1>
    //!
    //! This example shows the basic setup of CAN in order to transmit 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.  A CAN interrupt
    //! handler is used to confirm message transmission and count the number of
    //! messages that have been sent.
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - CAN1 peripheral
    //! - GPIO Port B peripheral (for CAN1 pins)
    //! - CAN1RX - PB4
    //! - CAN1TX - PB5
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of CAN.
    //! - GPIO port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - INT_CAN1 - CANIntHandler
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // A counter that keeps track of the number of times the TX interrupt has
    // occurred, which should match the number of TX messages that were sent.
    //
    //*****************************************************************************
    volatile uint32_t g_ui32MsgCount = 0;
    
    //*****************************************************************************
    //
    // A flag to indicate that some transmission error occurred.
    //
    //*****************************************************************************
    volatile bool g_bErrFlag = 0;
    
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
    
        //
        // Enable UART0 so that we can configure the clock.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, 16000000);
    	UARTprintf("DEBUG:UART DONE \n");
    }
    
    //*****************************************************************************
    //
    // This function provides a 1 second delay using a simple polling method.
    //
    //*****************************************************************************
    void
    SimpleDelay(void)
    {
        //
        // Delay cycles for 1 second
        //
        SysCtlDelay(16000000 / 3);
    }
    
    //*****************************************************************************
    //
    // This function is the interrupt handler for the CAN peripheral.  It checks
    // for the cause of the interrupt, and maintains a count of all messages that
    // have been transmitted.
    //
    //*****************************************************************************
    void
    CANIntHandler(void)
    {
        uint32_t ui32Status;
    	UARTprintf("DEBUG:CAN Int 1 \n");
        //
        // Read the CAN interrupt status to find the cause of the interrupt
        //
        ui32Status = CANIntStatus(CAN1_BASE, CAN_INT_STS_CAUSE);
    
        //
        // If the cause is a controller status interrupt, then get the status
        //
        if(ui32Status == CAN_INT_INTID_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.  If the
            // CAN peripheral is not connected to a CAN bus with other CAN devices
            // present, then errors will occur and will be indicated in the
            // controller status.
            //
            ui32Status = CANStatusGet(CAN1_BASE, CAN_STS_CONTROL);
    		UARTprintf("DEBUG:CAN Int CAN_INT_INTID_STATUS\n");
            //
            // Set a flag to indicate some errors may have occurred.
            //
            g_bErrFlag = 1;
        }
    
        //
        // Check if the cause is message object 1, which what we are using for
        // sending messages.
        //
        else if(ui32Status == 1)
        {
            //
            // Getting to this point means that the TX interrupt occurred on
            // message object 1, and the message TX is complete.  Clear the
            // message object interrupt.
            //
            CANIntClear(CAN1_BASE, 1);
    		UARTprintf("DEBUG:CAN Int ui32Status == 1\n");
            //
            // Increment a counter to keep track of how many messages have been
            // sent.  In a real application this could be used to set flags to
            // indicate when a message is sent.
            //
            g_ui32MsgCount++;
    
            //
            // Since the message was sent, clear any error flags.
            //
            g_bErrFlag = 0;
        }
    
        //
        // Otherwise, something unexpected caused the interrupt.  This should
        // never happen.
        //
        else
        {
            //
            UARTprintf("DEBUG:CAN Int something wrong\n");
            //
        }
    	UARTprintf("DEBUG:Int Handler complete..\n");
    }
    
    //*****************************************************************************
    //
    // Configure the CAN and enter a loop to transmit periodic CAN messages.
    //
    //*****************************************************************************
    int
    main(void)
    {
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        uint32_t ui32SysClock;
    #endif
    
        tCANMsgObject sCANMessage;
        uint32_t ui32MsgData;
        uint8_t *pui8MsgData;
    
        pui8MsgData = (uint8_t *)&ui32MsgData;
    
        //
        // Set the clocking to run directly from the external crystal/oscillator.
        // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
        // crystal on your board.
        //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
    #else
        SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);
    #endif
    
        //
        // Set up the serial console to use for displaying messages.  This is
        // just for this example program and is not needed for CAN operation.
        //
        InitConsole();
    
        //
        // For this example CAN1 is used with RX and TX pins on port B4 and B5.
        // The actual port and pins used may be different on your part, consult
        // the data sheet for more information.
        // GPIO port B needs to be enabled so these pins can be used.
        // TODO: change this to whichever GPIO port you are using
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
        //
        // Configure the GPIO pin muxing to select CAN1 functions for these pins.
        // This step selects which alternate function is available for these pins.
        // This is necessary if your part supports GPIO pin function muxing.
        // Consult the data sheet to see which functions are allocated per pin.
        // TODO: change this to select the port/pin you are using
        //
        GPIOPinConfigure(GPIO_PB0_CAN1RX);
        GPIOPinConfigure(GPIO_PB1_CAN1TX);
    
        //
        // Enable the alternate function on the GPIO pins.  The above step selects
        // which alternate function is available.  This step actually enables the
        // alternate function instead of GPIO for these pins.
        // TODO: change this to match the port/pin you are using
        //
        GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // The GPIO port and pins have been set up for CAN.  The CAN peripheral
        // must be enabled.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN1);
    
        //
        // Initialize the CAN controller
        //
        CANInit(CAN1_BASE);
    
        //
        // Set up the bit rate for the CAN bus.  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.
        // In this example, the CAN bus is set to 500 kHz.  In the function below,
        // the call to SysCtlClockGet() or ui32SysClock is used to determine the
        // clock rate that is used for clocking the CAN peripheral.  This can be
        // replaced with a  fixed value if you know the value of the system clock,
        // saving the extra function call.  For some parts, the CAN peripheral is
        // clocked by a fixed 8 MHz regardless of the system clock in which case
        // the call to SysCtlClockGet() or ui32SysClock should be replaced with
        // 8000000.  Consult the data sheet for more information about CAN
        // peripheral clocking.
        //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        CANBitRateSet(CAN1_BASE, ui32SysClock, 500000);
    #else
        CANBitRateSet(CAN1_BASE, SysCtlClockGet(), 500000);
    #endif
    
        //
        // Enable interrupts on the CAN peripheral.  This example uses static
        // allocation of interrupt handlers which means the name of the handler
        // is in the vector table of startup code.  If you want to use dynamic
        // allocation of the vector table, then you must also call CANIntRegister()
        // here.
        //
        // CANIntRegister(CAN1_BASE, CANIntHandler); // if using dynamic vectors
        //
        CANIntEnable(CAN1_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    
        //
        // Enable the CAN interrupt on the processor (NVIC).
        //
        IntEnable(INT_CAN1);
    
        //
        // Enable the CAN for operation.
        //
        CANEnable(CAN1_BASE);
    
        //
        // Initialize the message object that will be used for sending CAN
        // messages.  The message will be 4 bytes that will contain an incrementing
        // value.  Initially it will be set to 0.
        //
        ui32MsgData = 0;
        sCANMessage.ui32MsgID = 1;
        sCANMessage.ui32MsgIDMask = 0;
        sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
        sCANMessage.ui32MsgLen = sizeof(pui8MsgData);
        sCANMessage.pui8MsgData = pui8MsgData;
    
        //
        // 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 uint32_t
        // and incremented by one each time.
        //
        while(1)
        {
            //
            // Print a message to the console showing the message count and the
            // contents of the message being sent.
            //
            UARTprintf("Sending msg: 0x%02X %02X %02X %02X",
                       pui8MsgData[0], pui8MsgData[1], pui8MsgData[2],
                       pui8MsgData[3]);
    
            //
            // 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.
            //
            CANMessageSet(CAN1_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX);
    
            UARTprintf("DEBUG: Send Complete");
            //
            // Now wait 1 second before continuing
            //
            SimpleDelay();
    
            //
            // Check the error flag to see if errors occurred
            //
            if(g_bErrFlag)
            {
                UARTprintf(" error - cable connected?\n");
            }
            else
            {
                //
                // If no errors then print the count of message sent
                //
                UARTprintf(" total count = %u\n", g_ui32MsgCount);
            }
    
            //
            // Increment the value in the message data.
            //
            ui32MsgData++;
        }
    
        //
        // Return no errors
        //
        return(0);
    }
    
    HI all,

    1) While waiting for the UART to USB converter, I have decided to try the vendor supplied program using CAN1 and UART0. It seems to me, the program is not calling CANIntHandler() and did not continue after "UARTprintf("Sending msg: 0x%02X %02X %02X %02X",)" statement. The output is as below. From the oscilloscope, the Tx is now 5V but no sign of transmit signal.  (This is tested by connecting the Tx pin directly to the oscilloscope).

    2) I could not compile the program to attempt loopback using "HWREG(CAN1_BASE+CAN_O_CTL) |= CAN_CTL_TEST;" and "HWREG(CAN1_BASE+CAN_O_TST) |= CAN_TST_LBACK;". The error message are as below: 

    1)

    2)

  • That is a bit weird. Can you do HWREG write to any register?
  • Charles,

    If we "steer poster" to "loopback" - should we not "Provide (some) instruction as to "How" loopback should be deployed?"

    Specifically - does poster:

    • maintain his TX & RX connections between MCU and ONE CAN Xcvr?
    • should you not describe what (likely) MCU connections are to be deployed?    (does he connect TX from one UART to RX of a 2nd (different) UART - on that SAME MCU?)

    I've followed (many) such CAN Loopback postings - should memory serve - most ... have not proved greatly successful!    (many - not at all...)

  • Hi cb1,

      My purpose of the loopback mode is to make sure the configuration of the CAN module is proper. In loopback mode the poster can check if the ISR is entered and if the message is sent. There is no need to connect the MCU to the transceiver. As a matter of fact in loopback mode the CAN module will ignore the RX pin. Internally the TX is connected to the RX but the kernel will ignore the ACK bit since there is no node on the bus to drive the ACK. He can leave both the TX and RX pins open in loopback mode. Once loopback mode is working at least we know it is programmed as expected to work, he can then disable the loopback and focus on the connection between the MCU and transceiver and between the transceiver to the bus. I will suggest the poster to open the register window and monitor the CANSTS (CAN status) register when he gets an error. It is likely that the RX is held at recessive state when the TX is trying to drive a dominant bit on the bus. When this happens, it will be a Bit-0 error and eventually exceed the error counter threshold and will force the CAN controller into bus-off state. 

  • As an "even more basic, fact-finding approach" I'd suggest poster reconfigure his selected UART_TX (instead) into GPIO (push-pull) Output) then write code to toggle it at 5-10 Hz.    

    Such should immediately reveal:

    • likelihood of connection integrity between UART_TX (MCU pin) and Xcvr's TX.
    • that such toggling HAS "awakened the Xcvr" and "Dominant vs. Recessive" differential output should reveal upon CAN Bus H & L.

    It has been (ONLY) assumed that connection integrity has been achieved.    And the (banned from here (KISS)) stands ready/able to detect - and deny or confirm - such outcome.    (you may note that both Robert & myself noted the 5V output - "claimed" to be upon the "interconnect between XCVR TX and MCU TX."    Instead - unless this is one of the "non-standard or USB pins" is not there reasonable expectation - that an ESD diode would clamp that 5V to a diode drop beyond (above) 3V3?    Absent such "clamping" as poster's cap revealed - there is either "mis-connect" or "damage" to that UART_TX pin - and "all here" continue the "endless, chase of our tails."    (which while fun - proves not terribly effective...)

  • Today's Story:

    1) The while loop seems to be working. However, the CANIntHandler is not triggered and count of message sent (total count) remains 0. Wierd. Attached the screen shot and code.

    2) dear cb1, could you provide me an example or reference for ' reconfigure selected UART_TX (instead) into GPIO (push-pull) Output) then write code to toggle it at 5-10 Hz.  '

    Again this is attempted without using any transciever and directly probing the tx to oscilloscope after the program is initiated.

    //*****************************************************************************
    //
    // simple_tx.c - Example demonstrating simple CAN message transmission.
    //
    // Copyright (c) 2010-2017 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    //   Redistribution and use in source and binary forms, with or without
    //   modification, are permitted provided that the following conditions
    //   are met:
    //
    //   Redistributions of source code must retain the above copyright
    //   notice, this list of conditions and the following disclaimer.
    //
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the
    //   documentation and/or other materials provided with the
    //   distribution.
    //
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    //
    // This is part of revision 2.1.4.178 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_can.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/can.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    //*****************************************************************************
    //
    //! \addtogroup can_examples_list
    //! <h1>Simple CAN TX (simple_tx)</h1>
    //!
    //! This example shows the basic setup of CAN in order to transmit 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.  A CAN interrupt
    //! handler is used to confirm message transmission and count the number of
    //! messages that have been sent.
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - CAN1 peripheral
    //! - GPIO Port B peripheral (for CAN1 pins)
    //! - CAN1RX - PB4
    //! - CAN1TX - PB5
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of CAN.
    //! - GPIO port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - INT_CAN1 - CANIntHandler
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // A counter that keeps track of the number of times the TX interrupt has
    // occurred, which should match the number of TX messages that were sent.
    //
    //*****************************************************************************
    volatile uint32_t g_ui32MsgCount = 0;
    
    //*****************************************************************************
    //
    // A flag to indicate that some transmission error occurred.
    //
    //*****************************************************************************
    volatile bool g_bErrFlag = 0;
    
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
    
        //
        // Enable UART0 so that we can configure the clock.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, 16000000);
    	UARTprintf("DEBUG:UART DONE \n");
    }
    
    //*****************************************************************************
    //
    // This function provides a 1 second delay using a simple polling method.
    //
    //*****************************************************************************
    void
    SimpleDelay(void)
    {
        //
        // Delay cycles for 1 second
        //
        SysCtlDelay(16000000 / 3);
    }
    
    //*****************************************************************************
    //
    // This function is the interrupt handler for the CAN peripheral.  It checks
    // for the cause of the interrupt, and maintains a count of all messages that
    // have been transmitted.
    //
    //*****************************************************************************
    void
    CANIntHandler(void)
    {
        uint32_t ui32Status;
    	UARTprintf("DEBUG:CAN Int 1 \n");
        //
        // Read the CAN interrupt status to find the cause of the interrupt
        //
        ui32Status = CANIntStatus(CAN1_BASE, CAN_INT_STS_CAUSE);
    
        //
        // If the cause is a controller status interrupt, then get the status
        //
        if(ui32Status == CAN_INT_INTID_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.  If the
            // CAN peripheral is not connected to a CAN bus with other CAN devices
            // present, then errors will occur and will be indicated in the
            // controller status.
            //
            ui32Status = CANStatusGet(CAN1_BASE, CAN_STS_CONTROL);
    		UARTprintf("DEBUG:CAN Int CAN_INT_INTID_STATUS\n");
            //
            // Set a flag to indicate some errors may have occurred.
            //
            g_bErrFlag = 1;
        }
    
        //
        // Check if the cause is message object 1, which what we are using for
        // sending messages.
        //
        else if(ui32Status == 1)
        {
            //
            // Getting to this point means that the TX interrupt occurred on
            // message object 1, and the message TX is complete.  Clear the
            // message object interrupt.
            //
            CANIntClear(CAN1_BASE, 1);
    		UARTprintf("DEBUG:CAN Int ui32Status == 1\n");
            //
            // Increment a counter to keep track of how many messages have been
            // sent.  In a real application this could be used to set flags to
            // indicate when a message is sent.
            //
            g_ui32MsgCount++;
    
            //
            // Since the message was sent, clear any error flags.
            //
            g_bErrFlag = 0;
        }
    
        //
        // Otherwise, something unexpected caused the interrupt.  This should
        // never happen.
        //
        else
        {
            //
            UARTprintf("DEBUG:CAN Int something wrong\n");
            //
        }
    	UARTprintf("DEBUG:Int Handler complete..\n");
    }
    
    //*****************************************************************************
    //
    // Configure the CAN and enter a loop to transmit periodic CAN messages.
    //
    //*****************************************************************************
    int
    main(void)
    {
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        uint32_t ui32SysClock;
    #endif
    
        tCANMsgObject sCANMessage;
        uint32_t ui32MsgData;
        uint8_t *pui8MsgData;
    
        pui8MsgData = (uint8_t *)&ui32MsgData;
    
        //
        // Set the clocking to run directly from the external crystal/oscillator.
        // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
        // crystal on your board.
        //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
    #else
        SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);
    #endif
    
        //
        // Set up the serial console to use for displaying messages.  This is
        // just for this example program and is not needed for CAN operation.
        //
        InitConsole();
    
        //
        // For this example CAN1 is used with RX and TX pins on port B4 and B5.
        // The actual port and pins used may be different on your part, consult
        // the data sheet for more information.
        // GPIO port B needs to be enabled so these pins can be used.
        // TODO: change this to whichever GPIO port you are using
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
        //
        // Configure the GPIO pin muxing to select CAN1 functions for these pins.
        // This step selects which alternate function is available for these pins.
        // This is necessary if your part supports GPIO pin function muxing.
        // Consult the data sheet to see which functions are allocated per pin.
        // TODO: change this to select the port/pin you are using
        //
        GPIOPinConfigure(GPIO_PB0_CAN1RX);
        GPIOPinConfigure(GPIO_PB1_CAN1TX);
    
        //
        // Enable the alternate function on the GPIO pins.  The above step selects
        // which alternate function is available.  This step actually enables the
        // alternate function instead of GPIO for these pins.
        // TODO: change this to match the port/pin you are using
        //
        GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // The GPIO port and pins have been set up for CAN.  The CAN peripheral
        // must be enabled.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN1);
    
        //
        // Initialize the CAN controller
        //
        CANInit(CAN1_BASE);
    
        //
        // Set up the bit rate for the CAN bus.  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.
        // In this example, the CAN bus is set to 500 kHz.  In the function below,
        // the call to SysCtlClockGet() or ui32SysClock is used to determine the
        // clock rate that is used for clocking the CAN peripheral.  This can be
        // replaced with a  fixed value if you know the value of the system clock,
        // saving the extra function call.  For some parts, the CAN peripheral is
        // clocked by a fixed 8 MHz regardless of the system clock in which case
        // the call to SysCtlClockGet() or ui32SysClock should be replaced with
        // 8000000.  Consult the data sheet for more information about CAN
        // peripheral clocking.
        //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        CANBitRateSet(CAN1_BASE, ui32SysClock, 500000);
    #else
        CANBitRateSet(CAN1_BASE, SysCtlClockGet(), 500000);
    #endif
    
        //
        // Enable interrupts on the CAN peripheral.  This example uses static
        // allocation of interrupt handlers which means the name of the handler
        // is in the vector table of startup code.  If you want to use dynamic
        // allocation of the vector table, then you must also call CANIntRegister()
        // here.
        //
        // CANIntRegister(CAN1_BASE, CANIntHandler); // if using dynamic vectors
        //
        CANIntEnable(CAN1_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    
        //
        // Enable the CAN interrupt on the processor (NVIC).
        //
        IntEnable(INT_CAN1);
    
        //
        // Enable the CAN for operation.
        //
        CANEnable(CAN1_BASE);
    
        //
        // Initialize the message object that will be used for sending CAN
        // messages.  The message will be 4 bytes that will contain an incrementing
        // value.  Initially it will be set to 0.
        //
        ui32MsgData = 0;
        sCANMessage.ui32MsgID = 1;
        sCANMessage.ui32MsgIDMask = 0;
        sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
        sCANMessage.ui32MsgLen = sizeof(pui8MsgData);
        sCANMessage.pui8MsgData = pui8MsgData;
    
        //
        // 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 uint32_t
        // and incremented by one each time.
        //
        while(1)
        {
            //
            // Print a message to the console showing the message count and the
            // contents of the message being sent.
            //
            UARTprintf("Sending msg: 0x%02X %02X %02X %02X\n",
                       pui8MsgData[0], pui8MsgData[1], pui8MsgData[2],
                       pui8MsgData[3]);
    
            //
            // 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.
            //
            CANMessageSet(CAN1_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX);
    
            UARTprintf("DEBUG: Send Complete\n");
            //
            // Now wait 1 second before continuing
            //
            SimpleDelay();
    
            //
            // Check the error flag to see if errors occurred
            //
            if(g_bErrFlag)
            {
                UARTprintf(" error - cable connected?\n");
            }
            else
            {
                //
                // If no errors then print the count of message sent
                //
                UARTprintf(" total count = %u\n", g_ui32MsgCount);
            }
    
            //
            // Increment the value in the message data.
            //
            ui32MsgData++;
        }
    
        //
        // Return no errors
        //
        return(0);
    }
    

  • Feel your pain - but (so much) is induced (and added) by "Not following KISS guidelines!"

    Causing GPIO to "toggle" is among the most elementary of MCU operations - if you've "not yet" reached that point - you are in HUGE violation of "KISS" - by moving to the "far more difficult" attempt to implement CAN.

    It is quite "normal" - when beginning posters import "net code" - without deep understanding - and thus (predictably) fail in their efforts.

    Might you be moving "too quickly" - with an objective "too advanced?" None of this intends to be negative - instead I seek to make you "KISS compliant" - which years of experience (and founding - then taking past tech firm PUBLIC) have proved to be (by far) a superior, "Method of Attack!"

    Your read of the MCU manual (GPIO section) - along w/"Peripheral Driver User Guide" - and your (expanded) use of the Forum Search Box (atop this forum page) keyworded "GPIO set-up/config" are all, "KISS prescribed" - and I believe (most) necessary - for your more empowered understanding and resulting success...

    I've rarely seen "shortcuts" work - and they never prove "lasting." The decision to "launch into CAN" (most prematurely - IMO) overtaxes your knowledge base (at this early time). Starting instead w/the suggested "GPIO Mastery" - gained thru your experimentation (minus any CAN) is your "best path toward (even CAN) success...
  • Hi,

     You can use the blinky example program from TivaWare as a reference. Modify it toggle PB1 pin.

     The reason that your program didn't jump to the CANIntHandler is probably because you didn't uncomment the CANIntRegister() shown below unless you have specified the vector statically in the startup_ccs.c. Try to uncomment the line and run again. BTW, I thought you were going to try the TivaWare example as is which is using CAN0 but you seem to modify it for CAN1 again with different clock speed. 

        //
        // Enable interrupts on the CAN peripheral.  This example uses static
        // allocation of interrupt handlers which means the name of the handler
        // is in the vector table of startup code.  If you want to use dynamic
        // allocation of the vector table, then you must also call CANIntRegister()
        // here.
        //
        // CANIntRegister(CAN1_BASE, CANIntHandler); // if using dynamic vectors
        //
        CANIntEnable(CAN1_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);

  • Charles,

    At the risk of "vendor wrath" (i.e. further wrath) had you noted that poster is (presently) unaware of, "How to toggle GPIO."    As such - is it (really) wise to (further) encourage the "Drive towards CAN" - when (clearly) there is so much more "necessary learning" on poster's plate?

    Is the forum (only) to attend posters', "desire du jour" - and pass (far) from the real requirements - "disciplined learning & understanding?"

    Might today's (small fire) be doused (via spoon-fed, cut/paste) yet far larger (and predictable) "inferno" - surely lurk, "around the corner?"

    The rather clear "vendor rejection of KISS" comes squarely (and undeniably) into view here - is this really best?      Will the greatest volume of MCU Sales result from, "Neglect of Process?"

  • Gowtham said:
    The JP4 and JP5 jumpers are in default configuration since CAN1 is used instead of CAN0

    Hi Gowtham,

    JP4/5 are upside down in launch pad schematic relative targets MCU PD4, PD5 are available on BP2-X6 pins 9,11. Thus  PD4/5 of JP4/5 are on the X11 header pin 40 , X11-pin 38 and your picture shows CAN jumper wires on pin 58 and pin 60. UART0 of target MCU connects to ICDI UART0 via JP4/5,  UART0 jumpers can be turned sideways across JP4/5 headers to select MCU PA0, PA1 are for CAN0 out to BP2-X6 pins 9,11.

    X11 pin 60 =Target VBUS/1.6B

    X11 pin 58 = PB0

    X11 pin ? = PB1 seemingly does not exist....

    Likewise you have to do an alternate digital selection GPIO configuration where UART0=CAN0... I don't see that in your code...

  • Edit above post PA0,PA1 = CAN0 not CAN1 as shown in your code examples.

    1. Did you discover CAN1-TXD1 is not accessible on launch pad? 

    2. Text source states to terminate all devices on CAN serial bus?

    Note: JP4,5 turned sideways [1-3], [2-4]; UART2 can be configured for Printf() calls via ICDI.

    Camper smiles as big fish on hook puts up a furious fight, ends up in the frying pan over semantics.

  • Hi BP101,

     CAN1_TX is accessible at X11-60. I just created a loopback from TX (X11-60) to RX (X11-58). I ran OP's program with only modification to the data. I changed all data to 0x55 to avoid bit stuffing for easier viewing. Since it is a loopback the CAN transmitter will fail due to no ACK from any receivers. 

  • BP101 said:
    Camper smiles as big fish on hook puts up a furious fight, ends up in the frying pan over semantics.

    Does not vendor Charles' latest post - w/Xtal Clear Scope cap - prove that "semantics" are far from ALONE in (mistakes) w/in BP suggested "fix."    

    A more "furious fight" appears the presence - or lack thereof - of CAN1-TXD1.     Only BP - or Charles - can be correct.     (high stack of cb1 chips placed w/"Charles.")

  • Hi BP101, 

    Thank for your comment, I will try this loopback configuration using TX (X11-60) to RX (X11-58). 

    Hi Charles,

    I would like to replicate this work using my launchpad and check if my TX (X11-60) is actually working indeed . Would you be kind enough to provide me ur code ? (as you know previously i tried loopback using  "HWREG(CAN1_BASE+CAN_O_CTL) |= CAN_CTL_TEST;" and "HWREG(CAN1_BASE+CAN_O_TST) |= CAN_TST_LBACK;" but could not succeed. 

  • Hi Gowtham,

     I used your program. The only thing I changed was the msgData where I force the data to 0x55. You don't have the change at all. The only reason I changed was to avoid bit stuffing. All you need is to create an external loopback between X11-60 and X11-58 and probe the X11-60 on the scope and you should be able to see what I see. Earlier I was suggesting using internal loopback that is part of the CAN module's diagnostic tests. 

    If you look at the scope cap I displayed it is proper until it fails the ACK. The message ID is 1. Since it is a '1' then the protocol will have to bit stuff after every 5 consecutive same states. The Identifier field is 11 bits. You then see the RTR/IDE/R0 bits equal 0 followed by the DLC which is a 4 (4 bytes of data to followed). In the data field you see 4 bytes of 0x55 followed by the CRC. The ACK field is recessive which is expected since I'm in loopback mode. The ACK normally is replied by the receiver to dominant state. I have not used transceiver here.

    #include <stdbool.h>
    #include <stdint.h>
    #include <math.h>
    
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_can.h"
    #include "inc/hw_ints.h"
    #include "driverlib/can.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    #include "driverlib/uart.h"
    #include "driverlib/pin_map.h"
    
    #include "utils/uartstdio.h"
    
    #define PI 3.14159265359f
    
    volatile bool errFlag = 0; // transmission error flag
    unsigned int sysClock; // clockspeed in hz
    
    void delay(unsigned int milliseconds) {
        SysCtlDelay((sysClock / 3) * (milliseconds / 1000.0f));
    }
    
    // CAN interrupt handler
    void CANIntHandler(void) {
    
        unsigned long status = CANIntStatus(CAN1_BASE, CAN_INT_STS_CAUSE); // read interrupt status
        UARTprintf("Triggered\n");
        if(status == CAN_INT_INTID_STATUS) { // controller status interrupt
            status = CANStatusGet(CAN1_BASE, CAN_STS_CONTROL); // read back error bits, do something with them?
            errFlag = 1;
            UARTprintf("Triggered1\n");
        } else if(status == 1) { // message object 1
            CANIntClear(CAN1_BASE, 1); // clear interrupt
            errFlag = 0; // clear any error flags
            UARTprintf("Triggered2\n");
        } else { // should never happen
            UARTprintf("Unexpected CAN bus interrupt\n");
            UARTprintf("Error is-- %lu\n",status);
        }
    }
    
    int main(void) {
    
        tCANMsgObject msg; // the CAN message object
        unsigned int msgData; // the message data is four bytes long which we can allocate as an int32
        unsigned char *msgDataPtr = (unsigned char *)&msgData; // make a pointer to msgData so we can access individual bytes
    
        // Run from the PLL at 120 MHz.
        sysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
    
        // Set up debugging UART
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // enable UART0 GPIO peripheral
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        UARTStdioConfig(0, 115200, sysClock); // 115200 baud
    
        // Set up CAN1
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // enable CAN1 GPIO peripheral
        GPIOPinConfigure(GPIO_PB0_CAN1RX);
        GPIOPinConfigure(GPIO_PB1_CAN1TX);
        GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN1);
        CANInit(CAN1_BASE);
        CANBitRateSet(CAN1_BASE, sysClock, 500000);
        CANIntRegister(CAN1_BASE, CANIntHandler); // use dynamic vector table allocation
        CANIntEnable(CAN1_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
        IntEnable(INT_CAN1);
        CANEnable(CAN1_BASE);
    
        // Set up msg object
        msgData = 0;
        msg.ui32MsgID = 1;
        msg.ui32MsgIDMask = 0;
        msg.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
        msg.ui32MsgLen = sizeof(msgDataPtr);
        msg.pui8MsgData = msgDataPtr;
    
        unsigned int t = 0; // loop counter
       // float freq = 0.3; // frequency scaler
    
        while(1) {
    
            // set up next colour (scale sinf (0-1) to 0-255)
     //       msgDataPtr[0] = (0.5 + 0.5*sinf(t*freq)) * 0xFF;
     //       msgDataPtr[1] = (0.5 + 0.5*sinf(t*freq + (2*PI/3))) * 0xFF; // 120 degrees out of phase
     //       msgDataPtr[2] = (0.5 + 0.5*sinf(t*freq + (4*PI/3))) * 0xFF; // 240 degrees out of phase
     //       msgDataPtr[3] = 128; // 50% intensity
        	        msgDataPtr[0] = 0x55;
        	        msgDataPtr[1] = 0x55;
        	        msgDataPtr[2] = 0x55;
        	        msgDataPtr[3] = 0x55;
    
    
            UARTprintf("Sending colour\tr: %d\tg: %d\tb: %d\n", msgDataPtr[0], msgDataPtr[1], msgDataPtr[2]); // write colour to UART for debugging
            CANMessageSet(CAN1_BASE, 1, &msg, MSG_OBJ_TYPE_TX); // send as msg object 1
    
            delay(100); // wait 100ms
    
            if(errFlag) { // check for errors
                UARTprintf("CAN Bus Error\n");
            }
    
            t++; // overflow is fine
        }
    
        return 0;
    }

  • Charles Tsai said:
    CAN1_TX is accessible at X11-60

    According to the launch pad schematic EK-TM4C1294XL the X11-60 is (hard) tied to USB- VBUS and identified as such. Gowtham's launch pad looks identical EK-TM4C1294XL, not sure what 129EXL is in post title. Have to now wonder if that is even the same X11 header, if not why so different as that is not keeping consistent design principals in the very same family of launch pads.

    @Gowtham the control area network in my schematic (JP4/5) uses MCU CAN0 on PA0, PA1, seems EXL may have a different X11 header pin out I'm not aware of.

  • Perhaps the posters launch pad is not EXL, red beast looks identical to all the XL's we now own. Questions are why would TI make such an abrupt change on the X11 header pin 60 and does poster have the exact same LP as Charles?
  • Hi BP101,
    You are not alone. When I read the schematic I also had the same doubt at first. The TARGET_VBUS which is connected to PB1 came from the TPS2052B power switches. The TPS2052B takes its power source from one of the three power sources (BoosterPack, TARGET_VBUS or DEBUG_VBUS). The TPS2052's EN2 input is low by default which shuts off the switch to the TARGET_VBUS and in addition there is nothing connected to the Device USB port, hence the TARGET_VBUS is open until it is sourced from the MCU's PB1.
  • BP101 said:
    Perhaps the posters launch pad is not EXL

    Mon ami - might your, "Junior Detective" badge require (some) investigatory upgrades?

    You suggest poster's LPad may not be EXL - yet his "very first post" reveals - NOT ONE - but TWO such (identical) LPads (via highly legible photos) - both clearly screen printed: "EK-TM4C129EXL Rev A."

    Thus - indeed - both ARE (assuredly) EXLs!     Might your earlier battle w/claimed "big fish" have exhausted - dulled your (usual) investigative might?

    BP101 said:
    ... is not keeping consistent design principals in the very same family of launch pads. 

    You may also note - "principal" (is your friend), "principle" (fundamental truth or law) was the word you, "meant to use."    (again - "semantics" has company w/in "fishy" BP posting...)

  • cb1_mobile said:
    both clearly screen printed: "EK-TM4C129EXL Rev

    That escapes my vision on either launch pad so have to trust your words it is such.

    cb1_mobile said:
    Thus - indeed - both ARE (assuredly) EXLs!  

     Perhaps is true yet X11- pin 60 should not be producing +5v VDC (period) as clearly shown in scope capture 10/25 10:01Am. It would appear X11 pin 60 it is connected to USB port VBUS +5vdc. So it would appear the EXL & XL are identical PCB layout and only the MCU is different.  

    cb1_mobile said:
    You may also note - "principal" (is your friend), "principle

    Focusing on the issue and not spelling might you have caught +5V is far to high a voltage for non +5v GPIO pin? I never was one for English homonyms being viable as many civilizations prior to English tyrannical kings centuries past were far more simplistic. Oddly the Spanish language does not try to complicate various meanings of the same sound by several different spellings as we often hear here makes it most difficult for them and others to learn English language. 

  • 10/25 10:01am (1) 2.4v is the scope trigger level, pin 60 is shown at +5vdc. Good that web page zoom is working again can now see EXL but still pin 60 should never be +5v level if the MCU only difference is it has embedded encryption.

    X11-header (XL) and no schematic (EXL) evaluation kit PDF. Though table 2-4 is the same (XL/EXL) X11-headers. Pin 60 is only +5 tolerant for VBUS input from USB port, CAN1 is shown as TX output. Seemingly pin 60 should only be 3v3 level when alternate CAN1 is configured.  

  • Hi All,  sorry for the late reply as it was a long holiday here in my country and hence, I was away from the oscilloscope.  Anyways I am able to reproduce what Charles have observed. My findings are as below:

    Case 1: When the program is executed WITHOUT external loopback, Tx goes high to 3V.

    Case2:  When the program is executed WITH external loopback, I am able to see CAN transmission.

    Is this behaviour expected ? Attached the relevent screen shots.

    However this seems to only works with one of my launchpad. For the other 129EXL launchpad, the CAN1_Tx seems to be high at 5V always. And ISR seems to be only triggered  when it is in external loopback configuration for this particular launchpad. Is this behaviour may be due to the TARGET_VBUS that BP101 has pointed out ? How can I confirm this, or debug this issue ? (attached also the terminal output for CANStatusGet). Also to be noted is that by probing to CAN1_Tx alone (without GND), I am seeing some square like noisy waves. Could this be CAN signal? (attached also this scope cap).

    P.S1:CAN0 seems to be not working with both my launchpads (Let me DOUBLE & TRIPLE check before confirming it here).

    P.S2: Good to know the ninja code is working fine and I hope camper will forgive me for still using the ninja code since the well tested vendor code is also producing the same outcome in this case.

  • Hi,

      Glad that you are making some progress. 

    Gowtham said:

    Case 1: When the program is executed WITHOUT external loopback, Tx goes high to 3V.

    Case2:  When the program is executed WITH external loopback, I am able to see CAN transmission.

    Yes, I think this is expected. Without the loopback the RX input just stays high. The CAN controller will immediately detects this is a bit-0 error.

    Gowtham said:
    However this seems to only works with one of my launchpad. For the other 129EXL launchpad, the CAN1_Tx seems to be high at 5V always

    Are these two boards the same 129EXL board? Please also check all jumpers if they have the same settings. I assume for the one with the TX stuck at 5V you are also in external loopback, right? Can you show a scope shot where it stays on 5V? Can you also probe the state of PD6? If you force it low, will you see a difference on the TX? When the PD6 is high, it enables the switch to supply 5V power onto TARGET_VBUS. 

    Gowtham said:
    Also to be noted is that by probing to CAN1_Tx alone (without GND), I am seeing some square like noisy waves. Could this be CAN signal?

      What is the third scope shot with the noise? Is this from the good board that you were showing in the second shot or the bad board which is stuck 5V? In your second shot the signal was quite clean. I'm confused. Which board is it? Is this with the transceiver connected or not? In you scope can set the trigger mode to Single? 

      

  • Hi Charles,

    Thank you so much for your help so far. I am glad too.

    Charles Tsai said:

    Are these two boards the same 129EXL board? Please also check all jumpers if they have the same settings. I assume for the one with the TX stuck at 5V you are also in external loopback, right? Can you show a scope shot where it stays on 5V? Can you also probe the state of PD6? If you force it low, will you see a difference on the TX? When the PD6 is high, it enables the switch to supply 5V power onto TARGET_VBUS.

    Yes. they are the same. The jumpers are in default setting. Yes I tested them both in external loopback configuration without the transcievers ( directly connected to oscilloscope). Initially Tx is high at 5V, but the very moment I touch PD6 with the oscilloscope's probe, Tx becomes low at 0V. Again it becomes high at 5V once the probe is removed from PD6. (PD6 remains low).

    The board with the blue jumper and jumper wires is not faulty:

    When Tx is at high at 5V (channel 1 is tx, channel 2 is PD6), PD6 is not connected to probe here :

    Tx goes low when pd6 is connected :

    None of this occurs with my other launchpad. The other launchpad works fine regardless if the probe is connected to PD6 or not connected. (PD6 remains low). Wierd.

    Socpe cap of the working launchpad :

    Btw could you share me the link to the 129EXL's schematics ?

  • Gowtham said:
    Initially Tx is high at 5V, but the very moment I touch PD6 with the oscilloscope's probe, Tx becomes low at 0V. Again it becomes high at 5V once the probe is removed from PD6. (PD6 remains low).

    Hi Gowtham,

    All rested from long holiday and bam you find the issue is related to PD6 seemingly not controlling EN2. Perhaps it is time to ring out PD6 trace from MCU pin over to X11 header and back to U4. I suspect a VIA is not plated all the way through so don't be afraid to *** the via rings with probe tip to confirm a no ring resistance typically over 300 ohms.

    When or if you find an open via my trick is to scrape via ring masking (top/bottom) PCB then first try to solder fill the hole using plenty of flux/heat with 5mm iron tip or less. Next method use very fine wire wrap of course stripping the insulation shove it down via hole with due force with fine tip needle nose pliers then apply ample heat flux/solder snip the left over wire tips.

    Please let us know what you find.

  • Hi,

      Can you measure the voltage at TP4 and if possible measure the EN2 input to the TPS2052B. 

      Do you have a third board? Rather than debugging the questionable board, I will suggest you come back later to this questionable board and first focus on the CAN which is your original problem. If you can get the CAN working with a third board then your original issue of not working CAN may somehow relate to the questionable board. 

      The 129EXL and 1294XL have the same schematic. You can find the 1294XL user guide here. Go to section 5 for schematic. 

  • Hi BP101,

    Yea. my holiday mode is ruined.haha. Hmm..ok..where can I find this VIA hole and to find which VIA hole is indeed faulty ? ( I have very little knowledge abt PCB debugging).

    Hi Charles,

    Yea. I can see the difference now between my faulty board n the working board. TP4_working_board = 3.3 V , TP4_faulty_board = 5 V. What can I conclude from this (want to know this for learning sake) ?
    PD6 is 0V for both this board.

    Yea. you are right. I would like to avoid the debugging of the launchpad if it is too complicated as I my main concern now is to make the CAN Bus work in time. I will try to search for another launchpad if available.

  • Hi All,

    Since the CAN1 is not working. I did try external loopback using CAN0. The good news I am not seeing 5V with the faulty launchpad. However the CAN transmission not seem to be working for both my launchpads using CAN0. From the scope cap, the Tx line seem to go high (~3V) when the program is initiated.This leads me to suspect on my code. Please advice. No terminal output at this moment. Due to limited resources, I am working on a method of using a RS232 cable for the UART(terminal). Attached the code.

    Jumper & pin:

    Waveform

    #include <stdbool.h>
    #include <stdint.h>
    #include <math.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_can.h"
    #include "inc/hw_ints.h"
    #include "driverlib/can.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    #include "driverlib/uart.h"
    #include "driverlib/pin_map.h"
    #include "utils/uartstdio.h"
    
    volatile bool errFlag = 0; // transmission error flag
    unsigned int sysClock; // clockspeed in hz
    
    void delay(unsigned int milliseconds) {
        SysCtlDelay((sysClock / 3) * (milliseconds / 1000.0f));
    }
    
    // CAN interrupt handler
    void CANIntHandler(void) {
    
        unsigned long status = CANIntStatus(CAN1_BASE, CAN_INT_STS_CAUSE); // read interrupt status
        UARTprintf("Triggered\n");
        if(status == CAN_INT_INTID_STATUS) { // controller status interrupt
            status = CANStatusGet(CAN1_BASE, CAN_STS_CONTROL); // read back error bits, do something with them?
            errFlag = 1;
            UARTprintf("Triggered1\n");
        } else if(status == 1) { // message object 1
            CANIntClear(CAN1_BASE, 1); // clear interrupt
            errFlag = 0; // clear any error flags
            UARTprintf("Triggered2\n");
        } else { // should never happen
            UARTprintf("Unexpected CAN bus interrupt\n");
            UARTprintf("Error is-- %lu\n",status);
        }
    }
    
    int main(void) {
    
        tCANMsgObject msg; // the CAN message object
        unsigned int msgData; // the message data is four bytes long which we can allocate as an int32
        unsigned char *msgDataPtr = (unsigned char *)&msgData; // make a pointer to msgData so we can access individual bytes
    
        // Run from the PLL at 120 MHz.
        sysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
    
        // Set up debugging UART
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        GPIOPinConfigure(GPIO_PA6_U2RX);
        GPIOPinConfigure(GPIO_PA7_U2TX);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2);
        UARTClockSourceSet(UART2_BASE, UART_CLOCK_PIOSC);
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7);
        UARTStdioConfig(2, 115200, 16000000);
    
        // Set up CAN0
    	//SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    	GPIOPinConfigure(GPIO_PA0_CAN0RX);
        GPIOPinConfigure(GPIO_PA1_CAN0TX);
    	GPIOPinTypeCAN(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
    	CANInit(CAN0_BASE);
    	CANBitRateSet(CAN0_BASE, sysClock, 500000);
        CANIntRegister(CAN0_BASE, CANIntHandler); // use dynamic vector table allocation
        CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
        IntEnable(INT_CAN0);
        CANEnable(CAN0_BASE);
    
        // Set up msg object
        msgData = 0;
        msg.ui32MsgID = 1;
        msg.ui32MsgIDMask = 0;
        msg.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
        msg.ui32MsgLen = sizeof(msgDataPtr);
        msg.pui8MsgData = msgDataPtr;
    
        unsigned int t = 0; // loop counter
       // float freq = 0.3; // frequency scaler
    
        while(1) {
                    msgDataPtr[0] = 0x55;
                    msgDataPtr[1] = 0x55;
                    msgDataPtr[2] = 0x55;
                    msgDataPtr[3] = 0x55;
    
    
            UARTprintf("Sending colour\tr: %d\tg: %d\tb: %d\n", msgDataPtr[0], msgDataPtr[1], msgDataPtr[2]); // write colour to UART for debugging
            CANMessageSet(CAN1_BASE, 1, &msg, MSG_OBJ_TYPE_TX); // send as msg object 1
    
            delay(100); // wait 100ms
    
            if(errFlag) { // check for errors
                UARTprintf("CAN Bus Error\n");
            }
    
            t++; // overflow is fine
        }
    
        return 0;
    }
    

  • You jumper setting is correct in order to bring out CAN0 on PA0 and PA1. Did you connect the PA0 and PA1 as a loopback? Did you run the TivaWare Example for CAN0? I ran it and was able to see the same waveform as before using CAN1.

    //*****************************************************************************
    //
    // simple_tx.c - Example demonstrating simple CAN message transmission.
    //
    // Copyright (c) 2010-2017 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    //
    //   Redistribution and use in source and binary forms, with or without
    //   modification, are permitted provided that the following conditions
    //   are met:
    //
    //   Redistributions of source code must retain the above copyright
    //   notice, this list of conditions and the following disclaimer.
    //
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the
    //   documentation and/or other materials provided with the
    //   distribution.
    //
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    //
    // This is part of revision 2.1.4.178 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_can.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/can.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    //*****************************************************************************
    //
    //! \addtogroup can_examples_list
    //! <h1>Simple CAN TX (simple_tx)</h1>
    //!
    //! This example shows the basic setup of CAN in order to transmit 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.  A CAN interrupt
    //! handler is used to confirm message transmission and count the number of
    //! messages that have been sent.
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - CAN0 peripheral
    //! - GPIO Port B peripheral (for CAN0 pins)
    //! - CAN0RX - PB4
    //! - CAN0TX - PB5
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of CAN.
    //! - GPIO port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - INT_CAN0 - CANIntHandler
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // A counter that keeps track of the number of times the TX interrupt has
    // occurred, which should match the number of TX messages that were sent.
    //
    //*****************************************************************************
    volatile uint32_t g_ui32MsgCount = 0;
    
    //*****************************************************************************
    //
    // A flag to indicate that some transmission error occurred.
    //
    //*****************************************************************************
    volatile bool g_bErrFlag = 0;
    
    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
    
        //
        // Enable UART0 so that we can configure the clock.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    
        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    
        //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Initialize the UART for console I/O.
        //
        UARTStdioConfig(0, 115200, 16000000);
    }
    
    //*****************************************************************************
    //
    // This function provides a 1 second delay using a simple polling method.
    //
    //*****************************************************************************
    void
    SimpleDelay(void)
    {
        //
        // Delay cycles for 1 second
        //
        SysCtlDelay(16000000 / 3);
    }
    
    //*****************************************************************************
    //
    // This function is the interrupt handler for the CAN peripheral.  It checks
    // for the cause of the interrupt, and maintains a count of all messages that
    // have been transmitted.
    //
    //*****************************************************************************
    void
    CANIntHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Read the CAN interrupt status to find the cause of the interrupt
        //
        ui32Status = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
    
        //
        // If the cause is a controller status interrupt, then get the status
        //
        if(ui32Status == CAN_INT_INTID_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.  If the
            // CAN peripheral is not connected to a CAN bus with other CAN devices
            // present, then errors will occur and will be indicated in the
            // controller status.
            //
            ui32Status = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);
    
            //
            // Set a flag to indicate some errors may have occurred.
            //
            g_bErrFlag = 1;
        }
    
        //
        // Check if the cause is message object 1, which what we are using for
        // sending messages.
        //
        else if(ui32Status == 1)
        {
            //
            // Getting to this point means that the TX interrupt occurred on
            // message object 1, and the message TX is complete.  Clear the
            // message object interrupt.
            //
            CANIntClear(CAN0_BASE, 1);
    
            //
            // Increment a counter to keep track of how many messages have been
            // sent.  In a real application this could be used to set flags to
            // indicate when a message is sent.
            //
            g_ui32MsgCount++;
    
            //
            // Since the message was sent, clear any error flags.
            //
            g_bErrFlag = 0;
        }
    
        //
        // Otherwise, something unexpected caused the interrupt.  This should
        // never happen.
        //
        else
        {
            //
            // Spurious interrupt handling can go here.
            //
        }
    }
    
    //*****************************************************************************
    //
    // Configure the CAN and enter a loop to transmit periodic CAN messages.
    //
    //*****************************************************************************
    int
    main(void)
    {
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        uint32_t ui32SysClock;
    #endif
    
        tCANMsgObject sCANMessage;
        uint32_t ui32MsgData;
        uint8_t *pui8MsgData;
    
        pui8MsgData = (uint8_t *)&ui32MsgData;
    
        //
        // Set the clocking to run directly from the external crystal/oscillator.
        // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
        // crystal on your board.
        //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN |SYSCTL_USE_OSC), 25000000);
    #else
        SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);
    #endif
    
        //
        // Set up the serial console to use for displaying messages.  This is
        // just for this example program and is not needed for CAN operation.
        //
        InitConsole();
    
        //
        // For this example CAN0 is used with RX and TX pins on port B4 and B5.
        // The actual port and pins used may be different on your part, consult
        // the data sheet for more information.
        // GPIO port B needs to be enabled so these pins can be used.
        // TODO: change this to whichever GPIO port you are using
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
        //
        // Configure the GPIO pin muxing to select CAN0 functions for these pins.
        // This step selects which alternate function is available for these pins.
        // This is necessary if your part supports GPIO pin function muxing.
        // Consult the data sheet to see which functions are allocated per pin.
        // TODO: change this to select the port/pin you are using
        //
        GPIOPinConfigure(GPIO_PA0_CAN0RX);
        GPIOPinConfigure(GPIO_PA1_CAN0TX);
    
        //
        // Enable the alternate function on the GPIO pins.  The above step selects
        // which alternate function is available.  This step actually enables the
        // alternate function instead of GPIO for these pins.
        // TODO: change this to match the port/pin you are using
        //
        GPIOPinTypeCAN(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // The GPIO port and pins have been set up for CAN.  The CAN peripheral
        // must be enabled.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
    
        //
        // Initialize the CAN controller
        //
        CANInit(CAN0_BASE);
    
        //
        // Set up the bit rate for the CAN bus.  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.
        // In this example, the CAN bus is set to 500 kHz.  In the function below,
        // the call to SysCtlClockGet() or ui32SysClock is used to determine the
        // clock rate that is used for clocking the CAN peripheral.  This can be
        // replaced with a  fixed value if you know the value of the system clock,
        // saving the extra function call.  For some parts, the CAN peripheral is
        // clocked by a fixed 8 MHz regardless of the system clock in which case
        // the call to SysCtlClockGet() or ui32SysClock should be replaced with
        // 8000000.  Consult the data sheet for more information about CAN
        // peripheral clocking.
        //
    #if defined(TARGET_IS_TM4C129_RA0) ||                                         \
        defined(TARGET_IS_TM4C129_RA1) ||                                         \
        defined(TARGET_IS_TM4C129_RA2)
        CANBitRateSet(CAN0_BASE, ui32SysClock, 500000);
    #else
        CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000);
    #endif
    
        //
        // Enable interrupts on the CAN peripheral.  This example uses static
        // allocation of interrupt handlers which means the name of the handler
        // is in the vector table of startup code.  If you want to use dynamic
        // allocation of the vector table, then you must also call CANIntRegister()
        // here.
        //
        // CANIntRegister(CAN0_BASE, CANIntHandler); // if using dynamic vectors
        //
        CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    
        //
        // Enable the CAN interrupt on the processor (NVIC).
        //
        IntEnable(INT_CAN0);
    
        //
        // Enable the CAN for operation.
        //
        CANEnable(CAN0_BASE);
    
        //
        // Initialize the message object that will be used for sending CAN
        // messages.  The message will be 4 bytes that will contain an incrementing
        // value.  Initially it will be set to 0.
        //
        ui32MsgData = 0;
        sCANMessage.ui32MsgID = 1;
        sCANMessage.ui32MsgIDMask = 0;
        sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
        sCANMessage.ui32MsgLen = sizeof(pui8MsgData);
        sCANMessage.pui8MsgData = pui8MsgData;
    
        //
        // 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 uint32_t
        // and incremented by one each time.
        //
        while(1)
        {
            //
            // Print a message to the console showing the message count and the
            // contents of the message being sent.
            //
    /*        UARTprintf("Sending msg: 0x%02X %02X %02X %02X",
                       pui8MsgData[0], pui8MsgData[1], pui8MsgData[2],
                       pui8MsgData[3]); */
            ui32MsgData = 0x55555555;
    
            //
            // 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.
            //
            CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX);
    
            //
            // Now wait 1 second before continuing
            //
            SimpleDelay();
    
            //
            // Check the error flag to see if errors occurred
            //
            if(g_bErrFlag)
            {
    //            UARTprintf(" error - cable connected?\n");
            	while(1);
            }
            else
            {
                //
                // If no errors then print the count of message sent
                //
    //            UARTprintf(" total count = %u\n", g_ui32MsgCount);
            }
    
            //
            // Increment the value in the message data.
            //
            //ui32MsgData++;
        }
    
        //
        // Return no errors
        //
        return(0);
    }