本文描述的FlexCan主要指的是NXP公司的I.MX RT系列提供的FlexCan低速总线,主要内容是个人根据在调试FlexCan接口时碰到的一些问题而总结出的调试心得,希望对后续使用到此类接口的朋友有所帮助。
1、 FlexCan内部结构
其中比较重要的结构就是提供Message Buffers去临时存储发送或者接收到的CAN Frame数据,这也是后续会使用到的很重要的一个功能。CAN收发数据时,MBs会存储有仲裁域、数据域的数据(含ID),控制器将从这一块的空间去取得收发的数据,进而完成收发功能。
此处不做详细介绍,感兴趣的朋友直接参照手册即可,下面直接进入正题,关于FlexCan的初始化和不同的功能实现。
**
2、 FlexCan的初始化
**
第一步,配置CAN的总线时钟,配置如下:
/*Clock setting for FLEXCAN*/
clock_root_config_t rootCfg = {
0};
rootCfg.mux = kCLOCK_CAN1_ClockRoot_MuxSysPll2Pfd3; //FLEXCAN_CLOCK_SOURCE_SELECT
rootCfg.div = 5; //CAN ROOT CLK:60M
CLOCK_SetRootClock(kCLOCK_Root_Can1, &rootCfg);
此处我配置的总线时钟为60M,主要是为了后续配置CANFD总线波特率方便分频,如数据域的几个常用波特率:1Mbps,2 Mbps,3 Mbps,4 Mbps,5Mbps等,具体波特率可以参照产品的实际需求去配置。
第二步,在配置完时钟之后,配置波特率的实际分频参数,注意这里为了更贴合CAN总线对Bit数据采样的需求(实际测试过程中也发现如果使用默认配置,板子当前的硬件链路高波特率下无法完成正常传输:3Mbps以上,收发器支持5Mbps),下图是1BIT的CAN数据的组成:
代码如下:
if (FLEXCAN_FDCalculateImprovedTimingValues(flexcanConfig.baudRate, flexcanConfig.baudRateFD, CAN_CLK_FREQ,
&timing_config))
{
/* Update the improved timing configuration*/
memcpy(&(flexcanConfig.timingConfig), &timing_config, sizeof(flexcan_timing_config_t));
}
else
{
PRINTF("No found Improved Timing Configuration. Just used default configuration\r\n\r\n");
}
第三步,设置完波特率之后,就是初始化CAN控制器,使用的函数如下:
/*!
* brief Initializes a FlexCAN instance.
*
* This function initializes the FlexCAN module with user-defined settings.
* This example shows how to set up the flexcan_config_t parameters and how
* to call the FLEXCAN_FDInit function by passing in these parameters.
* code
* flexcan_config_t flexcanConfig;
* flexcanConfig.clkSrc = kFLEXCAN_ClkSrc0;
* flexcanConfig.baudRate = 1000000U;
* flexcanConfig.baudRateFD = 2000000U;
* flexcanConfig.maxMbNum = 16;
* flexcanConfig.enableLoopBack = false;
* flexcanConfig.enableSelfWakeup = false;
* flexcanConfig.enableIndividMask = false;
* flexcanConfig.disableSelfReception = false;
* flexcanConfig.enableListenOnlyMode = false;
* flexcanConfig.enableDoze = false;
* flexcanConfig.timingConfi