【S32K3 RTD LLD篇3 】K344 PIT CANFD 收发

小编最近学S32K344比较上头,微醺状态,感觉有点上瘾的那种,所以利用周末,总结下自己学习并动手做的一些东西,不见得好,就当一个笔记。
前面刚刚表达了下对于RTD400自带CAN demo的不满,并且也写了一个外部loopback 标准CAN的代码和文章:
【S32K3 RTD LLD篇2】K344 FlexCAN 外部loopback

这里,准备升级下,上CANFD,enhanced Rx FIFO接收,并且编写了个小功能,并且分享一些小编在实际中遇到的坑点,其实学习了一段时间,感觉这个汽车的芯片,单纯从技术上讲并不算难,就是技术内容点比较多,需要时间一点点去走一遭。
代码功能:开机PIT以2ms间隔定时触发并发送CANFD 64字节的数据帧10帧,每次定时到发送CAN数据的时候,同时也会翻转一个外部引脚,便于示波器查看,然后停止发送,并且进入接收状态,可以接收两种类型的标准ID帧,以及一种类型的扩展ID帧,收到之后果断回环出来。这里在收到ID回环的时候,同时也会去翻转板载的绿色小灯,如果接收到的ID帧并不是滤波表里面的,就不会接收数据并且翻转小灯。测试代码基于S32DS3.5, RTD4.0.0, 板子基于官方的S32K3X4EVB-T172,并且借助PEAK的PCAN-USB Pro去做测试。
同样声明下,此处篇幅有限,并不展开去讲整个FlexCAN的模块信息,因为看过很多的芯片参考手册,我认为这个汽车的芯片参考手册还是很值得夸赞的,写的清晰易懂,唯一要求就是不要偷懒,自己好好看,好好动手做。废话不多说,直接进入构建代码主题。

一,代码实现与配置

代码工程可以重新导入一个RTD4.0.0的can代码做,也可以直接基于之前做的外部loopbcak的代码去做。如果直接导入RTD的can demo,就得把上一篇文章里面提到的坑自己修复下。

1.1 引脚配置

除了添加的PTA6,PTA7用于CAN0_RX, CAN0_TX之外,添加了两个外部引脚,分别是PTA12,PTA30. PTA12用于标志2ms的定时翻转发送CANFD数据,PTA30是板载的绿色小灯引脚。
在这里插入图片描述

图 1

1.2 时钟配置

这里提到时钟配置,主要原因是需要使用告诉的CANFD,所以把CAN0的时钟源给提高到80MHZ,还有就是要注意下PIT使用的时钟源是什么,频率是多少,时钟配置如下:
在这里插入图片描述

图 2

在这里插入图片描述

图 3

1.3 外设配置

外设这里又添加了些模块,比如Pit, Siul2_Dio,然后flexCAN模块需要重新配置。
先说简单的Pit,就是一个定时器,配置如下:
在这里插入图片描述

图 4

在这里插入图片描述

图5

在这里插入图片描述

图6

实际上这个duration并没有真正使用,具体的定时时间是直接使用代码去控制的。
Siul2_Port在之前外部loop的基础上,又加了两个外部引脚:
在这里插入图片描述

图7

在这里插入图片描述

图8

对于这个MSCR,不知道号的,可以直接去S32K344RM附件的表格里面去查找。以CAN的PTA6,PTA7为例:
在这里插入图片描述

图9

关于Siul2_Dio,模块加了,啥也不用配,默认就行。
到了最关键的部分,FlexCAN,配置如下:
在这里插入图片描述

图10

在这里插入图片描述

图11

到目前为止,所有的配置就完成了。IntCtrl_lp配不配置无所谓,因为会在代码里面调用API配置。
点击update code,重新生成代码。

1.4 代码添加

直接上整个main的代码:

/*!
** Copyright 2019 NXP
** @file main.c
** @brief
**         Main module.
**         This module contains user's application code.
*/
/*!
**  @addtogroup main_module main module documentation
**  @{
*/
/* MODULE main */


