LPC54618_CAN

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC54618_CAN

Jump to solution
1,123 Views
Xiaoyh
Contributor III

///////////////////////////////////////////////////////////////////////////////////////////// 

/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#include "fsl_debug_console.h"
#include "fsl_mcan.h"
#include "board.h"
#include "stdlib.h"

#include "pin_mux.h"
#include <stdbool.h>
/*******************************************************************************
* Definitions
******************************************************************************/
//#define USE_CANFD (1U)
/*
* CAN_DATASIZE DLC BYTES_IN_MB
* 8 8 kMCAN_8ByteDatafield
* 12 9 kMCAN_12ByteDatafield
* 16 10 kMCAN_16ByteDatafield
* 20 11 kMCAN_20ByteDatafield
* 24 12 kMCAN_24ByteDatafield
* 32 13 kMCAN_32ByteDatafield
* 48 14 kMCAN_48ByteDatafield
* 64 15 kMCAN_64ByteDatafield
*
* CAN data size (pay load size), DLC and Bytes in Message buffer must align.
*
*/
#define DLC (15)
#define BYTES_IN_MB kMCAN_64ByteDatafield
/* If not define USE_CANFD or define it 0, CAN_DATASIZE should be 8. */
#define CAN_DATASIZE (8U)
/* If user need to auto execute the improved timming configuration. */
//#define USE_IMPROVED_TIMING_CONFIG (10U)
#define EXAMPLE_MCAN_IRQHandler CAN0_IRQ0_IRQHandler
#define EXAMPLE_MCAN_IRQn CAN0_IRQ0_IRQn
#define EXAMPLE_MCAN CAN0
#define MCAN_CLK_FREQ CLOCK_GetMCanClkFreq(0U)
#define STDID_OFFSET (18U)
#define MSG_RAM_BASE 0x20010000U
#define STD_FILTER_OFS 0x0
#define RX_FIFO0_OFS 0x10U
#define TX_BUFFER_OFS 0x20U
mcan_handle_t mcanHandle;
mcan_buffer_transfer_t txXfer;
mcan_fifo_transfer_t rxXfer;
/*******************************************************************************
* Prototypes
******************************************************************************/

/*******************************************************************************
* Variables
******************************************************************************/
volatile bool rxComplete = false;
volatile bool txComplete = false;
mcan_rx_buffer_frame_t rxFrame;
mcan_tx_buffer_frame_t txFrame;
uint8_t tx_data[CAN_DATASIZE];
uint8_t rx_data[CAN_DATASIZE];

/*******************************************************************************
* Code
******************************************************************************/

//void CAN0_IRQ0_IRQHandler(void)
//{
// MCAN_ClearStatusFlag(EXAMPLE_MCAN, CAN_IR_RF0N_MASK);
// MCAN_ReadRxFifo(EXAMPLE_MCAN, 0, &rxFrame);
// rxComplete = true;
// /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
// exception return operation might vector to incorrect interrupt */
//#if defined __CORTEX_M && (__CORTEX_M == 4U)
// __DSB();
//#endif
//}
static void mcan_callback(CAN_Type *base, mcan_handle_t *handle, status_t status, uint32_t result, void *userData)
{
switch (status)
{
case kStatus_MCAN_RxFifo0Idle:
{
rxComplete = true;
}
break;

case kStatus_MCAN_TxIdle:
{

txComplete = true;
}
break;

default:
break;
}
// MCAN_TransmitCancelRequest(EXAMPLE_MCAN,0);
}

/*!
* @brief Main function
*/
int main(void)
{
mcan_config_t mcanConfig;
mcan_frame_filter_config_t rxFilter;
mcan_std_filter_element_config_t stdFilter;
mcan_rx_fifo_config_t rxFifo0;
mcan_tx_buffer_config_t txBuffer;

/* Initialize board hardware. */
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);

