自学S32k144(12)-CANFD

1.CAN_FD简介

1.1 什么是CANFD

在《 通信总线协议之CAN总线协议详解 》中介绍了CAN 2.0 A/B总线协议,但是随着总线技术在汽车电子领域越来越广泛的应用,特别是自动驾驶技术的迅速发展,汽车电子对总线宽度和数据传输速率的要求也越来越高,传统CAN(1MBit/s,8Bytes Payload)已难以满足日益增加的需求。
因此,一种能够与CAN 2.0 A/B兼容,但通信速率更高,有效载荷更高的CAN总线 :CAN-FD总线协议应运而生,在2012年,Bosch发布了新的CAN FD标准 (CAN with Flexible Data Rate)
CAN FD继承了CAN的绝大多数特性,如同样的物理层,双线串行通信协议,基于非破坏性仲裁技术,分布式实时控制,可靠的错误处理和检测机制等,同时CAN FD弥补了CAN在总线带宽和数据长度方面的不足。

1.2 CAN FD的特点

CAN FD传输速率是可变的:从控制场中的BRS位到ACK场之前(含CRC分界符)为可变速率,最高速率可达到8Mbps
CAN FD数据长度不同:CAN FD每个数据帧最多支持64个数据字节,而传统CAN最多支持8个数据字节,这减少了协议开销,并提高了协议效率。
CAN FD帧格式不同:CanFD新增了FDF、BRS、ESI位
FDF 位(Flexible Data Rate Format):原 CAN 数据帧中的保留位 r,用来区别是 CAN 报文还是 CAN-FD 报文,FDF 位常为隐性 1,表示 CAN FD 报文;
BRS 位( Bit Rate Switch):表示位速率转换,当 BRS 为显性位 0时,数据段的位速率与仲裁段的位速率一致(恒定速率),当 BRS 为隐性位 1时速率可变(即 BSR 到 CRC 使用转换速率传输);
ESI 位(Error State Indicator):发送节点错误状态指示,主动错误时发送显性位 0 ,被动错误时发送隐性位 1 。

2. CAN-FD总线协议

CAN FD节点可以正常收、发CAN报文,但CAN节点不能正确收、发CAN FD报文,因为其帧格式不一致。
与CAN一样,CAN FD一共具有:帧起始,仲裁段,控制段,数据段,CRC段,ACK段和帧结束,7部分组成。
在这里插入图片描述

2.1 帧起始

CAN FD与CAN使用相同的SOF标志位来标志报文的起始
帧起始由1个显性位构成,标志着报文的开始,并在总线上起着同步的作用
在这里插入图片描述

2.2 仲裁段

与传统CAN相比,CAN FD取消了远程帧,用RRS位替换了RTR位,为常显性;
RTR(Remote Transmission Request Bit):远程发送请求位,RTR位在数据帧里必须是显性,而在远程帧里为隐性
RRS(Remote Request Substitution):远程请求替换位,即传统CAN中的RTR位,CAN FD中为常显性
IDE位仍为标准帧和扩展帧标志位,若标准帧与扩展帧具有相同的前 11 位 ID,那么标准帧将会由于 IDE 位为 0,优先获得总线。
在这里插入图片描述

2.3 控制段

控制段中CANFD与CAN有着相同的IDE,res,DLC位;同时增加了三个控制bit位,FDF、BRS、ESI;
FDF(Flexible Data Rate Format):原CAN数据帧中的保留位r,FDF常为隐性,表示CAN FD 报文;
BRS(Bit Rate Switch):位速率转换开关,当BRS为显性位时数据段的位速率与仲裁段的位速率一致,当BRS为隐性位时数据段的位速率高于仲裁段的位速率;
ESI(Error State Indicator):错误状态指示,主动错误时发送显性位,被动错误时发送隐性位;
在这里插入图片描述
DLC同样是4bit表示数据段的长度,对应的关系如下
在这里插入图片描述

2.4 数据段

