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.
Hi,
We confirmed CAN communication using EK-TM4C1294XL as the master and EK-TM4C1294XL as the receiving node. I downloaded the sample code (spna245.zip) according to spna245.pdf, executed [simple_can_tx] and [simple_can_rx] on the receiving side, and confirmed that communication could be performed normally.
https://www.ti.com/lit/an/spna245/spna245.pdf
When using EK-TM4C1294XL as the master and changing the receiving side to EK-TM4C123GXL, or when connecting with our own products (MPU: MSP430FR2353/CAN controller: MCP2518/CAN transceiver: SN65HVD231DP), an ACK error occurs and communication cannot be performed.
BOFF = 0
EWARN = 1
EPASS = 1
RXOK=0
TXOK=0
LEC=0x3 ※ACK Error
The CAN module is the same for the EK-TM4C123GXL, so I believe it should work correctly.
"There are no differences among the CAN modules between Tempest- and Firestorm-class and TM4C129x devices."
https://www.ti.com/lit/an/spma065/spma065.pdf
Can you give me any comments?
Thanks,
Conor
Hi Conor,
You cannot just run the simple_can_rx as is on the EK-TM4C123GXL board because the system clock setup and CAN bit rate setup is different between TM4C129 and TM4C123. Refer to the C:\ti\TivaWare_C_Series-2.2.0.295\examples\peripherals\can\simple_rx.c example for details. As you can see in below highlighted lines where there is a difference on the clock and bit rate setup. You must change accordingly for running the code on EK-TM4C129GXL.
//*****************************************************************************
//
// Configure the CAN and enter a loop to receive 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;
uint8_t pui8MsgData[8];
//
// 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 used 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_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_PB4_CAN0RX);
GPIOPinConfigure(GPIO_PB5_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_4 | GPIO_PIN_5);
//
// 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 a message object to be used for receiving CAN messages with
// any CAN ID. In order to receive any CAN ID, the ID and mask must both
// be set to 0, and the ID filter enabled.
//
sCANMessage.ui32MsgID = 0;
sCANMessage.ui32MsgIDMask = 0;
sCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER;
sCANMessage.ui32MsgLen = 8;
//
// Now load the message object into the CAN peripheral. Once loaded the
// CAN will receive any message on the bus, and an interrupt will occur.
// Use message object 1 for receiving messages (this is not the same as
// the CAN ID which can be any value in this example).
//
CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_RX);
Hi Charles,
OK, I understood. I would like to modify the sample code and test it.
When using EK-TM4C1294XL as the master and changing the receiving side to EK-TM4C123GXL, or when connecting with our own products (MPU: MSP430FR2353/CAN controller: MCP2518/CAN transceiver: SN65HVD231DP), an ACK error occurs and communication cannot be performed.
Please advise if there are any items to check when an ACK error occurs when communicating with our own product.
Thanks,
Conor
Hi Conor,
I will suggest you use a logic analyzer which can interpret CAN packets to understand why the receiving node does not ACK. Please make sure they are the same bit rate configured on both the transmit node and the receiving node.