/* Set MCAN clock 180/5=36MHz. */
CLOCK_SetClkDiv(kCLOCK_DivCan0Clk, 5U, true);

BOARD_InitPins();
BOARD_BootClockPLL180M();
BOARD_InitDebugConsole();

PRINTF("\r\n==MCAN loopback functional example -- Start.==\r\n\r\n");

MCAN_GetDefaultConfig(&mcanConfig);
//mcanConfig.enableLoopBackExt = true;
#if (defined(USE_CANFD) && USE_CANFD)
// mcanConfig.enableCanfdNormal = true;
#endif

#if (defined(USE_IMPROVED_TIMING_CONFIG) && USE_IMPROVED_TIMING_CONFIG)
mcan_timing_config_t timing_config;
memset(&timing_config, 0, sizeof(timing_config));
#if (defined(USE_CANFD) && USE_CANFD)
if (MCAN_FDCalculateImprovedTimingValues(mcanConfig.baudRateA, mcanConfig.baudRateD, MCAN_CLK_FREQ, &timing_config))
{
/* Update the improved timing configuration*/
memcpy(&(mcanConfig.timingConfig), &timing_config, sizeof(mcan_timing_config_t));
}
else
{
PRINTF("No found Improved Timing Configuration. use default configuration\r\n\r\n");
}
#else
if (MCAN_CalculateImprovedTimingValues(mcanConfig.baudRateA, MCAN_CLK_FREQ, &timing_config))
{
/* Update the improved timing configuration*/
memcpy(&(mcanConfig.timingConfig), &timing_config, sizeof(mcan_timing_config_t));
}
else
{
PRINTF("No found Improved Timing Configuration. use default configuration\r\n\r\n");
}
#endif
#endif

MCAN_Init(EXAMPLE_MCAN, &mcanConfig, MCAN_CLK_FREQ);
MCAN_TransferCreateHandle(EXAMPLE_MCAN, &mcanHandle, mcan_callback, NULL);
/* Set Message RAM base address and clear to avoid BEU/BEC error. */
MCAN_SetMsgRAMBase(EXAMPLE_MCAN, MSG_RAM_BASE);
uint32_t *p = (uint32_t *)(MSG_RAM_BASE);
memset(p, 0, (8U + CAN_DATASIZE) * sizeof(uint8_t));

/* STD filter config. */
rxFilter.address = STD_FILTER_OFS;
rxFilter.idFormat = kMCAN_FrameIDStandard;
rxFilter.listSize = 1U;
rxFilter.nmFrame = kMCAN_reject0;
rxFilter.remFrame = kMCAN_rejectFrame;
MCAN_SetFilterConfig(EXAMPLE_MCAN, &rxFilter);

stdFilter.sfec = kMCAN_storeinFifo0;
/* Classic filter mode, only filter matching ID. */
stdFilter.sft = kMCAN_classic;
stdFilter.sfid1 = 0x123U;
stdFilter.sfid2 = 0x0U;
MCAN_SetSTDFilterElement(EXAMPLE_MCAN, &rxFilter, &stdFilter, 0);

/* RX fifo0 config. */
rxFifo0.address = RX_FIFO0_OFS;
rxFifo0.elementSize = 1U;
rxFifo0.watermark = 0;
rxFifo0.opmode = kMCAN_FifoBlocking;
rxFifo0.datafieldSize = kMCAN_8ByteDatafield;
#if (defined(USE_CANFD) && USE_CANFD)
rxFifo0.datafieldSize = BYTES_IN_MB;
#endif
MCAN_SetRxFifo0Config(EXAMPLE_MCAN, &rxFifo0);

/* TX buffer config. */
memset(&txBuffer, 0, sizeof(txBuffer));
txBuffer.address = TX_BUFFER_OFS;
txBuffer.dedicatedSize = 1U;
txBuffer.fqSize = 0;
txBuffer.datafieldSize = kMCAN_8ByteDatafield;
// txBuffer.mode = kMCAN_txQueue;
#if (defined(USE_CANFD) && USE_CANFD)
txBuffer.datafieldSize = BYTES_IN_MB;
#endif
MCAN_SetTxBufferConfig(EXAMPLE_MCAN, &txBuffer);

