TMS320F28069之CAN通信

项目场景:

通过TMS320F28069与北京伟恩斯技术有限公司的VSMD136_025T步进电机驱动控制器实现CAN通信,控制电机的转速、使能、细分、加速、减速等控制与读写。


CAN通信介绍

  • 通过两条通信线(双绞线)产生的电压差传输数据,一个CAN网络里的所有节点都挂在这两条通信线上,使用差分信号半双工通信。

  • CAN 使用称为 CANH / CANL 的通信线路执行传输和接收。没有电位差的信号称为隐性(Recessive)信号,其逻辑值为1。具有电位差的信号称为显性(Dominant)信号,其逻辑值0。如果通信总线上发生显性和隐性(Recessive)冲突,则显性(Dominant)优先。总线空闲时保持隐性。

  • CAN的数据定义了有5种帧类型:

帧用途
数据帧由于节点向外传输数据
遥控帧用于向远端节点请求数据
错误帧用于向远端节点通知检验错误,请求重新发送上一个数据
过载帧用于通知远端节点
帧间隔用于将数据帧和遥控帧与前面的帧分离开来

TMS320F28069之CAN通信:

  • 如下图是由一个 CAN协议内核 (CPK) 和一个消息控制器组成,根据 CAN 协议,CPK 的两个功能的是解码在 CAN 总线上接收到的所有消息,并把这些消息转移到接收缓冲器。CPK 的另一个功能是根据 CAN 协议传输 CAN 总线上的消息。CAN 控制器的消息控制器是负责确定 CPK 接收到的任何信息是否必须被保留以便用于CPU 使用还是被丢弃。在初始化阶段,CPU 指定消息控制器应用所使用的所有消息标识符。根据消息的优先级,消息控制器还负责发送下一条消息传输到 CPK。

在这里插入图片描述

  • 一条消息由 11 或 29 位标识符、一个控制字段,以及多达 8 个数据字节组成。当一条消息必须传输时, 消息控制器把该消息传输到 CPK 的发送缓冲区, 以便在下次总线空闲状态时开始
    传输该消息。 当必须传输多个消息时, 已做好传输准备的、 具有最高优先级的消息将由消息控制器传输到CPK 中。 如果两个邮箱具有相同的优先级, 那么具有较高的号码的邮箱优先传输。
  • 邮箱布局:各个邮箱都由以下四个 32 位寄存器组成:MSGID(存储 ID)、MSGCTRL (定义字节, 传输优先级和远程帧的数目)、 CANMDL ( 4 字节数据)、CANMDH ( 4 字节数据)。结构如下:
    在这里插入图片描述
    发送邮箱
    CPU 将要发送的数据存储在一个配置为发送邮箱的邮箱中。 在把数据和标识符写入到 RAM 中后, 如果相应的 TRS[n] 位已设置, 假如通过设置相应的 CANME.n 位邮箱被启用的话, 则消息被发送。如果不止一个邮箱被设为发送邮箱, 并且不止一个 TRS[n] 位被置位, 则消息从具有最高优先级的邮箱按照优先级下降的次序依次发送。
    接收邮箱
    每个进入消息的标识符与保存在使用适当屏蔽的接收邮箱内的标识符相比较。 当两者匹配时, 接收到的标注符, 控制位和数据字节将被写进匹配的 RAM 位置。同时,相应的接收消息等待位,RMP[n] ( RMP.31-0 ) ) 被设置, 如果被启用则产生一个接收中断。 如果未检测到匹配, 则消息不存储。当消息接收后, 消息控制器从邮箱编号最高的邮箱开始搜索一个匹配的标识符。 在 SCC 兼容模式下的,eCAN 的邮箱 15 具有最高接收优先级; 在 eCAN 模式下, eCAN 的邮箱 31 具有最高接收优先级。

程序:


unsigned char pump_tx_len;
unsigned long pump_msgid;		   //接收存储信息
unsigned char pump_rcvBuf[128];    //接受数据缓存
unsigned char pump_rcvLen;         //接收数据长度
p_pumpcomm_callback				pumpCommFunc  //接收数据 回调函数
void InitECana(void)        // Initialize eCAN-A module
{
   struct ECAN_REGS ECanaShadow;
    EALLOW;     // EALLOW enables access to protected bits
/* Configure eCAN RX and TX pins for CAN operation using eCAN regs*/
    ECanaShadow.CANTIOC.all = ECanaRegs.CANTIOC.all;
    ECanaShadow.CANTIOC.bit.TXFUNC = 1;
    ECanaRegs.CANTIOC.all = ECanaShadow.CANTIOC.all;
    ECanaShadow.CANRIOC.all = ECanaRegs.CANRIOC.all;
    ECanaShadow.CANRIOC.bit.RXFUNC = 1;
    ECanaRegs.CANRIOC.all = ECanaShadow.CANRIOC.all;
/* Configure eCAN for HECC mode - (reqd to access mailboxes 16 thru 31) */
                                    // HECC mode also enables time-stamping feature
    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.SCB = 1;
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
/* Initialize all bits of 'Message Control Register' to zero */
// Some bits of MSGCTRL register come up in an unknown state. For proper operation,
// all bits (including reserved bits) of MSGCTRL must be initialized to zero
    ECanaMboxes.MBOX0.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX1.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX2.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX3.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX4.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX5.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX6.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX7.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX8.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX9.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX10.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX11.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX12.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX13.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX14.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX15.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX16.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX17.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX18.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX19.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX20.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX21.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX22.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX23.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX24.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX25.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX26.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX27.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX28.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX29.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX30.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX31.MSGCTRL.all = 0x00000000;

// TAn, RMPn, GIFn bits are all zero upon reset and are cleared again
//  as a matter of precaution.
    ECanaRegs.CANTA.all = 0xFFFFFFFF;   /* Clear all TAn bits */
    ECanaRegs.CANRMP.all = 0xFFFFFFFF;  /* Clear all RMPn bits */
    ECanaRegs.CANGIF0.all = 0xFFFFFFFF; /* Clear all interrupt flag bits */
    ECanaRegs.CANGIF1.all = 0xFFFFFFFF;
/* Configure bit timing parameters for eCANA*/
    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.CCR = 1 ;            // Set CCR = 1
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
    // Wait until the CPU has been granted permission to change the configuration registers
    do
    {
      ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    } while(ECanaShadow.CANES.bit.CCE != 1 );       // Wait for CCE bit to be set..

    ECanaShadow.CANBTC.all = 0;
    /* The following block is for 80 MHz SYSCLKOUT. (40 MHz CAN module clock Bit rate = 100 Kbps
       See Note at end of file. */
    ECanaShadow.CANBTC.bit.BRPREG = 29;
    ECanaShadow.CANBTC.bit.TSEG2REG = 2;
    ECanaShadow.CANBTC.bit.TSEG1REG = 10;
    ECanaShadow.CANBTC.bit.SAM = 1;
    ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all;

    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.CCR = 0 ;            // Set CCR = 0
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

    // Wait until the CPU no longer has permission to change the configuration registers
    do
    {
      ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    } while(ECanaShadow.CANES.bit.CCE != 0 );       // Wait for CCE bit to be  cleared..

/* Disable all Mailboxes  */
    ECanaRegs.CANME.all = 0;        // Required before writing the MSGIDs
    EDIS;
}
void xd_halCAN_init(void)
{
	struct ECAN_REGS ECanaShadow;
	InitECanGpio();
	MessageReceivedCount = 0;
	ErrorCount = 0;
	PassCount = 0;
	InitECana(); // Initialize eCAN-A module  CANMC
	EALLOW;
	ECanaShadow.CANGAM.all = ECanaRegs.CANGAM.all;
	ECanaShadow.CANGAM.bit.AMI = 0; // Standard and extended frames can be received.接收标识符位必须与MSGID寄存器一致
	ECanaRegs.CANGAM.all = ECanaShadow.CANGAM.all;
	EDIS;
	EALLOW;

	ECanaMboxes.MBOX1.MSGID.bit.IDE = 1;
	ECanaMboxes.MBOX1.MSGID.bit.AAM =0;
	ECanaMboxes.MBOX1.MSGID.bit.AME =0;

	ECanaMboxes.MBOX30.MSGID.bit.IDE =1;
	ECanaMboxes.MBOX30.MSGID.bit.AAM =0;
	ECanaMboxes.MBOX30.MSGID.bit.AME =0;
	
	ECanaMboxes.MBOX1.MSGCTRL.bit.RTR = 0;  //无远程帧
	ECanaMboxes.MBOX30.MSGCTRL.bit.RTR = 0;
	ECanaMboxes.MBOX29.MSGCTRL.bit.RTR = 0;
	ECanaMboxes.MBOX28.MSGCTRL.bit.RTR = 0;
	ECanaMboxes.MBOX27.MSGCTRL.bit.RTR = 0;
	ECanaMboxes.MBOX26.MSGCTRL.bit.RTR = 0;
	EDIS;
	EALLOW;
	ECanaShadow.CANMD.all = ECanaRegs.CANMD.all;
	ECanaShadow.CANMD.all = 0xFFFF0000;
	ECanaRegs.CANMD.all = ECanaShadow.CANMD.all;

	ECanaShadow.CANME.all = ECanaRegs.CANME.all;
	ECanaShadow.CANME.all = 0xFFFFFFFF;
	ECanaRegs.CANME.all = ECanaShadow.CANME.all;

	// Configure the eCAN for self test mode
	// Enable the enhanced features of the eCAN.
	ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
	ECanaShadow.CANMC.bit.STM = 0; // Configure CAN for self-test mode
	ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;
	EDIS;

	//中断配置
	EALLOW;
	ECanaShadow.CANMIM.all = ECanaRegs.CANMIM.all;
	ECanaShadow.CANMIM.all = 0xFFFF0000;
	ECanaRegs.CANMIM.all = ECanaShadow.CANMIM.all;

	ECanaShadow.CANMIL.all = ECanaRegs.CANMIL.all;
	ECanaShadow.CANMIL.all = 0;    //level0
	ECanaRegs.CANMIL.all = ECanaShadow.CANMIL.all;

	ECanaShadow.CANGIM.all = ECanaRegs.CANGIM.all;
	ECanaShadow.CANGIM.bit.I0EN = 1; //can0init
	ECanaRegs.CANGIM.all = ECanaShadow.CANGIM.all;
	EDIS;

	EALLOW;
	PieVectTable.ECAN0INTA = &xd_halCAN_RxFifoIsr;
	PieCtrlRegs.PIEIER9.bit.INTx5 = 1;	// PIE Group 9, Ecan1 CAN-A
	IER |= M_INT9;
	EDIS;
}
//发送数据,发送数据的邮箱ID在初始化中设置完成,接收邮箱ID也在此处更改,
void xd_Pump_can_Send_Data(unsigned int e_id ,unsigned char* data, unsigned char size)
{
	  unsigned int i =0;
 		pump_tx_len =size;
 		ECanaRegs.CANME.all = 0;						//此处必须打开
 		ECanaMboxes.MBOX30.MSGID.all = e_id ;   		//此处根据需要更改为接收信号的ID号。
 		ECanaRegs.CANME.all = 0xFFFFFFFF;   			//此处必须关闭
 		ECanaMboxes.MBOX1.MSGCTRL.bit.DLC = size;
 		switch(pump_tx_len)
 		{
 		case 8:
 			ECanaMboxes.MBOX1.MDH.byte.BYTE7 = data[7];
 		case 7:
 			ECanaMboxes.MBOX1.MDH.byte.BYTE6 = data[6];
 		case 6:
 			ECanaMboxes.MBOX1.MDH.byte.BYTE5 = data[5];
 		case 5:
 			ECanaMboxes.MBOX1.MDH.byte.BYTE4 = data[4];
 		case 4:
 			ECanaMboxes.MBOX1.MDL.byte.BYTE3 = data[3];
 		case 3:
 			ECanaMboxes.MBOX1.MDL.byte.BYTE2 = data[2];
 		case 2:
 			ECanaMboxes.MBOX1.MDL.byte.BYTE1 = data[1];
 		case 1:
 			ECanaMboxes.MBOX1.MDL.byte.BYTE0 = data[0];
 			break;
 		default:break;
 		}
		ECanaRegs.CANTRS.all = 0x00000002;  // Set TRS for all transmit mailboxes
		while(ECanaRegs.CANTA.all != 0x00000002)//;// Wait for all TAn bits to be set..
		{
			if(i>5000)
			{
				break;
			}
			++i;
		}
		ECanaRegs.CANTA.all = 0x00000002;   // Clear all TAn
 		ECanaRegs.CANRMP.bit.RMP30 = 0 ;
}
__interrupt void xd_halCAN_RxFifoIsr(void)     // ECAN-A
{

//	g_halCanCfg.RcvTimeout.timeoutEnable = XD_TRUE;

	if(ECanaRegs.CANRMP.bit.RMP30 == 1)
	{
		pump_msgid = 0;
		pump_rcvLen = 0;
		pump_rcvBuf[7] = 0;
		pump_rcvBuf[6] = 0;
		pump_rcvBuf[5] = 0;
		pump_rcvBuf[4] = 0;
		pump_rcvBuf[3] = 0;
		pump_rcvBuf[2] = 0;
		pump_rcvBuf[1] = 0;
		pump_rcvBuf[0] = 0;

		pump_msgid = (ECanaMboxes.MBOX30.MSGID.all & 0x1FFFFFFF);
		pump_rcvLen = ECanaMboxes.MBOX30.MSGCTRL.bit.DLC;
		switch(pump_rcvLen)
		{
		case 0x08:
			pump_rcvBuf[7] = ECanaMboxes.MBOX30.MDH.byte.BYTE7;
		case 0x07:
			pump_rcvBuf[6] = ECanaMboxes.MBOX30.MDH.byte.BYTE6;
		case 0x06:
			pump_rcvBuf[5] = ECanaMboxes.MBOX30.MDH.byte.BYTE5;
		case 0x05:
			pump_rcvBuf[4] = ECanaMboxes.MBOX30.MDH.byte.BYTE4;
		case 0x04:
			pump_rcvBuf[3] = ECanaMboxes.MBOX30.MDL.byte.BYTE3;
		case 0x03:
			pump_rcvBuf[2] = ECanaMboxes.MBOX30.MDL.byte.BYTE2;
		case 0x02:
			pump_rcvBuf[1] = ECanaMboxes.MBOX30.MDL.byte.BYTE1;
		case 0x01:
			pump_rcvBuf[0] = ECanaMboxes.MBOX30.MDL.byte.BYTE0;
		}
	}
	

	if(pumpCommFunc)
	{
		pumpCommFunc(pump_msgid,pump_rcvBuf,pump_rcvLen);  //回调函数返回数据 
	}

	ECanaRegs.CANRMP.bit.RMP30 = 1;
    ECanaMboxes.MBOX30.MDL.all &= 0x00000000;
    PieCtrlRegs.PIEACK.all |= M_INT9;              // Issue PIE ACK
}


