NXP RT1060学习总结 - CANFD功能

1、RT1060-CAN FD功能简介

这里使用RT1060系列的1064芯片进行开发,测试板是官方提供的开发板;RT1060系列支持3路CAN功能,CAN1和CAN2只能最为普通的CAN外设,支持CAN2.0,而CAN3支持CAN-FD功能;CAN-FD功能这里就不做详细介绍,百度上很多该方面资料,核心点是普通CAN只能传输8字节数据,而CAN-FD最大支持传输64字节数据。
注意事项:使用CANFD功能的时候,用于测试的CAN工具需要支持CANFD功能。

2、各类宏定义和全局变量

#define EXAMPLE_CAN CAN3								//使用的CAN外设 - CAN3
#define RX_MESSAGE_BUFFER_NUM (10)		//接收邮箱
#define TX_MESSAGE_BUFFER_NUM (9)			//发送邮箱

#define EXAMPLE_CAN_CLK_SOURCE (kFLEXCAN_ClkSrc1)	//CAN时钟

/* 选择60M时钟除以USB1 PLL (480mhz)作为flexcan主时钟源 */
#define FLEXCAN_CLOCK_SOURCE_SELECT (0U)
/* Clock divider for master flexcan clock source */
#define FLEXCAN_CLOCK_SOURCE_DIVIDER (2U)

#define DLC         (15)
#define BYTES_IN_MB kFLEXCAN_64BperMB	//每个消息区选择64字节数据
#define EXAMPLE_CAN_CLK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (FLEXCAN_CLOCK_SOURCE_DIVIDER + 1U))	//时钟频率

flexcan_handle_t flexcanHandle;
volatile bool txComplete = false;			//发送完成标志
volatile bool rxComplete = false;			//接收完成标志
volatile bool wakenUp    = false;			//唤醒标识
flexcan_mb_transfer_t txXfer, rxXfer;	//邮箱
flexcan_fd_frame_t frame;

uint32_t txIdentifier;		//收发ID标识符
uint32_t rxIdentifier;

uint16_t t_Count = 0;	//用于测试

3、CAN FD IO初始化

static void can2_gpio_config(void)
{
	//设置GPIO的时钟
	CLOCK_EnableClock(kCLOCK_Iomuxc);
	
	 //配置IO的复用模式 设置为CAN3的TX和RX功能
	IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_14_FLEXCAN3_TX, 1U); 
	IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_15_FLEXCAN3_RX, 1U);

	//配置GPIO功能
	IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_14_FLEXCAN3_TX, 0x10B0U); 
	IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_15_FLEXCAN3_RX, 0x10B0U); 
}

4、CAN FD功能配置

void can2_function_config(void)
{
	flexcan_config_t flexcanConfig;					//CAN配置
    flexcan_rx_mb_config_t mbConfig;				//接收邮箱配置
	flexcan_timing_config_t timing_config;		//时间配置
	
	/* FLEXCAN时钟配置 */
    CLOCK_SetMux(kCLOCK_CanMux, FLEXCAN_CLOCK_SOURCE_SELECT);
    CLOCK_SetDiv(kCLOCK_CanDiv, FLEXCAN_CLOCK_SOURCE_DIVIDER);
	
	/* 设置发送和接收的帧ID */
	txIdentifier = 0x321;
    rxIdentifier = 0x123;
	
	/* 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.clkSrc = EXAMPLE_CAN_CLK_SOURCE;
	flexcanConfig.bitRate = 500000U;			//这里使用的是**bitRate**,bit位的波特率
	
	memset(&timing_config, 0, sizeof(flexcan_timing_config_t));
	if (FLEXCAN_FDCalculateImprovedTimingValues(EXAMPLE_CAN, flexcanConfig.bitRate, flexcanConfig.bitRateFD,
                                                EXAMPLE_CAN_CLK_FREQ, &timing_config))
    {
        /* 更新修改后的定时配置 */
        memcpy(&(flexcanConfig.timingConfig), &timing_config, sizeof(flexcan_timing_config_t));
    }
	
	FLEXCAN_FDInit(EXAMPLE_CAN, &flexcanConfig, EXAMPLE_CAN_CLK_FREQ, BYTES_IN_MB, true);
	
	/* 创建CAN句柄 并建立回调函数 */
    FLEXCAN_TransferCreateHandle(EXAMPLE_CAN, &flexcanHandle, flexcan_callback, NULL);

    /* 设置接收屏蔽机制 后面来仔细研究一下该屏蔽机制 */
    FLEXCAN_SetRxMbGlobalMask(EXAMPLE_CAN, FLEXCAN_RX_MB_STD_MASK(rxIdentifier, 0, 0));
	
	/* 设置接收消息缓存 */
    mbConfig.format = kFLEXCAN_FrameFormatStandard;		//标准帧
    mbConfig.type   = kFLEXCAN_FrameTypeData;			//数据帧
    mbConfig.id     = FLEXCAN_ID_STD(rxIdentifier);		//设置帧ID
	FLEXCAN_SetFDRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);
	
	/* 设置发送消息缓存 */
	FLEXCAN_SetFDTxMbConfig(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, true);
}

