MPC5744P-CAN模块

1、CAN模块结构

5744CAN模块主要由CHI(Control Host Interface)、PE(Protocol Engine)和MBs三个部分组成,其中CHI负责发送仲裁和接收匹配,PE负责时钟等的配置,MBs进行消息的存储。结构如下图所示:
在这里插入图片描述

2、MB(Message Buffer)结构

5744含有多达64个MB(Mailbox)进行数据的收发,通过配置对应MB的C/S寄存器来进行数据发送或接收。其结构如下:
在这里插入图片描述

  • CODE 缓存器码,是进行缓存器匹配和仲裁过程的一部分,编码如下所示:
    0b0000 MB用于接收且未激活
    0b0100 MB用于发送、激活并且为空,准备接收数据
    0b0010 MB用于接收且为满
    0b0110 MB用于接收且为OVERRUN,并且被overwrite
    0b1010 MB接收到一个远程帧数据并发送一帧数据作为回应
    0bxxx1 MB用于接收且正在更新MB的内容,此时CPU禁止范围MB。
    0b1000 MB为用于发送且未激活
    0b1001 MB用于发送且被中止
    0b1100 MB用于发送,当RTR为0时内部消息为数据帧,当 RTR为1时,内部消息为远程帧
    0b1110 MB用于发送,为进入的远程请求帧发送一帧数据作为回应

  • SRR 替代远程请求 固定为隐形,该位发送时必须被设置为1,若接收到时不为1,则仲裁丢失

  • IDE ID标识位 1:MB内为扩展帧 0:MB内为标准帧

  • RTR 远程传输请求 1 :当前MB有一个远程请求帧要传输 0:当前MB有一个数据帧要传输

  • DLC 当前MB内数据的字节长度

  • TIMESTAMP 自由运行时间戳

  • PRIO 本地优先级,使能情况下,对于发送信箱有意义,参与发送仲裁过程

  • ID 帧ID

  • DATA BYTE0-7 数据域

3、模块配置

1、波特率设置
CAN时钟可选择外设时钟或晶振时钟作为时钟源,再时钟源选定以后可进行波特率的配置。公式如下:
在这里插入图片描述
在这里插入图片描述其中Time Quanta的组成如下:
在这里插入图片描述则可通过配置PRESDIV、PSEG1、PSEG2、PROPSEG的值配置不同的波特率,综合上述两个式子波特率计算公式为:

Bit Rate=
fcanclk/([1 + (PSEG1 + 1) + (PSEG2 + 1) + (PROPSEG + 1)] x (PRESDIV + 1))

其中各个值的范围和彼此的限制关系如下:
在这里插入图片描述由于CAN模块具有较多的MB,在进行发送仲裁的时候需要耗费一定的时间,为了给发送仲裁留充足的时间,外设时钟(控制CHI的时钟)和比特率需要保证一定的比率,也就是在处理每CAN bit的外设时钟数要足够大,计算公式如下:
在这里插入图片描述fsys为系统时钟,即是外设桥时钟,NCCP就是每CAN bit 耗费的外设时钟数,随着采用MB的数目的增加应调整NCCP的值,对应关系如下:
在这里插入图片描述2、CAN模块配置过程
1)多路复用功能选择
2)运行模式选择
3)进行时钟源的选择(需要先失能CAN模块然后再打开);
4)使能Frzee模式并进入Frzee模式以进行波特率配置;
5)进行波特率的配置
6)设置发送MB
7)设置接收MB(使能对应接收中断并设置中断优先级)
8)退出Frzee模式并确认
3、示例代码

/******************************************
 * 名称        CAN_CAN0_Init
 * 说明        进行CAN0的初始化
 * 输入参数     无
 * 返回值       无
 * 示例         CAN_CAN0_Init();//进行CAN0的初始化
 ******************************************
 */