/* Including necessary configuration files. */
#include "Mcal.h"
#include "Clock_Ip.h"
#include "FlexCAN_Ip.h"
#include "IntCtrl_Ip.h"
#include "Siul2_Port_Ip.h"
#include "Siul2_Dio_Ip.h"
#include "Pit_Ip.h"

#define MSG_ID 20u
#define RX_MB_IDX 1U
#define TX_MB_IDX 4U
volatile int exit_code = 0;
/* User includes */
uint8 dummyData[8] = {1,2,3,4,5,6,8};
/* PIT instance used - 0 */
#define PIT_INST_0 0U
/* PIT Channel used - 0 */
#define CH_0 0U
//#define PIT_PERIOD 400000//10ms
#define PIT_PERIOD 80000  //2ms
//#define PIT_PERIOD 8000  //20us

#define LED_PIN                 14u
#define LED_PORT                PTA_H_HALF

#define TEST_PIN                 12u
#define TEST_PORT                PTA_L_HALF

static volatile uint8 toggleLed = 0U;
static volatile uint8 canfdrxflag = 0U;
/* User includes */
uint8 tx_loop[64] =  {0X01, 0X02, 0X03, 0X04, 0X05, 0X06, 0X07, 0X08, 0X09, 0X0A, 0X0B, 0X0C, 0X0D, 0X0E, 0X0F, 0X10,
		              0X11, 0X12, 0X13, 0X14, 0X15, 0X16, 0X17, 0X18, 0X19, 0X1A, 0X1B, 0X1C, 0X1D, 0X1E, 0X1F, 0X20,
					  0X21, 0X22, 0X23, 0X24, 0X25, 0X26, 0X27, 0X28, 0X29, 0X2A, 0X2B, 0X2C, 0X2D, 0X2E, 0X2F, 0X30,
					  0X31, 0X32, 0X33, 0X34, 0X35, 0X36, 0X37, 0X38, 0X39, 0X3A, 0X3B, 0X3C, 0X3D, 0X3E, 0X3F, 0X40
                      };
uint8 tx_cnt = 0;
Flexcan_Ip_DataInfoType rx_info = {
        .msg_id_type = FLEXCAN_MSG_ID_STD,
        .data_length = 8u,
        .is_polling = TRUE,
        .is_remote = FALSE
};

Flexcan_Ip_DataInfoType tx_info = {
        .msg_id_type = FLEXCAN_MSG_ID_STD,
        .data_length = 64,
        .is_polling = TRUE,
        .is_remote = FALSE,
		.fd_padding = 0,
		.fd_enable = TRUE,
		.enable_brs = TRUE,

};

const Flexcan_Ip_EnhancedIdTableType CAN0_EnhanceFIFO_IdFilterTable[3] =
{
		/* Enhanced FIFO filter table element 0-2 */
		{
			.filterType = FLEXCAN_IP_ENHANCED_RX_FIFO_ONE_ID_FILTER,  // Filter element with filter + mask scheme
			.isExtendedFrame = true,
			.id2 = 0xABCD, 	// EXT ID filter
			.id1 = 0x1FFFFFFF ,	// EXT ID mask
			.rtr2 = false,	// RTR filter
			.rtr1 = true,	// RTR mask
		},
		{
			.filterType = FLEXCAN_IP_ENHANCED_RX_FIFO_ONE_ID_FILTER,
			.isExtendedFrame = false,
			.id2 = 0x123, 	// STD ID filter
			.id1 = 0x7FF ,	// STD ID mask
			.rtr2 = false,	// RTR filter
			.rtr1 = true,	// RTR mask
		},
		{
			.filterType = FLEXCAN_IP_ENHANCED_RX_FIFO_ONE_ID_FILTER,
			.isExtendedFrame = false,
			.id2 = 0x456, 	// STD ID filter
			.id1 = 0x7FF ,	// STD ID mask
			.rtr2 = false,	// RTR filter
			.rtr1 = true,	// RTR mask
		}
};
Flexcan_Ip_MsgBuffType rxData, rxFifoData;

