本来采用这一款芯片就是看中了其有双通道的CANFD,这个大大解决了CAN2.0B的传输效率问题,以往产品升级和批量传输数据的时候,总是容易出现总线堵塞,这次就简单测试一下其性能,还会比较一下STM新出的STM32H503CBT6,进行比较;STM32H503CBT6采用M33内核,主频250M,同样带有FPU和DSP指令,带有1路CANFD。
1.FR3068X-C can测试
按照SDK的外设例程,打开对应例程,修改部分时钟,因为本次测试的CANFD是总裁段是1M波特率,数据段是4M波特率,所以需要重新配置一下时钟。
/*********************************************************************
* @fn system_clock_config
*
* @brief System Misc Init.
*/
void system_clock_config(void)
{
System_ClkConfig_t ClkConfig;
/* CORE HSCLK Config */
ClkConfig.CORE_HSCLK_CFG.CORE_HSCLK_Source = CORE_HSCLK_SEL_HES;
/* PLL clock = HSE_VALUE*N + (HSE_VALUE/65535)*M */
/* SPLL CLK Config */
ClkConfig.SPLL_CFG.PowerEn = PLL_POWER_ENABLE;
ClkConfig.SPLL_CFG.PLL_N = 8;
ClkConfig.SPLL_CFG.PLL_M = 0;
/* PLL clock = HSE_VALUE*N + (HSE_VALUE/65535)*M */
/* AUPLL CLK Config */
ClkConfig.AUPLL_CFG.PowerEn = PLL_POWER_ENABLE;
ClkConfig.AUPLL_CFG.PLL_N = 8;
ClkConfig.AUPLL_CFG.PLL_K = 0;
ClkConfig.AUPLL_CFG.PLL_D = 0;
System_CORE_HSCLK_config(&ClkConfig.CORE_HSCLK_CFG);
if (System_SPLL_config(&ClkConfig.SPLL_CFG,200) == -1)
while(1);
if (System_AUPLL_config(&ClkConfig.AUPLL_CFG,200) == -1)
while(1);
ClkConfig.MCU_Clock_Source = MCU_CLK_SEL_SPLL_CLK;
ClkConfig.SOC_DIV = 1; /* This parameter is valid when MCU_Clock_Source == MCU_CLK_SEL_SPLL_CLK */
ClkConfig.MCU_DIV = 1;
ClkConfig.APB0_DIV = 1;
ClkConfig.APB1_DIV = 1;
ClkConfig.APB2_DIV = 1;
System_MCU_clock_Config(&ClkConfig);
} 复制代码
上述代码,将主时钟设置为192Mhz,然后继续初始化CAN时钟,
void can_demo(void)
{
uint32_t ram_size;
GPIO_InitTypeDef GPIO_Handle;
__SYSTEM_MCAN_CLK_SELECT_SPLL();
__SYSTEM_GPIOA_CLK_ENABLE();
__SYSTEM_MCAN3_CLK_ENABLE();
printf("can clock:%d\r\n", system_get_peripheral_clock(PER_CLK_CANx));
GPIO_Handle.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_Handle.Mode = GPIO_MODE_AF_PP;
GPIO_Handle.Pull = GPIO_PULLUP;
GPIO_Handle.Alternate = GPIO_FUNCTION_5;
gpio_init(GPIOA, &GPIO_Handle);
CAN3_Handle.CANx = CAN3;
CAN3_Handle.Init.Prescaler = 4;
CAN3_Handle.Init.SyncJumpWidth = 3;
CAN3_Handle.Init.TimeSeg1 = 16;
CAN3_Handle.Init.TimeSeg2 = 5;
CAN3_Handle.Init.DataBit_RateSwitch = CAN_FUNC_ENABLE;
CAN3_Handle.Init.DataBit_Prescaler = 1;
CAN3_Handle.Init.DataBit_SyncJumpWidth = 3;
CAN3_Handle.Init.DataBit_TimeSeg1 = 16;
CAN3_Handle.Init.DataBit_TimeSeg2 = 5;
can_init(&CAN3_Handle);
CAN3_Handle.RAMConfig.StartAddress = (uint32_t)Can0Buffer;
CAN3_Handle.RAMConfig.StandardIDFilterNums = 128;
CAN3_Handle.RAMConfig.ExtendedIDFilterNums = 64;
CAN3_Handle.RAMConfig.TxFIFOQueueNums = 32;
CAN3_Handle.RAMConfig.TxDedicatedBufferNums = 0;
CAN3_Handle.RAMConfig.RxFIFO0Nums = 64;
CAN3_Handle.RAMConfig.RxFIFO1Nums = 64;
CAN3_Handle.RAMConfig.DataBufferSize = CAN_DATA_BUFFER_SIZE_64_BYTE;
ram_size = can_message_ram_init(&CAN3_Handle);
printf("can3 use ram size %d \r\n", ram_size);
struct_FilterCfg_t FilterCfg;
FilterCfg.FilterType = CAN_FILTER_RANGE_FILTER;
FilterCfg.ProcessMode = FILTER_PROCESS_SET_PRIORITY_AND_STORE_IN_RxFIFO0;
FilterCfg.FilterID_1 = 0x400;
FilterCfg.FilterID_2 = 0x500;
can_add_standard_filter(&CAN3_Handle, FilterCfg, 0);
FilterCfg.FilterType = CAN_FILTER_SINGLE_ID_FILTER;
FilterCfg.ProcessMode = FILTER_PROCESS_SET_PRIORITY_AND_STORE_IN_RxFIFO0;
FilterCfg.FilterID_1 = 0x750;
FilterCfg.FilterID_2 = 0x750;
can_add_standard_filter(&CAN3_Handle, FilterCfg, 1);
FilterCfg.FilterType = CAN_FILTER_DUAL_ID_FILTER;
FilterCfg.ProcessMode = FILTER_PROCESS_SET_PRIORITY_AND_STORE_IN_RxFIFO0;
FilterCfg.FilterID_1 = 0x600;
FilterCfg.FilterID_2 = 0x601;
can_add_standard_filter(&CAN3_Handle, FilterCfg, 2);
FilterCfg.FilterType = CAN_FILTER_CLASSIC_FILTER;
FilterCfg.ProcessMode = FILTER_PROCESS_SET_PRIORITY_AND_STORE_IN_RxFIFO0;
FilterCfg.FilterID_1 = 0xF0;
FilterCfg.FilterID_2 = 0xFC;
can_add_standard_filter(&CAN3_Handle, FilterCfg, 3);
FilterCfg.FilterType = CAN_FILTER_RANGE_FILTER;
FilterCfg.ProcessMode = FILTER_PROCESS_SET_PRIORITY_AND_STORE_IN_RxFIFO1;
FilterCfg.FilterID_1 = 0x10000;
FilterCfg.FilterID_2 = 0x20000;
can_add_extended_filter(&CAN3_Handle, FilterCfg, 0);
FilterCfg.FilterType = CAN_FILTER_DUAL_ID_FILTER;
FilterCfg.ProcessMode = FILTER_PROCESS_SET_PRIORITY_AND_STORE_IN_RxFIFO1;
FilterCfg.FilterID_1 = 0x333333;
FilterCfg.FilterID_2 = 0x444444;
can_add_extended_filter(&CAN3_Handle, FilterCfg, 1);
CAN3_Handle.RxFIFO0_New_Message_Callback = RxFIFO0_New_Message_handle;
CAN3_Handle.RxFIFO1_New_Message_Callback = RxFIFO1_New_Message_handle;
CAN3_Handle.Transmission_Completed_Callback = Transmission_Completed_handle;
can_int_select_line(&CAN3_Handle, INT_RxFIFO0_NEW_MESSAGE, CAN_INT_LINE0);
can_int_select_line(&CAN3_Handle, INT_RxFIFO1_NEW_MESSAGE, CAN_INT_LINE0);
can_int_select_line(&CAN3_Handle, INT_TRANSMISSION_COMPLETED, CAN_INT_LINE0);
can_int_enable(&CAN3_Handle, INT_RxFIFO0_NEW_MESSAGE);
can_int_enable(&CAN3_Handle, INT_RxFIFO1_NEW_MESSAGE);
can_int_enable(&CAN3_Handle, INT_TRANSMISSION_COMPLETED);
NVIC_EnableIRQ(CAN3_Line0_IRQn);
__SYSTEM_TIMER0_CLK_ENABLE();
__SYSTEM_TIMER1_CLK_ENABLE();
__SYSTEM_TIMER2_CLK_ENABLE();
__SYSTEM_TIMER3_CLK_ENABLE();
NVIC_EnableIRQ(TIMER0_IRQn);
NVIC_EnableIRQ(TIMER1_IRQn);
NVIC_EnableIRQ(TIMER2_IRQn);
NVIC_EnableIRQ(TIMER3_IRQn);
timer_int_enable(Timer0);
timer_int_enable(Timer1);
timer_int_enable(Timer2);
timer_int_enable(Timer3);
timer_init(Timer0, 24000*10);
timer_init(Timer1, 24000*20);
timer_init(Timer2, 24000*30);
timer_init(Timer3, 24000*40);
for (int i = 0; i < 64; i++)
TxBuffer[i] = i + 0x30;
CANTxHeader.DLC = CAN_FD_DLC15_DATA_LENGTH_64BYTE;
CANTxHeader.IdType = CAN_ID_EXTENDED;
CANTxHeader.FrameType = CAN_DATA_FRAME;
CANTxHeader.FormatMode = CAN_FD_FRAME;
CANTxHeader.BitRateSwitch = CAN_FUNC_ENABLE;
CANTxHeader.Identifier = 0x444444;
while(1)
{
can_add_tx_message(&CAN3_Handle, CANTxHeader, TxBuffer);
}
} 复制代码
上述代码重新配置了CAN的时钟为2分频的SPLL,然后管脚配置为A10 A11,使用CAN3,
void can3_line0_irq(void)
{
can_IRQHandler(&CAN3_Handle);
} 复制代码
注意,别忘了修改CAN中断函数名称,改为CAN3,
上述程序的目的是为了测试一下是否能够按照大约4M波特率进行测试,测试结果是大约每秒钟能发送5100帧左右的数据。
若调整为2M的数据波特率,则大约能发送3100帧,并且稳定性比较好
2.测试STM32H503CBT6,设置主频为240M,开启缓存,CANFD的速度为仲裁段1M,数据段2-4M,while循环发送,看看处理能力。
先看一下,经典CAN模式下,500K波特率下的速度,大概3400帧
经典CAN模式下,1M波特率下是6700帧的水平
CANFD模式下,因为使用的是TJA1042T,标称是5M的转换器,不知道为什么不能跑到4M数据波特率,所以仲裁帧是1M,数据帧是2M,可以看到发送速度是3100帧左右,但是数据略微有点波动2900-3100之间浮动,
以上的测试内容不是想说明什么强弱,只是看一下在空任务状态,各个SDK采用的发送方式能否跑满带宽。
双通道中FR3068在通道1,STM32在通道2,看一下经过一段时间以后,出现了一点点的性能累计差异。
视频可以看到,在经过一段时间以后,FR3068X发送帧率稳定在3050-3100左右,STM32稍微低一些,在2900-3100左右。
上述的测试方法存在部分问题,也许更加严谨的测试方法能测试出部分开销,但是2M波特率下都能稳定在3100左右就挺好了。