AnsweredAssumed Answered

HOW TO USE FLEXCAN IN I.MX RT 1052

Question asked by 宇辉 杨 on Aug 7, 2018

The official SDK FLEXCAN examples does not work properly

 

/*********main.c**********/

#include "fsl_debug_console.h"

#include "board.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "bsp_flexcan.h"

 

/*******************************************************************
* Prototypes
*******************************************************************/
uint8_t cnt=0;
uint8_t canbuf[8];
uint8_t rx_canbuf[8];
uint8_t res;

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


int main(void)
{

BOARD_ConfigMPU();

BOARD_InitPins();

BOARD_BootClockRUN();
BOARD_InitDebugConsole();

PRINTF("\r\n");
PRINTF("CPU: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_CpuClk));
PRINTF("AHB: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_AhbClk));
PRINTF("SEMC: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SemcClk));
PRINTF("SYSPLL: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllClk));
PRINTF("SYSPLLPFD0: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllPfd0Clk));
PRINTF("SYSPLLPFD1: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllPfd1Clk));
PRINTF("SYSPLLPFD2: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllPfd2Clk));
PRINTF("SYSPLLPFD3: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllPfd3Clk));


uint8_t i=0,j=0;
flexcanInit();
while(1)
{
res=0;
for(i=0;i<8;i++)
{
canbuf[i]=cnt+i;
}
res=CAN2_Send_Msg(canbuf,8);
if(!res)
PRINTF("OK\r\n");
else
PRINTF("False\r\n");

res=CAN2_Receive_Msg(rx_canbuf);
if(res)
{
PRINTF("\r\n");
for(i=0;i<res;i++)
PRINTF("%x",rx_canbuf[i]);
PRINTF("\r\n");
}
}

}

 

/***********bsp_flexcan.c*********/

 

 

#include "fsl_iomuxc.h"
#include "fsl_gpio.h"
#include "bsp_flexcan.h"
#include "fsl_debug_console.h"
#include "clock_config.h"
#include "pin_mux.h"

/* Select 80M clock divided by USB1 PLL (480 MHz) as master flexcan clock source */
#define FLEXCAN_CLOCK_SOURCE_SELECT (2U)
/* Clock divider for master flexcan clock source */
#define FLEXCAN_CLOCK_SOURCE_DIVIDER (3U)
#define CAN_CLK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 6) / (FLEXCAN_CLOCK_SOURCE_DIVIDER + 1U))
#define RX_MESSAGE_BUFFER_NUM (9)
#define TX_MESSAGE_BUFFER_NUM (8)
#define TS_CAN CAN2

flexcan_handle_t flexcanHandle;
flexcan_frame_t frame,can2_rxframe;
uint32_t txIdentifier;
uint32_t rxIdentifier;
volatile bool txComplete = false;
volatile bool rxComplete = false;
flexcan_mb_transfer_t txXfer, rxXfer;

void flexcanInit(void)
{
flexcan_config_t flexcanConfig;
flexcan_rx_mb_config_t mbConfig;

txIdentifier = 0x123;
rxIdentifier = 0x123;
CLOCK_SetMux(kCLOCK_CanMux, FLEXCAN_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_CanDiv, FLEXCAN_CLOCK_SOURCE_DIVIDER);
/* Get FlexCAN module default Configuration. */
/*
* flexcanConfig.clkSrc = kFLEXCAN_ClkSrcOsc;
* flexcanConfig.baudRate = 1000000U;
* flexcanConfig.maxMbNum = 16;
* flexcanConfig.enableLoopBack = false;
* flexcanConfig.enableSelfWakeup = false;
* flexcanConfig.enableIndividMask = false;
* flexcanConfig.enableDoze = false;
*/
FLEXCAN_GetDefaultConfig(&flexcanConfig);
#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE
flexcanConfig.clkSrc = kFLEXCAN_ClkSrcPeri;
#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */
#if (defined(SET_CAN_QUANTUM) && SET_CAN_QUANTUM)
flexcanConfig.timingConfig.phaseSeg1 = PSEG1;
flexcanConfig.timingConfig.phaseSeg2 = PSEG2;
flexcanConfig.timingConfig.propSeg = PROPSEG;
#endif
flexcanConfig.baudRate=500000U;
//flexcanConfig.enableLoopBack = true;

FLEXCAN_Init(TS_CAN, &flexcanConfig, CAN_CLK_FREQ);
FLEXCAN_EnableMbInterrupts(TS_CAN,1<<RX_MESSAGE_BUFFER_NUM); //ʹÄÜRXÏûÏ¢»º³åÖжÏ
//FLEXCAN_TransferCreateHandle(CAN1, &flexcanHandle, flexcan_callback, NULL);
EnableIRQ(CAN2_IRQn);
FLEXCAN_SetRxMbGlobalMask(TS_CAN, FLEXCAN_RX_MB_STD_MASK(rxIdentifier, 0, 0));
mbConfig.format = kFLEXCAN_FrameFormatStandard;
mbConfig.type = kFLEXCAN_FrameTypeData;
mbConfig.id = FLEXCAN_ID_STD(rxIdentifier);

FLEXCAN_SetRxMbConfig(TS_CAN, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);
FLEXCAN_SetTxMbConfig(TS_CAN, TX_MESSAGE_BUFFER_NUM, true);
// while(1)
// {
// frame.id = FLEXCAN_ID_STD(rxIdentifier);
// frame.format = kFLEXCAN_FrameFormatStandard;
// frame.type = kFLEXCAN_FrameTypeData;
// frame.length = 2;
// frame.dataByte0=0x64;
// frame.dataByte1=0x00;
// txXfer.frame = &frame;
// txXfer.mbIdx = TX_MESSAGE_BUFFER_NUM;
// FLEXCAN_TransferSendNonBlocking(TS_CAN, &flexcanHandle, &txXfer);//SendMsg
// PRINTF("TEST1\r\n\r\n");
// while (!txComplete)
// {
// };
// txComplete = false;
// PRINTF("Start to Wait data from Node A\r\n\r\n");
// rxXfer.mbIdx = RX_MESSAGE_BUFFER_NUM;
// rxXfer.frame = &frame;
// FLEXCAN_TransferReceiveNonBlocking(TS_CAN, &flexcanHandle, &rxXfer);
// while (!rxComplete)
// {
// };
// rxComplete = false;
// PRINTF("Rx MB ID: 0x%3x, Rx MB data: 0x%x\r\n", frame.id >> CAN_ID_STD_SHIFT, frame.dataByte0);
// frame.id = FLEXCAN_ID_EXT(0x0ff46f00);
// txXfer.mbIdx = TX_MESSAGE_BUFFER_NUM;
// }

}

static void flexcan_callback(CAN_Type *base, flexcan_handle_t *handle, status_t status, uint32_t result, void *userData)
{
PRINTF("TEST\r\n\r\n");
switch (status)
{
case kStatus_FLEXCAN_RxIdle:
if (RX_MESSAGE_BUFFER_NUM == result)
{
rxComplete = true;
}
break;

case kStatus_FLEXCAN_TxIdle:
if (TX_MESSAGE_BUFFER_NUM == result)
{
txComplete = true;
}
break;

default:
break;
}
}

//CAN2ÖжϷþÎñº¯Êý
void CAN2_IRQHandler(void)
{
if (FLEXCAN_GetMbStatusFlags(TS_CAN,1<<RX_MESSAGE_BUFFER_NUM)) //ÅжÏCAN2µÄRXÐÅÏ¢»º³åÊÇ·ñÊÕµ½Êý¾Ý
{
FLEXCAN_ClearMbStatusFlags(CAN2,1<<RX_MESSAGE_BUFFER_NUM); //Çå³ýÖжϱê־λ
FLEXCAN_ReadRxMb(TS_CAN,RX_MESSAGE_BUFFER_NUM,&can2_rxframe); //¶ÁÈ¡Êý¾Ý
rxComplete=true; //±ê¼Ç¶ÁÈ¡Íê³É
}
__DSB();
}

uint8_t CAN2_Send_Msg(uint8_t* msg,uint8_t len)
{
uint8_t ret=0;

frame.format=kFLEXCAN_FrameFormatStandard; //±ê×¼¸ñʽ
frame.type=kFLEXCAN_FrameTypeData; //Êý¾ÝÖ¡
frame.id=FLEXCAN_ID_STD(0x123); //±ê×¼ID
frame.length=len; //³¤¶È8

//ÉèÖÃÊý¾Ý
frame.dataByte0=msg[0];
frame.dataByte1=msg[1];
frame.dataByte2=msg[2];
frame.dataByte3=msg[3];
frame.dataByte4=msg[4];
frame.dataByte5=msg[5];
frame.dataByte6=msg[6];
frame.dataByte7=msg[7];

if(FLEXCAN_TransferSendBlocking(TS_CAN,TX_MESSAGE_BUFFER_NUM,&frame)==kStatus_Success) ret=0;
else ret=1;

return ret;
}


uint8_t CAN2_Receive_Msg(uint8_t *buf)
{
uint8_t datalen=0;

if(rxComplete==true) 
{
rxComplete=false;

 

buf[0]=can2_rxframe.dataByte0;
buf[1]=can2_rxframe.dataByte1;
buf[2]=can2_rxframe.dataByte2;
buf[3]=can2_rxframe.dataByte3;
buf[4]=can2_rxframe.dataByte4;
buf[5]=can2_rxframe.dataByte5;
buf[6]=can2_rxframe.dataByte6;
buf[7]=can2_rxframe.dataByte7;
datalen=can2_rxframe.length;
}
else
datalen=0;

return datalen;
}

Outcomes