/*!
  \brief The main function for the project.
  \details The startup initialization sequence is the following:
 * - startup asm routine
 * - main()
*/
extern void CAN0_ORED_0_31_MB_IRQHandler(void);
void PIT_timer(void)
{
    toggleLed = 1;
}

void flexcan0_Callback(uint8 instance, Flexcan_Ip_EventType eventType, uint32 buffIdx,
		const Flexcan_Ip_StateType *flexcanState)
{
	(void)flexcanState;
	(void)instance;

	switch(eventType)
	{
	case FLEXCAN_EVENT_RX_COMPLETE:

		dummyData[0]++;

		if(buffIdx==2) // MB2 received, std id
		{
			tx_info.msg_id_type = FLEXCAN_MSG_ID_STD; // send std ID message
			FlexCAN_Ip_Send(INST_FLEXCAN_0, TX_MB_IDX, &tx_info, MSG_ID, (uint8 *)&dummyData);
			FlexCAN_Ip_Receive(INST_FLEXCAN_0, 2, &rxData, false);
		}
		else if(buffIdx==1) // MB1 received, ext id
		{
			tx_info.msg_id_type = FLEXCAN_MSG_ID_EXT; // send ext ID message
			FlexCAN_Ip_Send(INST_FLEXCAN_0, TX_MB_IDX, &tx_info, MSG_ID, (uint8 *)&dummyData);
			FlexCAN_Ip_Receive(INST_FLEXCAN_0, 1, &rxData, false);
		}
		else {};


		break;
	case FLEXCAN_EVENT_RXFIFO_COMPLETE:
		break;
	case FLEXCAN_EVENT_TX_COMPLETE:
		break;
	case FLEXCAN_EVENT_ENHANCED_RXFIFO_COMPLETE:

		canfdrxflag = 1;
		// read rxFifoData[5]
		//FlexCAN_Ip_RxFifo(INST_FLEXCAN_0, &rxFifoData);

		break;
	case FLEXCAN_EVENT_ENHANCED_RXFIFO_WATERMARK:
		break;
	default:
		break;
	}
}

