CAN协议报文格式:Motorola和Intel格式的区别

DBC协议就是Database CAN的缩写。
多说无益,看图:

在这里插入图片描述


分割线
下面是准备更新的草稿2020-10-08


CAN的帧格式

CAN的帧格式一共有5种:数据帧(发送数据)、遥控帧(读取数据)、错误帧(通知其他设备错误)、过载帧(没准备好)、帧间隔。(括号中的内容是个人理解的,有错误的话各位大佬告诉我)

  1. SOF起始帧 显性电平
  2. RTR远程帧(0,数据帧;1,远程帧),远程帧可以理解为请求帧,A发送远程帧(请求帧)给B,B收到后返回一个数据帧给A。
  3. IDE标识符选择位(0,使用标准标识符;1(隐性),使用扩展标识符),拓展地址:由原来的11bit拓展为29bit。
  4. SRR位为代替远程请求位,为隐性位,它代替了标准帧中的RTR位。
  5. DLC段为数据长度表示段,DLC段有效值为0~8
  6. ACK返回帧,隐性电平,收到显性电平代表通信成功
  7. EOF结束帧 7bit隐性电平
  8. r0、r1表示保留 必须全部因为显性电平

ID越小,仲裁权越高,ID地址禁止高7位地址都为隐性电平,这代表停止帧。

我就学了数据帧和远程帧,因此只对其进行总结。

在这里插入图片描述

下图为标准帧的时序图,可以与上图一一对应。
在这里插入图片描述
拓展帧时序
在这里插入图片描述
下面是拓展帧,没解释,看看波形就好:
在这里插入图片描述
可以看到它没有数据,只有个DLC(数据长度)。

上述是物理层,理解了对写程序很有帮助。

Stm32的CAN波特率计算:

在这里插入图片描述

波特率 = 1 / 最小位周期

可以根据上图看到,一个最小位采样周期由三部分组成:

Tq = ( BRP + 1 ) × tPCLK——————BRP 在 CAN_BTR寄存器中设置
SYNC_SEG(同步段)—————————1个Tq
BS1(Bit SEG 1——位段1)——————几个Tq是由CAN_BTR寄存器的TS1位决定的
BS2(Bit SEG 2——位段2)——————几个Tq是由CAN_BTR寄存器的TS2为决定的
在这里插入图片描述

带入上述公式最后简化得到下式:

在这里插入图片描述

(时钟频率不一定是APB1,不同的型号CAN外设可能使用的时钟不同)

我的片子APB1设置为36MHz,想设置为250kbps的波特率,因此带入公式为:

36000000/25000 = (TS1 + TS2 + 3) * (BRP + 1) = 144
自己设置TS1、TS2、BRP,注意不要超出范围,同时TS1和TS2相差不多。
因此 TS1 = 5;TS2 = 4;BRP = 11;

STM32的筛选器

在这里插入图片描述
F303有14组,F103、F407、F429有28组。

FDCAN

STM32G4、H7支持FDCAN。
在这里插入图片描述
FDCAN的DLC(数据长度)8以内都是正常的,大于8以后如上表所示。
在这里插入图片描述

代码

typedef union
{
	u8 CAN_8Data[8];
	u32 CAN_32Data[2];
}CAN_Data_Union;

typedef struct 
{
	u8 IDE;
	u8 RTR;
	u32 Addr;
	u8 DLC;
	CAN_Data_Union CAN_Data;
}CAN_Message;

u8 CAN_Init(void)
{
	u16 wait_time = 0x2000;
	CAN1->MCR |= CAN_MCR_RESET;
	CAN1->MCR = CAN_MCR_NART | CAN_MCR_INRQ;
	while((!(CAN1->MSR & CAN_MSR_INAK)) && (--wait_time));
	if(wait_time)
	{
		CAN1->BTR = (5 << CAN_BTR_TS1_Pos)\
					| (4 << CAN_BTR_TS2_Pos)\
					| (11 << CAN_BTR_BRP_Pos);//250kbps
		
		CAN1->MCR &= ~CAN_MCR_INRQ;//退出初始化
		wait_time = 0x2000;
		while((CAN1->MSR & CAN_MSR_INAK) && (--wait_time));
		if(wait_time)
		{
			CAN1->FMR |= CAN_FMR_FINIT;//滤波器初始化模式
			CAN1->FA1R = 0;//关闭所有组筛选器
			CAN1->FM1R |= CAN_FM1R_FBM0;//组0列表模式
			CAN1->FS1R = 0;//尺度为16bit
			CAN1->FFA1R = 0;//都给FIFO0
			CAN1->sFilterRegister[0].FR1 = (0x209 << 5) | (0 << 4) | (0 <<3 ) | 0x00
										|(0x209 << 21) | (1 << 20) | (0 <<19 ) | (0x00 << 16);
			CAN1->sFilterRegister[0].FR2 = (0x609 << 5) | (0 << 4) | (0 <<3 ) | 0x00// 0110 0000 1001
										|(0x609 << 21) | (1 << 20) | (0 <<19 ) | (0x00 << 16);
			CAN1->FA1R = CAN_FA1R_FACT0;//启动组0筛选器
			CAN1->FMR &= ~CAN_FMR_FINIT;//退出滤波器初始化模式
			CAN1->IER = CAN_IER_FMPIE0;//开启FIFO0的接收中断
		}
		else
		{
			return FAILED;
		}
	}
	else
	{
		return FAILED;
	}
	return SUCCEED;
}
u8 CAN_SendData()
{
	u8 free_box;
	if(CAN1->TSR & CAN_TSR_TME0)
	{
		free_box = 0;
	}
	else if(CAN1->TSR & CAN_TSR_TME1)
	{
		free_box = 1;
	}
	else if(CAN1->TSR & CAN_TSR_TME2)
	{
		free_box = 2;
	}
	else
	{
		return 0xff;
	}

	CAN1->sTxMailBox[free_box].TDTR = CAN_SendBuffer.DLC;
	if(CAN_SendBuffer.RTR)
	{
		if(CAN_SendBuffer.IDE)
		{
			CAN1->sTxMailBox[free_box].TIR = (CAN_SendBuffer.Addr << CAN_TIR_EXID_Pos) | CAN_TIR_IDE | CAN_TIR_RTR | CAN_TIR_TXRQ;
		}
		else
		{
			CAN1->sTxMailBox[free_box].TIR = (CAN_SendBuffer.Addr << CAN_TIR_STID_Pos) | CAN_TIR_RTR | CAN_TIR_TXRQ;
		}							
	}
	else
	{
		CAN1->sTxMailBox[free_box].TDHR = CAN_SendBuffer.CAN_Data.CAN_32Data[1];
		CAN1->sTxMailBox[free_box].TDLR = CAN_SendBuffer.CAN_Data.CAN_32Data[0];
		if(CAN_SendBuffer.IDE)
		{
			CAN1->sTxMailBox[free_box].TIR = (CAN_SendBuffer.Addr << CAN_TIR_EXID_Pos) | CAN_TIR_IDE | CAN_TIR_TXRQ;
		}
		else
		{
			CAN1->sTxMailBox[free_box].TIR = (CAN_SendBuffer.Addr << CAN_TIR_STID_Pos) | CAN_TIR_TXRQ;
		}
	}
	return free_box;
}

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页