数据段即为传输的具体数据内容
CAN FD不仅能支持传统的0-8字节报文,同时可以支持12, 16, 20, 24, 32, 48, 64字节
在这里插入图片描述

2.5 CRC段

为了避免位填充对CRC的影响,CAN FD在CRC场中增加了stuff count记录填充位的个数对应8的模,并用格雷码表示,还增加了奇偶校验位;且在CRC中加入了填充位FSB(fixed stuff-bit)
Stuff Count由以下两个元素组成:
格雷码计算:CRC区域之前的填充位数除以8,得到的余数(Stuff bit count modulo 8)进行格雷码计算得到的值(Bit 0-2)
奇偶校验(parity):通过格雷码计算后的值的奇偶校验(偶校验)
CAN FD对CRC算法进行了改进,CRC对填充位也加入了计算;在校验部分为避免有连续位超过6个,就确定在第一位以及以后每4位添加一个填充位加以分割,这个填充位的值是上一位的反码,作为格式检查,如果填充位不是上一位的反码,就作出错处理。
CAN的CRC的位数是15位,而在CAN FD中,CRC场扩展到了21位,如下:
当传输数据为0~8字节时:CRC 15位
当传输数据为9~16字节时:CRC 17位
当传输数据为17~64个字节时:CRC 21位
CAN的CRC的位数是15位,而在CAN FD中,CRC场扩展到了21位,如下:
当传输数据为0~8字节时:CRC 15位
当传输数据为9~16字节时:CRC 17位
当传输数据为17~64个字节时:CRC 21位
在这里插入图片描述

2.6 ACK段

与CAN相比,在CAN FD中最多可接受2个位时间有效的ACK,允许1个额外的位时间来补偿收发器相移和传播延迟
由从高速的数据场到慢速的仲裁场时,时钟切换会引起收发器相移和总线传播延迟;为了补偿其相移和延迟,相比传统的CAN,在CAN FD中多加了这额外的1位时间
在ACK之后,发送ACK界定符,这是一个表示ACK结束的分隔符,用1位隐性位表示
在这里插入图片描述

2.7 帧结束

与CAN一样,CAN FD的帧结尾也为连续7位的隐性位

3. 如何从传统的CAN升级到CAN FD

尽管 CANFD 继承了绝大部分传统 CAN 的特性,但是从传统 CAN 到 CANFD 的升级, 仍需要做很多的工作,主要包括:
在硬件和工具方面,要使用 CANFD,首先要选取支持 CANFD 的 CAN 控制器和收发器,还要选取新的网络调试和监测工具;
在网络兼容性方面,对于传统 CAN 网段的部分节点需要升级到 CANFD 的情况要特别注意,由于帧格式不一致的原因,CANFD 节点可以正常收发传统 CAN 节点报文,但是传统 CAN 节点不能正常收发 CANFD 节点的报文;
参考链接: https://blog.csdn.net/weixin_44289254/article/details/135508269?fromshare=blogdetail&sharetype=blogdetail&sharerId=135508269&sharerefer=PC&sharesource=weixin_70362088&sharefrom=from_link

4.can_FD配置基于S32K144

S32k144 只有一路Can。Can0
配置PINMUX
在这里插入图片描述
配置外设
在这里插入图片描述
在这里插入图片描述
S32 CAN FD(Flexible Data-Rate) 中配置两个波特率(即仲裁段波特率和数据段波特率)是由 CAN FD协议的核心设计特性 决定的。
在本次实验中,仲裁段比特率设置为500kbps,数据段比特率设置为2Mkbps。其他配置可以参考CAN配置,具体配置如下。
在这里插入图片描述
生成代码。

5.canfd 分析工具的简单使用

设备针对S32K144Can0的配置进行配置。
在这里插入图片描述

6.实验描述

主要实现S32K144 向分析仪发送数据,同时分析仪也向S32K144发送数据。

7.关键代码