int main(void)
{
    /* Write your code here */
    Clock_Ip_Init(&Clock_Ip_aClockConfig[0]);

    Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS_PortContainer_0_BOARD_InitPeripherals, g_pin_mux_InitConfigArr_PortContainer_0_BOARD_InitPeripherals);

    IntCtrl_Ip_EnableIrq(FlexCAN0_1_IRQn);
    IntCtrl_Ip_InstallHandler(FlexCAN0_1_IRQn, CAN0_ORED_0_31_MB_IRQHandler, NULL_PTR);

    /* set PIT 0 interrupt */
    IntCtrl_Ip_Init(&IntCtrlConfig_0);
    IntCtrl_Ip_EnableIrq(PIT0_IRQn);

    /* Initialize PIT instance 0 - Channel 0 */
    Pit_Ip_Init(PIT_INST_0, &PIT_0_InitConfig_PB);
    /* Initialize channel 0 */
    Pit_Ip_InitChannel(PIT_INST_0, PIT_0_CH_0);
    /* Enable channel interrupt PIT_0 - CH_0 */
    Pit_Ip_EnableChannelInterrupt(PIT_INST_0, CH_0);
    /* Start channel CH_0 */
    Pit_Ip_StartChannel(PIT_INST_0, CH_0, PIT_PERIOD);



     FlexCAN_Ip_Init(INST_FLEXCAN_0, &FlexCAN_State0, &FlexCAN_Config0);
     FlexCAN_Ip_SetTDCOffset_Privileged(INST_FLEXCAN_0,1,12);

 	FlexCAN_Ip_ConfigEnhancedRxFifo_Privileged(INST_FLEXCAN_0, &CAN0_EnhanceFIFO_IdFilterTable[0]);

 	FlexCAN_Ip_SetRxMaskType_Privileged(INST_FLEXCAN_0,FLEXCAN_RX_MASK_INDIVIDUAL);
 	FlexCAN_Ip_SetRxIndividualMask_Privileged(INST_FLEXCAN_0,1,0x1FFFFFFF);
 	FlexCAN_Ip_SetRxIndividualMask(INST_FLEXCAN_0,2,0x7FF<<18);

     FlexCAN_Ip_SetStartMode(INST_FLEXCAN_0);
     FlexCAN_Ip_ConfigRxMb(INST_FLEXCAN_0, RX_MB_IDX, &rx_info, MSG_ID);

     rx_info.is_polling = FALSE;
     rx_info.msg_id_type = FLEXCAN_MSG_ID_STD;
     FlexCAN_Ip_ConfigRxMb(INST_FLEXCAN_0, RX_MB_IDX, &rx_info, 0x1);
     rx_info.msg_id_type = FLEXCAN_MSG_ID_EXT;
     FlexCAN_Ip_ConfigRxMb(INST_FLEXCAN_0, 2, &rx_info, 0xFACE);
     FlexCAN_Ip_RxFifo(INST_FLEXCAN_0, &rxFifoData);


    for(;;)
    {

    	if(1 == toggleLed)
    	{
    	   toggleLed = 0;
    	   tx_loop[63] = tx_cnt++;

    	   if(tx_cnt > 10)
    	   {
    	    	Pit_Ip_StopChannel(PIT_INST_0, CH_0);
    	   }
    	   else
    	   {

    	    	//Siul2_Dio_Ip_TogglePins(LED_PORT, (1UL << LED_PIN));
    	        Siul2_Dio_Ip_TogglePins(TEST_PORT, (1UL << TEST_PIN));

    	        FlexCAN_Ip_Send(INST_FLEXCAN_0, TX_MB_IDX, &tx_info, MSG_ID, (uint8 *)&tx_loop);
    	    	// Polling
    	    	while(FlexCAN_Ip_GetTransferStatus(INST_FLEXCAN_0, TX_MB_IDX) != FLEXCAN_STATUS_SUCCESS)
    	    	{
    	    	    FlexCAN_Ip_MainFunctionWrite(INST_FLEXCAN_0, TX_MB_IDX);
    	    	}
    	    }

    	}

    	if(1 == canfdrxflag)
    	{
    		canfdrxflag = 0;
    		Siul2_Dio_Ip_TogglePins(LED_PORT, (1UL << LED_PIN));
    		FlexCAN_Ip_Send(INST_FLEXCAN_0, TX_MB_IDX, &tx_info, MSG_ID, (uint8 *)&rxFifoData.data);
  	        while(FlexCAN_Ip_GetTransferStatus(INST_FLEXCAN_0, TX_MB_IDX) != FLEXCAN_STATUS_SUCCESS)
  	        {
  	    	  FlexCAN_Ip_MainFunctionWrite(INST_FLEXCAN_0, TX_MB_IDX);
  	        }
  	        FlexCAN_Ip_RxFifo(INST_FLEXCAN_0, &rxFifoData);

    	}


    }
    FlexCAN_Ip_SetStopMode(INST_FLEXCAN_0);
    FlexCAN_Ip_Deinit(INST_FLEXCAN_0);
    return 0;
}

/* END main */
/*!
** @}
*/

二,测试结果

代码写的对不对,测试结果走一圈。

PCAN-VIEW配置如下:
在这里插入图片描述

图 12

在这里插入图片描述

图 13

在这里插入图片描述

图14

可以看到,启动之后S32K344发了10次的CANFD帧都被收到了,而且带FD,BRS那种。
后面就是PC断通过CAN盒子给S32K344下发数据,然后K344收到之后回环回来。
从Trace窗口可以看到,只能接收标准帧0X123,0X456,和扩展帧0XABDC。后面再发0X789标准帧没有反应,说明ID滤波是起效果的。
看完了这种数字效果,来点示波器CAN0_TX上的总线效果。
在这里插入图片描述

图15