流程与基础CAN功能类似,在波特率配置的时候使用的是bitRate ,这里需要注意以下;
CANFD采用了双波特率形式:标准波特率(也称仲裁域波特率)和数据域波特率,所以帧结构中不同段采用的波特率也不同。

配置的接收是轮询接收,中断接收后面再测试一下,配合官方SDK的例程探索,难度不大。
这里还配置了一个回调函数,用于判断接收和发送是否完成。

5、CAN FD收发

//发送数据
void can2_send_data(void)
{
	frame.id = FLEXCAN_ID_STD(txIdentifier);
	frame.format = (uint8_t)kFLEXCAN_FrameFormatStandard;
	frame.type   = (uint8_t)kFLEXCAN_FrameTypeData;
	frame.length = (uint8_t)DLC;
	frame.brs = 1U;	//灵活的数据率格式与比特率开关
    frame.edl = 1U;	//灵活的数据速率格式扩展数据长度
	
	frame.dataWord[0] = 0x12345678;
	frame.dataWord[2] = 0x12345678;
	frame.dataWord[15] = t_Count;
	txXfer.mbIdx = (uint8_t)TX_MESSAGE_BUFFER_NUM;	//用于传输消息的消息缓冲区的索引。
	txXfer.framefd = &frame;
	(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
	//FLEXCAN_WriteFDTxMb(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, &frame);
}

/*!
 * @brief FlexCAN Call Back function
 */
static FLEXCAN_CALLBACK(flexcan_callback)
{
    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;

        case kStatus_FLEXCAN_WakeUp:
            wakenUp = true;
            break;

        default:
            break;
    }
}

//轮询接收
void can2_receive_data(void)
{
	rxXfer.mbIdx = (uint8_t)RX_MESSAGE_BUFFER_NUM;
	rxXfer.framefd = &frame;

	//无阻塞接收 利用回调函数进行接收数据
	(void)FLEXCAN_TransferFDReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
	if (rxComplete == true)
	{
		t_Count++; 
		rxComplete = false;
	}
}

这里的接收和发送有一个联动的功能,就是CAN FD接收到正确的帧ID后,会将t_Count++;,然后再发送的地方frame.dataWord[15] = t_Count;这样就可以检测这个CAN FD的发送后接收是否都正确。
另外需要注意的是,使用CAN FD一定需要将flexcan_fd_frame_t 中的brs 、edl 置1;
CAN FD 发送配置

6、涉及的函数及标志位解释

6.1 FLEXCAN_FDCalculateImprovedTimingValues()函数

根据CAN FD的特定比特率计算改进的定时值。
该函数用于根据给定的标称相位比特率和数据相位比特率计算CAN FD定时值。计算时间值将在CBT/ENCBT和FDCBT/EDCBT寄存器中设置。计算基于CiA 1301 v1.0.0文档的建议。
参数bitRate:CAN FD标称相位速度,单位为bps,由用户定义。
参数bitRateFD:CAN FD数据相位速度(以bps为单位)由用户定义。等于bitRate表示禁用比特率切换。
参数sourceClock_Hz:时钟源频率,单位为Hz。
参数pTimingConfig:指向FlexCAN定时配置结构的指针。

6.2 flexcan_timing_config_t 结构体

FlexCAN协议定时特性的配置结构。

typedef struct _flexcan_timing_config
{
    uint16_t preDivider; /*!< 经典CAN或CAN FD标称相位比特率预分频器。 */
    uint8_t rJumpwidth;  /*!< 经典CAN或CAN FD标称相位重同步跳变宽度。 */
    uint8_t phaseSeg1;   /*!< 经典CAN或CAN FD标称相位段1。 */
    uint8_t phaseSeg2;   /*!< 经典CAN或CAN FD标称相位段2。 */
    uint8_t propSeg;     /*!< 经典CAN或CAN FD标称相位传播段。 */
#if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
    uint16_t fpreDivider; /*!< CAN FD数据相位比特率预分频器。*/
    uint8_t frJumpwidth;  /*!< CAN FD数据相位重同步跳变宽度。 */
    uint8_t fphaseSeg1;   /*!< CAN FD数据相位相位段1 */
    uint8_t fphaseSeg2;   /*!< CAN FD数据相位相位段2 */
    uint8_t fpropSeg;     /*!< CAN FD数据相位传播段。*/
#endif
} flexcan_timing_config_t;

使用CAN FD时,仲裁域波特率对应:preDivider、rJumpwidth、phaseSeg1、phaseSeg2、propSeg,数据域波特率对应fpreDivider、frJumpwidth、fphaseSeg1、fphaseSeg2、fpropSeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值