#include "Cpu.h"
#include "delay.h"
#include "uart.h"
#include"key.h"
#include"oled.h"
  volatile int exit_code = 0;

#define LED1(x)  PINS_DRV_WritePin(PTD,16,!x);
#define LED2(x)  PINS_DRV_WritePin(PTD,15,!x);
#define LED3(x)  PINS_DRV_WritePin(PTD,1,!x);
#define LED4(x)  PINS_DRV_WritePin(PTD,0,!x);

#define Rx_Filter  0x0	//接收过滤器,0x0表示接收所有报文
char IRQ_CAN0_RX;	//接收中断标志位
char IRQ_CAN1_RX;
char IRQ_CAN2_RX;
can_message_t recvMsg_CAN0;	//接收报文结构体
can_message_t recvMsg_CAN1;
can_message_t recvMsg_CAN2;

#define RX_MAILBOX_CAN0  (0UL)	//接收邮箱号
#define TX_MAILBOX_CAN0  (1UL)	//发送邮箱号

#define RX_MAILBOX_CAN1  (2UL)
#define TX_MAILBOX_CAN1  (3UL)

#define RX_MAILBOX_CAN2  (4UL)
#define TX_MAILBOX_CAN2  (5UL)


/*CAN0回调函数*/
void CAN0_Callback_Func (uint32_t instance,can_event_t event,uint32_t buffIdx,void *flexcanState)
  {
	(void)flexcanState; //此处防止警报
	(void)instance;
	(void)buffIdx;
	CAN_Receive(&can_pal1_instance, RX_MAILBOX_CAN0, &recvMsg_CAN0); //接收报文并重新注册回调函数 重点
	switch(event) //回调事件
		{
			case CAN_EVENT_RX_COMPLETE: //接收完成 事件
				IRQ_CAN0_RX =1;
				break;
			case CAN_EVENT_TX_COMPLETE: //发送完成事件
				break;
			default:
				break;
		}
  }


void CAN0_Init(void)
{
	// CAN0初始化配置
	CAN_Init(&can_pal1_instance, &can_pal1_Config0);
	can_buff_config_t Rx_buffCfg =  {
		.enableFD = true,	////启用FD模式
		.enableBRS = true,	////启用BRS模式, 采用不同的波特率发送数据
		.fdPadding = 0U,	////填充字节数
		.idType = CAN_MSG_ID_STD,	////消息ID类型,标准类型
		.isRemote = false	////是否远程帧(遥控针)
	};
	can_buff_config_t Tx_buffCfg =  {
		.enableFD = true,	////启用FD模式
		.enableBRS = true,	////启用BRS模式, 采用不同的波特率发送数据
		.fdPadding = 0U,	////填充字节数
		.idType = CAN_MSG_ID_STD,	////消息ID类型,标准类型
		.isRemote = false	////是否远程帧(遥控针)
	};
	//注册接收配置和MSGID过滤器(如过滤器配置为0x1,则只接受msgid 0x1发来的报文)
	CAN_ConfigRxBuff(&can_pal1_instance, RX_MAILBOX_CAN0, &Rx_buffCfg, Rx_Filter); 
	CAN_ConfigTxBuff(&can_pal1_instance, TX_MAILBOX_CAN0, &Tx_buffCfg); //配置发送
	//设置MSGID的掩码,掩码粗略可以理解为对11bit MSGID地址的过滤
	//如果某bit位需要过滤设置为1,不过滤设置为0,例如掩码设置为0x7ff则过滤全部标准id,如果设置为0x7fe,这只能接受0x01的报文(不存在0x0的地址)*/
	CAN_SetRxFilter(&can_pal1_instance,CAN_MSG_ID_STD,RX_MAILBOX_CAN0,0); //设置MSGID掩码,
	CAN_InstallEventCallback(&can_pal1_instance,&CAN0_Callback_Func,(void*)0); //注册回调函数
	CAN_Receive(&can_pal1_instance, RX_MAILBOX_CAN0, &recvMsg_CAN0); //*****重点****此函数不只有接收作用 还有续订回调函数的作用.
}