这个是启动之后10次的定时触发,准确的2ms定时触发并且发送CAN数据,通道1是CAN0_TX的数据,通道3是引脚PTA12的定时翻转效果。
放大看看一帧的情况,看看总帧时间是否靠谱:
在这里插入图片描述

图16

那么这个150us是否靠谱呢,我们借助下PEAK的神器:CAN FD Frame Analyzer:
https://www.peak-system.com/CAN-FD-Frame-Analyzer.563.0.html?&L=1
无需硬件,免费使用。
在这里插入图片描述

图 17

在这里插入图片描述

图18

因为示波器测试的是结尾的上升沿,所以总体看下来150us还是靠谱的存在,说明这个CANFD是确实发出来了。但是为了进一步确认,去查看下仲裁帧bit时间和数据断bit时间:
仲裁帧bit时间如下,2us,波特率是500KHZ,所以说这个bit时间2us是正确的:
在这里插入图片描述

图 19

数据帧bit时间,200ns,定义的5Mhz,正好就是200ns,所以也是准确的:
在这里插入图片描述

图20

所以,到目前为止,所有的功能已经全部实现了。

三,坑位标点排雷

3.1 PC接受现实CANFD实际数据段并没有高频

小编在这个圈里面差点迷失了自我。刚开始,小编很顺利,就是用PIT定时2ms去发的CANFD,然后PEAKCAN看收到了数据,就很开心,觉得已经OK了。然而冥冥之中,小编又想用示波器看看总线,不看不知道,一看吓一跳,

在这里插入图片描述

图21

看看,500K/5M的64字节标准帧发出来这么长时间,这倒推一下,妥妥的就是按照500K去发的。
PC收到的数据这样:
在这里插入图片描述

图 22

所以小编就开始找问题了,什么BRS,ISO CAN,FIFO,enhancedCBT Can都试了,CAN transiver能不能支持ISO CAN 也怀疑了,最后毛了,连PEAK CAN能不能收5M都怀疑了,所以上了一块RT同样配置的,人家妥妥的稳定的能收到,只是
Type 变成了FD,BRS,于是查看了自己,发送的时候,使能BRS, 使能CANFD,再一搞,直接收不到了。所以,开始怀疑波特率配置,我之前用的那组波特率配置,是因为别人用了能够收发同样的数据,所以才偷懒直接用,因为不行,所以小编去NXP官方论坛网上找了一个贼牛的表格 :
CAN Bit Timing calculation v2.1.zip:
https://community.nxp.com/t5/MPC5xxx-Knowledge-Base/MPC5xxx-S32Kxx-LPCxxxx-CAN-CAN-FD-bit-timing-calculation/ta-p/1119319
里面直接可以选择K344,选择CAN收发器,然后填入目标波特率,直接给你推算几个合适的。我一看,这里推荐的没有一组是和我老的波特率配置一致的,所以按照表格果断改了配置,表格是这样的:
在这里插入图片描述

图23

在这里插入图片描述

图 24

再试一把,还没行!然后又开始各种寻寻觅觅,凄凄惨惨戚戚!最后发现了一个神秘的点,S32K344RM里面是这么说的:73.3.10.3 Transceiver delay compensation
在这里插入图片描述

图 25

就是加上TDC offset,于是小编果断加上了这段代码:
FlexCAN_Ip_SetTDCOffset_Privileged(INST_FLEXCAN_0,1,14);
这个就是使能TDC offset,这个14就是按照:
Offset = (FPSEG1 + FPROPSEG + 2) × (FPRESDIV + 1)=(2+2+2)*(1+1)=12
加了之后,就可以接收了,而且还很稳定。

3.2 ISO CAN和NO ISO CAN

这里主要说明的就是,PEAK View的配置ISO CAN要和芯片的FlexCAN的ISO CAN 配置要对应,比如选了ISO CAN,就都要选,否则一个不选就会通讯错误。另外在平时选择CAN收发器的时候也要注意,如果要用ISO CAN,也的选择支持ISO CAN标准的CAN收发器。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值