/* Enable RX fifo0 new message interrupt using interrupt line 0. */
// MCAN_EnableInterrupts(EXAMPLE_MCAN, 0, CAN_IE_RF0NE_MASK);
// EnableIRQ(CAN0_IRQ0_IRQn);

/* Enter normal mode. */
MCAN_EnterNormalMode(EXAMPLE_MCAN);

/* Config TX frame data. */
uint8_t cnt = 0;
for (cnt = 0; cnt < CAN_DATASIZE; cnt++)
{
tx_data[cnt] = cnt;
}
txFrame.xtd = kMCAN_FrameIDStandard;
txFrame.rtr = kMCAN_FrameTypeData;
txFrame.fdf = 0;
txFrame.brs = 0;
txFrame.dlc = 8U;
txFrame.id = 0x110U << STDID_OFFSET;
txFrame.data = tx_data;
txFrame.size = CAN_DATASIZE;
#if (defined(USE_CANFD) && USE_CANFD)
txFrame.fdf = 1;
txFrame.brs = 1;
txFrame.dlc = DLC;
#endif
// MCAN_TransferSendBlocking(EXAMPLE_MCAN, 0, &txFrame);

txXfer.frame = &txFrame;
txXfer.bufferIdx = 0;
// while(1){
MCAN_TransferSendNonBlocking(EXAMPLE_MCAN, &mcanHandle, &txXfer);
// }
while (!txComplete){
}
txComplete = false;
rxFrame.size = CAN_DATASIZE;
rxXfer.frame = &rxFrame;
MCAN_TransferReceiveFifoNonBlocking(EXAMPLE_MCAN, 0, &mcanHandle, &rxXfer);
while (!rxComplete)
{
}

// rxFrame.size = CAN_DATASIZE;
// /* After call the API of rMCAN_TransferReceiveFifoNonBlocking success, we can
// * only get a point (rxFrame.data) to the fifo reading entrance.
// * Copy the received frame data from the FIFO by the pointer(rxFrame.data). */
// memcpy(rx_data, rxFrame.data, rxFrame.size);
//
// PRINTF("Received Frame ID: 0x%x\r\n", rxFrame.id >> STDID_OFFSET);
// PRINTF("Received Frame DATA: ");
// cnt = 0;
// while (cnt < rxFrame.size)
// {
// PRINTF("0x%x ", rx_data[cnt++]);
// }
rxComplete = false;

/* After call the API of rMCAN_TransferReceiveFifoNonBlocking success, we can
* only get a point (rxFrame.data) to the fifo reading entrance.
* Copy the received frame data from the FIFO by the pointer(rxFrame.data). */
memcpy(rx_data, rxFrame.data, rxFrame.size);

PRINTF("Received Frame ID: 0x%x\r\n", rxFrame.id >> STDID_OFFSET);
PRINTF("Received Frame DATA: ");

cnt = 0;
while (cnt < rxFrame.size)
{
PRINTF("0x%x ", rx_data[cnt++]);
}
PRINTF("\r\n");
PRINTF("\r\n\r\n==MCAN loopback functional example -- Finish.==\r\n");

while (1)
{
}
}

Question:

I dont not know how to set CAN BUS buadrate to 1MHZ.I use classic CAN.

I have changed the can0 clock frequency to 36 MHZ by use this function CLOCK_SetClkDiv(kCLOCK_DivCan0Clk, 5U, true);” .

when I set can bus buadrate to 500khz,I find that it worked normal,the configuration is