注意事项:

  1. 波特率计算,CAN位时序如下:
    在这里插入图片描述
    在这里插入图片描述
    波特率计算公式如上,其中BRP=BRPreg+1 (CANBTC.23-16)。
    Bit-time = (TSEG1reg + 1) + (TSEG2reg + 1) + 1

2.程序当中,要修改邮箱ID号(MSGID),必须将ECanaRegs.CANME.all=0,修改完ID后,ECanaRegs.CANME.all=0xFFFFFFFF。
3.数据帧由7个段(Field)构成,分别为帧起始,仲裁段,控制段,数据段,CRC段,ACK段和帧结束。遥控帧由6个段构成,即数据帧的7个段去除数据段。
在这里插入图片描述
当发送数据为0x0008019E, 00 ,02。其中ID号为0x0008019E,数据为0x00、0x02,长度为2。使用示波器测试CAN帧数据,示波器电源不接地线,表笔高接CANH,夹子接CANL,发示波器观察时序如下:
在这里插入图片描述

  • CAN协议结构帧中连续出现5个高电平时,需插入一个低电平,如表中红色0。
  • 高电平为显性,逻辑为0,低电平为隐形,逻辑为1。
  • 由于未接其他CAN设备,后面CRC、ACK段、帧结束段没有。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乖巧梦想Fs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值