void CAN_CAN0_Init()
{
	uint8_t i=0;

	/*管脚复用设置*/
	SIUL2.MSCR[16].B.SSS=1;    //PB0复用为CAN0_TX
	SIUL2.MSCR[16].B.OBE=1;
	SIUL2.MSCR[16].B.SRC=3;

	SIUL2.MSCR[17].B.IBE=1;    //PB1复用为CAN0_RX
	SIUL2.IMCR[32].B.SSS=2;

	MC_ME.PCTL79.B.RUN_CFG=0;  //选择运行模式0

	CAN_0.MCR.B.MDIS=1;        //关闭CAN模块
	CAN_0.CTRL1.B.CLKSRC=0;    //选择晶振作为CAN时钟源
	CAN_0.MCR.B.MDIS=0;        //开启CAN模块
	
	CAN_0.MCR.B.FRZ=1;         //允许进入Frzee 模式
	CAN_0.MCR.B.HALT=1;        //请求进入Frzee 模式
	while(!CAN_0.MCR.B.FRZACK);//确认进入frzee 模式

	CAN_0.CTRL1.B.PRESDIV=9;   //bit rate=fcanclk/([1+(PSEG1+1)+(PSEG2+1)+(PROPSEG+1)]x(PRESDIV+1))
	CAN_0.CTRL1.B.PSEG1=3;     //=40MHz/((1+4+4+7)*10)=1/4MHz=250kHz
	CAN_0.CTRL1.B.PSEG2=3;
	CAN_0.CTRL1.B.PROPSEG=6;
	CAN_0.CTRL1.B.RJW=3;       //配置 Resync Jump Width为3+1=4


	for(i=0;i<64;i++)          //复位MBs为失活状态
	{
		CAN_0.MB[0].CS.B.CODE=0;
	}

	CAN_0.MB[0].CS.B.CODE=8;    //配置MB0位发送激活状态

	CAN_0.MB[5].CS.B.IDE=1;     //配置MB5接收扩展帧
	CAN_0.MB[5].ID.R=0x18FF9400;//配置要接收的CAN帧IID,需要根据要接收的帧ID确定
	CAN_0.MB[5].CS.B.CODE=4;    //配置MB5为接收激活状态
	CAN_0.IMASK1.R = 0x00000020;//使能MB5接收和发送中断
	INTC_0.PSR[523].R=0x800B;   //配置MB5中断优先级

	CAN_0.MCR.B.MAXMB=63;       //选择最大可以数据缓存为默认,默认为63
	CAN_0.MCR.B.HALT=0;         //退出 Frzee模式
	while(CAN_0.MCR.B.FRZACK & CAN_0.MCR.B.NOTRDY);  //等待退出Frzee模式
}

4、传输过程

1、发送过程
1)检测对应标志位是否被置位并清除;
2)如果要使用的MB为激活状态,则写入中止码(0b1001)中止传输过程(或直接写入失活码(0b1000)失活对应MB);
3)写入ID、数据字节、数据长度,设置SRR、RTR、IDE等;
4)写入激活码激活MB参与发送仲裁进行传输。
2、示例代码

/*******************************************************
 * 名称         CAN_CAN0_Send
 * 说明         采用CAN0发送指定数据
 * 输入参数
 *             can_msg
 *               要发送的CAN信息
 * 返回值       无
 * 示例         CAN_CAN0_Send(can_msg);//发送CAN信息can_msg
 *******************************************************
 */
void CAN_CAN0_Send(const CAN_Msg_Struct can_msg)
{
	uint8_t i=0;
	static uint32_t counter=0;
	CAN_0.MB[0].CS.B.CODE=0b1000;                     //失活MB0
	CAN_0.MB[0].ID.R=can_msg.can_msg_id;       //设置ID
	for(i=0;i<8;i++)
		CAN_0.MB[0].DATA.B[i]=can_msg.can_msg_data[i];//设置数据
	CAN_0.MB[0].CS.B.DLC=can_msg.can_msg_len;         //设置数据长度
	CAN_0.MB[0].CS.B.SRR=1;                           //设置SRR 强制为1
	CAN_0.MB[0].CS.B.IDE=1;                           //发送帧为扩展帧
	CAN_0.MB[0].CS.B.RTR=0;                           //非请求帧
	CAN_0.MB[0].CS.B.CODE=0b1100;                     //设置MB0为发送激活 参与发送仲裁进行发送
}

3、接收过程
接收过程一般采用中断,本文只介绍CAN接收过程,具体中断配置参见PIT模块的介绍。
1)为保证数据完整新,先读取MB的C/S寄存器上锁MB;
2)读取ID、数据长度、数据等;
3)读取自由运行定时器解锁MB;
4)清零对应标志位;
4、示例代码

/***************************************
 * 函数名        CAN_CAN0_Rx4_7_Isr
 * 功能          CAN_0 MB4-7中断接收函数
 * 输入参数      无
 * 返回值        无
 ***************************************
 */
void CAN_CAN0_Rx4_7_Isr()
{
	uint8_t i=0;
	uint32_t dummy=0;
	dummy=CAN_0.MB[5].CS.R;                                 //上锁MB5
	GL_Can_Msg.can_msg_id=CAN_0.MB[5].ID.R;           //读取ID
	GL_Can_Msg.can_msg_len=CAN_0.MB[5].CS.B.DLC;             //读取数据长度
	for(i=0;i<GL_Can_Msg.can_msg_len;i++)                    //读取数据
	{
		GL_Can_Msg.can_msg_data[i]=CAN_0.MB[5].DATA.B[i];
	}
	dummy=CAN_0.TIMER.R;                                     //解锁MB5
	//GPIO_ToggleBit(GPIO_PORTC,GPIO_PIN11);
	CAN_0.IFLAG1.B.BUF5I= 1;
}

猜你喜欢

转载自blog.csdn.net/sinat_31773903/article/details/88895239