void MCAN_GetDefaultConfig(mcan_config_t *config)
{
/* Assertion. */
assert(NULL != config);

/* Initializes the configure structure to zero. */
(void)memset(config, 0, sizeof(*config));

/* Initialize MCAN Module config struct with default value. */
config->baudRateA = 500000U;
config->baudRateD = 500000U;
config->enableCanfdNormal = false;
config->enableCanfdSwitch = false;
config->enableLoopBackInt = false;
config->enableLoopBackExt = false;
config->enableBusMon = false;
/* Default protocol timing configuration, time quantum is 16. */
config->timingConfig.seg1 = 0x6U;
config->timingConfig.seg2 = 0x3U;
config->timingConfig.rJumpwidth = 0x1U;
#if (defined(FSL_FEATURE_CAN_SUPPORT_CANFD) && FSL_FEATURE_CAN_SUPPORT_CANFD)
config->timingConfig.dataseg1 = 0x16U;
config->timingConfig.dataseg2 = 0xBU;
config->timingConfig.datarJumpwidth = 0xAU;
#endif
}

when I set can bus buadrate to 1000khz1Mhz,unfortunatelysomething I can not predict has happenedit has send data 13 times by  called this function “MCAN_TransferSendNonBlocking(EXAMPLE_MCAN, &mcanHandle, &txXfer);” one timeand the 

“”txComplete” always equal to FALSE, the configuration is:

   

void MCAN_GetDefaultConfig(mcan_config_t *config)
{
/* Assertion. */
assert(NULL != config);

/* Initializes the configure structure to zero. */
(void)memset(config, 0, sizeof(*config));

/* Initialize MCAN Module config struct with default value. */
config->baudRateA = 1000000U;
config->baudRateD = 1000000U;
config->enableCanfdNormal = false;
config->enableCanfdSwitch = false;
config->enableLoopBackInt = false;
config->enableLoopBackExt = false;
config->enableBusMon = false;
/* Default protocol timing configuration, time quantum is 16. */
config->timingConfig.seg1 = 0x6U;
config->timingConfig.seg2 = 0x3U;
config->timingConfig.rJumpwidth = 0x1U;
#if (defined(FSL_FEATURE_CAN_SUPPORT_CANFD) && FSL_FEATURE_CAN_SUPPORT_CANFD)
config->timingConfig.dataseg1 = 0x16U;
config->timingConfig.dataseg2 = 0xBU;
config->timingConfig.datarJumpwidth = 0xAU;
#endif
}

I was use LPC54618 and cantest soft to analyse can bus.

This question has confused a few days,I would appreciate it if it could be resolved.

                                                                                                                           yours yang,

                                                                                                                           thank you

   

 

Labels (1)
0 Kudos
Reply
1 Solution
1,073 Views
Xiaoyh
Contributor III

微信图片_20210318104108.png微信图片_20210318104957.png

 

I used  MCUXpresso configuration tool configure the clock, baud rate,then it can send data normally,but it can not receive,I do not know  what make that happened.

                                                                                                                      thank you

View solution in original post

0 Kudos
Reply
4 Replies
1,107 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello,

First recommend you use the MCUXpresso Configure tool to config the CAN module to 1MHZ to test,

check whether it can work well.

 

Regards,

Alice

0 Kudos
Reply
1,102 Views
Xiaoyh
Contributor III

Thank you for your recommendation, but I am not familiar with the recommended software and do not know how to use it. Is there any other way to solve it.

                                                                                                                             thank you!

    

0 Kudos
Reply
1,092 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello,

Use MCUXpresso configuration tool can just configure the clock, baud rate as your requirement, then it

generate  code automatically , you can compare the code with your code to check whether the code is configured well.

Alice_Yang_0-1615455107620.png

 

 

BR

Alice

0 Kudos
Reply
1,074 Views
Xiaoyh
Contributor III

微信图片_20210318104108.png微信图片_20210318104957.png

 

I used  MCUXpresso configuration tool configure the clock, baud rate,then it can send data normally,but it can not receive,I do not know  what make that happened.

                                                                                                                      thank you

0 Kudos
Reply