int main(void)
{
  /* Write your local variable definition here */
	uint8_t pinstate;
	int MCU_Freq;

	
  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
  #ifdef PEX_RTOS_INIT
    PEX_RTOS_INIT();                   /* Initialization of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of Processor Expert internal initialization.                    ***/

	CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
	CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);
	MCU_Freq = delay_init();//初始化delay函数
	PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr); //初始化IO
	I2C_MasterInit(&i2c1_instance, &i2c1_MasterConfig0);//初始化I2C外设,用于OLED通讯
	LPUART_DRV_Init(INST_LPUART1, &lpuart1_State, &lpuart1_InitConfig0); //初始化串口

	CAN0_Init(); //S32K144 使用CANFD时只能使用CAN0 初始化其他CAN时会导致hardfault

	oled_init(); //OLED配置参数初始化
	OLED_TITLE((uint8_t*)"S32K144",(uint8_t*)"01_BASE");//OLED显示标题
	u1_printf("初始化完毕,MCU运行频率为 %d Mhz \r\n",MCU_Freq);
    while(1)
    {
		pinstate = KEY_Proc (0);
		if(pinstate ==BTN1_PRES )
		{
			u1_printf("KEY1 CAN0发送报文\r\n");
			can_message_t Tx_msg = {
				.cs = 0U,	//发送报文的控制和状态字节
				.id = 0x1,	//发送报文的ID号
				.data[0] = 0x11,	//发送报文的第一个数据字节
				.data[1] = 0x22,	//发送报文的第二个数据字节
				.data[2] = 0x33,	//发送报文的第三个数据字节
				.data[3] = 0x44,	//发送报文的第四个数据字节
				.data[4] = 0x55,	//发送报文的第五个数据字节
				.data[5] = 0x66,	//发送报文的第六个数据字节
				.data[6] = 0x77,	//发送报文的第七个数据字节
				.data[7] = 0x88,	//发送报文的第八个数据字节
				.length = 8,	//发送报文的长度
			};
			CAN_Send(&can_pal1_instance, TX_MAILBOX_CAN0, &Tx_msg); //发送报文
		}
		if(IRQ_CAN0_RX ==1) //接收中断标志位
		{
			int i;
			u1_printf("CAN0 RECV ID:0x%x \r\n",recvMsg_CAN0.id); //打印接收报文的ID号
			for(i=0; i<recvMsg_CAN0.length;i++) //打印接收报文的所有数据字节
			{
				u1_printf("Data %d : %x\r\n",i,recvMsg_CAN0.data[i]); //打印接收报文的第i个数据字节
				if(i==recvMsg_CAN0.length-1) u1_printf("***************\r\n"); //打印分隔符
			}
			IRQ_CAN0_RX=0; //清除接收中断标志位
		}
    }
  /*** Don't write any code pass th5is line, or it will be deleted during code generation. ***/
  /*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
  #ifdef PEX_RTOS_START
    PEX_RTOS_START();                  /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
  #endif
  /*** End of RTOS startup code.  ***/
  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
  for(;;) {
    if(exit_code != 0) {
      break;
    }
  }
  return exit_code;
  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

8.实验现象

实验现象发现,接收正常,可是本人发送CAN报文给分析仪,识别出来却是标准远程CAN,如果有大佬,能帮我看看什么原因吗,
在这里插入图片描述
抓取波形发现:
与传统CAN相比,CAN FD取消了远程帧,用RRS位替换了RTR位,为常显性;
RTR(Remote Transmission Request Bit):远程发送请求位,RTR位在数据帧里必须是显性,而在远程帧里为隐性
RRS(Remote Request Substitution):远程请求替换位,即传统CAN中的RTR位,CAN FD中为常显性
发送波形的(RRS/RTR位)发现是隐性电平,而不是默认的常显性。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值