Hello NXP Support,
Currently I am working on NXP KW45B41Z-EVK board. My goal is to transmit CAN Frames from the BLE board. I have tried using SDK examples, but that dosen't provide direct interface with CAN.
I am not able transmit CAN frames. FYI I am using Technica CAN Capture Module.
Looking forward for your prompt assitance.
So, I have developed a custom application, below is the code for your reference:
#include "fsl_debug_console.h"
#include "fsl_flexcan.h"
#include "board.h"
#include "app.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Fix MISRA_C-2012 Rule 17.7. */
#define LOG_INFO (void)PRINTF
#ifndef USE_CANFD
#define USE_CANFD (1)
#endif
#ifndef EXAMPLE_CAN_BIT_RATE
#define EXAMPLE_CAN_BIT_RATE (500000U)
#endif
#ifndef EXAMPLE_CAN_BIT_RATE_FD
#define EXAMPLE_CAN_BIT_RATE_FD (2000000U)
#endif
#define USE_PHY_TJA1152 (1)
#if (defined(USE_CANFD) && USE_CANFD)
/*
* DWORD_IN_MB DLC BYTES_IN_MB Maximum MBs
* 2 8 kFLEXCAN_8BperMB 32(1 RAM block) 64(2 RAM block) 96(3 RAM block)
* 4 10 kFLEXCAN_16BperMB 21(1 RAM block) 42(2 RAM block) 63(3 RAM block)
* 8 13 kFLEXCAN_32BperMB 12(1 RAM block) 24(2 RAM block) 36(3 RAM block)
* 16 15 kFLEXCAN_64BperMB 7(1 RAM block) 14(2 RAM block) 21(3 RAM block)
*
* Dword in each message buffer, Length of data in bytes, Payload size must align,
* and the Message Buffers are limited corresponding to each payload configuration:
*/
#define DWORD_IN_MB (16)
#define DLC (15)
#define BYTES_IN_MB kFLEXCAN_64BperMB
#else
#define DLC (8)
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
flexcan_handle_t flexcanHandle;
volatile bool txComplete = false;
flexcan_mb_transfer_t txXfer;
#if (defined(USE_CANFD) && USE_CANFD)
flexcan_fd_frame_t frame;
#else
flexcan_frame_t frame;
#endif
static const uint32_t kFlexcanTxId = 0x123U;
#if (defined(USE_CANFD) && USE_CANFD)
static const uint8_t kPayloadSize = 64U;
static const uint8_t kFrameLength = (uint8_t)DLC;
#else
static const uint8_t kPayloadSize = 8U;
static const uint8_t kFrameLength = (uint8_t)DLC;
#endif
/*******************************************************************************
* Code
******************************************************************************/
/*!
* @brief CAN transceiver configuration function
*/
static void FLEXCAN_PHY_Config(void)
{
/* Always ensure the transceiver standby pin is driven. */
GPIO_PortSet(EXAMPLE_STB_RGPIO, 1u << EXAMPLE_STB_RGPIO_PIN);
#if (defined(USE_PHY_TJA1152) && USE_PHY_TJA1152)
/* Initialize TJA1152. */
/* STB=H, configuration CAN messages are expected from the local host via TXD pin. */
/* Classical CAN messages with standard identifier 0x555 must be transmitted
* by the local host controller until acknowledged by the TJA1152 for
* automatic bit rate detection. Do not set frame.brs = 1U to keep nominal
* bit rate in CANFD frame data phase. */
frame.id = FLEXCAN_ID_STD(0x555);
frame.format = (uint8_t)kFLEXCAN_FrameFormatStandard;
frame.type = (uint8_t)kFLEXCAN_FrameTypeData;
frame.length = 0U;
txXfer.mbIdx = (uint8_t)TX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) && USE_CANFD)
txXfer.framefd = &frame;
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#else
txXfer.frame = &frame;
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
/* Configuration of spoofing protection. */
/* Add 0x321 and 0x123 to Transmission Whitelist. */
frame.id = FLEXCAN_ID_EXT(0x18DA00F1);
frame.format = (uint8_t)kFLEXCAN_FrameFormatExtend;
frame.type = (uint8_t)kFLEXCAN_FrameTypeData;
frame.length = 6U;
#if (defined(USE_CANFD) && USE_CANFD)
frame.dataWord[0] = CAN_WORD_DATA_BYTE_0(0x10) | CAN_WORD_DATA_BYTE_1(0x00) | CAN_WORD_DATA_BYTE_2(0x33) |
CAN_WORD_DATA_BYTE_3(0x21);
frame.dataWord[1] = CAN_WORD_DATA_BYTE_4(0x11) | CAN_WORD_DATA_BYTE_5(0x23);
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#else
frame.dataWord0 = CAN_WORD0_DATA_BYTE_0(0x10) | CAN_WORD0_DATA_BYTE_1(0x00) | CAN_WORD0_DATA_BYTE_2(0x33) |
CAN_WORD0_DATA_BYTE_3(0x21);
frame.dataWord1 = CAN_WORD1_DATA_BYTE_4(0x11) | CAN_WORD1_DATA_BYTE_5(0x23);
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
/* Configuration of command message ID. */
/* Reconfiguration is only accepted locally. Keep CONFIG_ID as default value 0x18DA00F1. */
frame.length = 5U;
#if (defined(USE_CANFD) && USE_CANFD)
frame.dataWord[0] = CAN_WORD_DATA_BYTE_0(0x60) | CAN_WORD_DATA_BYTE_1(0x98) | CAN_WORD_DATA_BYTE_2(0xDA) |
CAN_WORD_DATA_BYTE_3(0x00);
frame.dataWord[1] = CAN_WORD_DATA_BYTE_4(0xF1);
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#else
frame.dataWord0 = CAN_WORD0_DATA_BYTE_0(0x60) | CAN_WORD0_DATA_BYTE_1(0x98) | CAN_WORD0_DATA_BYTE_2(0xDA) |
CAN_WORD0_DATA_BYTE_3(0x00);
frame.dataWord1 = CAN_WORD1_DATA_BYTE_4(0xF1);
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
/* Leaving configuration mode. */
/* Configuration into volatile memory only. */
frame.length = 8U;
#if (defined(USE_CANFD) && USE_CANFD)
frame.dataWord[0] = CAN_WORD_DATA_BYTE_0(0x71) | CAN_WORD_DATA_BYTE_1(0x02) | CAN_WORD_DATA_BYTE_2(0x03) |
CAN_WORD_DATA_BYTE_3(0x04);
frame.dataWord[1] = CAN_WORD_DATA_BYTE_4(0x05) | CAN_WORD_DATA_BYTE_5(0x06) | CAN_WORD_DATA_BYTE_6(0x07) |
CAN_WORD_DATA_BYTE_7(0x08);
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#else
frame.dataWord0 = CAN_WORD0_DATA_BYTE_0(0x71) | CAN_WORD0_DATA_BYTE_1(0x02) | CAN_WORD0_DATA_BYTE_2(0x03) |
CAN_WORD0_DATA_BYTE_3(0x04);
frame.dataWord1 = CAN_WORD1_DATA_BYTE_4(0x05) | CAN_WORD1_DATA_BYTE_5(0x06) | CAN_WORD1_DATA_BYTE_6(0x07) |
CAN_WORD1_DATA_BYTE_7(0x08);
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
LOG_INFO("Initialize TJA1152 successfully!\r\n\r\n");
/* Initialize TJA1152 end. */
#endif
/* Release transceiver standby so CANH/CANL are driven. */
GPIO_PortClear(EXAMPLE_STB_RGPIO, 1u << EXAMPLE_STB_RGPIO_PIN);
}
/*!
* @brief FlexCAN Call Back function
*/
static FLEXCAN_CALLBACK(flexcan_callback)
{
LOG_INFO("status: %d \n", status);
switch (status)
{
case kStatus_FLEXCAN_TxIdle:
if (TX_MESSAGE_BUFFER_NUM == result)
{
txComplete = true;
}
break;
default:
break;
}
}
/*!
* @brief Main function
*/
int main(void)
{
flexcan_config_t flexcanConfig;
uint8_t txCounter = 0U;
/* Initialize board hardware. */
BOARD_InitHardware();
LOG_INFO("********* FLEXCAN Continuous TX EXAMPLE *********\r\n");
LOG_INFO(" Message format: Standard (11 bit id)\r\n");
#if (defined(USE_CANFD) && USE_CANFD)
LOG_INFO(" Frame type : CAN FD with BRS\r\n");
LOG_INFO(" Nominal/Data bit rates: %u / %u bps\r\n", EXAMPLE_CAN_BIT_RATE, EXAMPLE_CAN_BIT_RATE_FD);
LOG_INFO(" Payload length : %u bytes\r\n", kPayloadSize);
#else
LOG_INFO(" Frame type : Classical CAN\r\n");
LOG_INFO(" Bit rate : %u bps\r\n", EXAMPLE_CAN_BIT_RATE);
LOG_INFO(" Payload length : %u bytes\r\n", kPayloadSize);
#endif
LOG_INFO(" Message buffer %d used for Tx.\r\n", TX_MESSAGE_BUFFER_NUM);
LOG_INFO(" Interrupt Mode: Enabled\r\n");
LOG_INFO(" Operation Mode: Continuous transmit\r\n");
LOG_INFO("*********************************************\r\n\r\n");
LOG_INFO("Starting continuous CAN transmissions on ID 0x%3x\r\n\r\n", kFlexcanTxId);
/* Get FlexCAN module default Configuration. */
/*
* flexcanConfig.clkSrc = kFLEXCAN_ClkSrc0;
* flexcanConfig.bitRate = 1000000U;
* flexcanConfig.bitRateFD = 2000000U;
* flexcanConfig.maxMbNum = 16;
* flexcanConfig.enableLoopBack = false;
* flexcanConfig.enableSelfWakeup = false;
* flexcanConfig.enableIndividMask = false;
* flexcanConfig.disableSelfReception = false;
* flexcanConfig.enableListenOnlyMode = false;
* flexcanConfig.enableDoze = false;
*/
FLEXCAN_GetDefaultConfig(&flexcanConfig);
flexcanConfig.bitRate = EXAMPLE_CAN_BIT_RATE;
flexcanConfig.disableSelfReception = true;
#if (defined(USE_CANFD) && USE_CANFD)
flexcanConfig.bitRateFD = EXAMPLE_CAN_BIT_RATE_FD;
#endif
#if defined(EXAMPLE_CAN_CLK_SOURCE)
flexcanConfig.clksrc=EXAMPLE_CAN_CLK_SOURCE;
#endif
/* If special quantum setting is needed, set the timing parameters. */
#if (defined(SET_CAN_QUANTUM) && SET_CAN_QUANTUM)
flexcanConfig.timingConfig.phaseSeg1 = PSEG1;
flexcanConfig.timingConfig.phaseSeg2 = PSEG2;
flexcanConfig.timingConfig.propSeg = PROPSEG;
#if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
flexcanConfig.timingConfig.fphaseSeg1 = FPSEG1;
flexcanConfig.timingConfig.fphaseSeg2 = FPSEG2;
flexcanConfig.timingConfig.fpropSeg = FPROPSEG;
#endif
#endif
#if (defined(USE_IMPROVED_TIMING_CONFIG) && USE_IMPROVED_TIMING_CONFIG)
flexcan_timing_config_t timing_config;
memset(&timing_config, 0, sizeof(flexcan_timing_config_t));
#if (defined(USE_CANFD) && USE_CANFD)
if (FLEXCAN_FDCalculateImprovedTimingValues(EXAMPLE_CAN, flexcanConfig.bitRate, flexcanConfig.bitRateFD,
EXAMPLE_CAN_CLK_FREQ, &timing_config))
{
/* Update the improved timing configuration*/
memcpy(&(flexcanConfig.timingConfig), &timing_config, sizeof(flexcan_timing_config_t));
}
else
{
LOG_INFO("No found Improved Timing Configuration. Just used default configuration\r\n\r\n");
}
#else
if (FLEXCAN_CalculateImprovedTimingValues(EXAMPLE_CAN, flexcanConfig.bitRate, EXAMPLE_CAN_CLK_FREQ, &timing_config))
{
/* Update the improved timing configuration*/
memcpy(&(flexcanConfig.timingConfig), &timing_config, sizeof(flexcan_timing_config_t));
}
else
{
LOG_INFO("No found Improved Timing Configuration. Just used default configuration\r\n\r\n");
}
#endif
#endif
#if (defined(USE_CANFD) && USE_CANFD)
FLEXCAN_FDInit(EXAMPLE_CAN, &flexcanConfig, EXAMPLE_CAN_CLK_FREQ, BYTES_IN_MB, true);
#else
FLEXCAN_Init(EXAMPLE_CAN, &flexcanConfig, EXAMPLE_CAN_CLK_FREQ);
#endif
/* Create FlexCAN handle structure and set call back function. */
FLEXCAN_TransferCreateHandle(EXAMPLE_CAN, &flexcanHandle, flexcan_callback, NULL);
/* Setup Tx Message Buffer. */
#if (defined(USE_CANFD) && USE_CANFD)
FLEXCAN_SetFDTxMbConfig(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, true);
#else
FLEXCAN_SetTxMbConfig(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, true);
#endif
/* Configure CAN transceiver */
FLEXCAN_PHY_Config();
while (true)
{
frame.id = FLEXCAN_ID_STD(kFlexcanTxId);
frame.format = (uint8_t)kFLEXCAN_FrameFormatStandard;
frame.type = (uint8_t)kFLEXCAN_FrameTypeData;
frame.length = kFrameLength;
#if (defined(USE_CANFD) && USE_CANFD)
frame.brs = 1U;
frame.edl = 1U;
for (uint8_t wordIdx = 0U; wordIdx < DWORD_IN_MB; wordIdx++)
{
uint8_t baseValue = (uint8_t)(wordIdx * 4U);
frame.dataWord[wordIdx] = CAN_WORD_DATA_BYTE_0((uint32_t)txCounter + baseValue) |
CAN_WORD_DATA_BYTE_1(0x55U + baseValue) |
CAN_WORD_DATA_BYTE_2(0xAAU + baseValue) |
CAN_WORD_DATA_BYTE_3(0xFFU - baseValue);
}
#else
frame.dataWord0 = CAN_WORD0_DATA_BYTE_0(txCounter) | CAN_WORD0_DATA_BYTE_1(0x55U) |
CAN_WORD0_DATA_BYTE_2(0xAAU) | CAN_WORD0_DATA_BYTE_3(0xFFU);
frame.dataWord1 = CAN_WORD1_DATA_BYTE_4(0x11U) | CAN_WORD1_DATA_BYTE_5(0x22U) |
CAN_WORD1_DATA_BYTE_6(0x33U) | CAN_WORD1_DATA_BYTE_7(0x44U);
#endif
txXfer.mbIdx = (uint8_t)TX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) && USE_CANFD)
txXfer.framefd = &frame;
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#else
txXfer.frame = &frame;
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
txCounter++;
}
}