This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F280025:如何配置DCAN使用多个邮箱来接收消息?

Part Number: TMS320F280025


如前所述,由于 CAN 通信可能很忙,因此设计使用邮箱 1-8 发送消息,使用邮箱 9-16 接收消息。

接收邮箱9-16设置为接收所有消息。使用can工具软件一次发送5条消息。由于邮箱号码越小,优先级越高,因此预计消息应该按顺序接收并保存到邮箱9~13。

实测发现只有9号邮箱收到了第一帧报文,其余四帧没有被其他邮箱收到而是被丢弃了。

请问这是怎么回事?应该如何配置呢?请帮忙回复,谢谢!

  • 不是技术手册中的fifo概念,是想实现多个邮箱来共同接收消息,如果高优先级的邮箱的消息没有及时读出时,也能自动接收消息并存放在次优先级邮箱中,除非没有可用的邮箱才丢弃消息或覆盖已有消息。F280x系列的CAN是有这个功能的。实际应用中CAN ID里面会有可变部分,因此也不可能让某个邮箱去接收固定ID的报文。

  • 你好,我查看下相关资料后回复您。

  • 你好,你这里邮箱9-16是如何设置的?是否使用了过滤功能?能否将过滤功能的设置发上来?9-16邮箱是否允许接收不同邮箱的ID?

    以及利用CAN工具发送的5个信息是使用的一样的ID还是不同的ID?

  • 配置函数:

    /******************************************************************************
    初始化发送缓冲,扩展帧
    ******************************************************************************/
    void CANDriver_Init_TXFIFO(Uint32 u32StartObj,Uint32 u32EndObj)
    {
    	Uint32 u32ObjNo = u32StartObj;
    	while(u32ObjNo <= u32EndObj)
    	{
    		CAN_setupMessageObject(CANDRIVER_BASE, u32ObjNo, 0,
    								CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_TX, 0,
    								CAN_MSG_OBJ_NO_FLAGS , 8);
    		u32ObjNo++;
    	}
    }
    
    /******************************************************************************
    初始化接收缓冲,扩展帧|滤波
    ******************************************************************************/
    void CANDriver_Init_RXFIFO(Uint32 u32StartObj,Uint32 u32EndObj,Uint32 msgID,Uint32 msgIDMask)
    {
    	Uint32 u32ObjNo = u32StartObj;
    	while(u32ObjNo < u32EndObj)
    	{
    		CAN_setupMessageObject(CANDRIVER_BASE, u32ObjNo, msgID,
    								CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, msgIDMask,
    								(CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_NO_FLAGS | CAN_MSG_OBJ_USE_EXT_FILTER | CAN_MSG_OBJ_FIFO), 8);
    		u32ObjNo++;
    	}
    	//最后1个Message Object 设置EoB
    	CAN_setupMessageObject(CANDRIVER_BASE, u32EndObj, msgID,
    							CAN_MSG_FRAME_EXT, CAN_MSG_OBJ_TYPE_RX, msgIDMask,
    							(CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_NO_FLAGS | CAN_MSG_OBJ_USE_EXT_FILTER ), 8);
    }

    循环接收函数:

    /******************************************************************************
    Function Name		: CANDriver_Rx_Loop
    Function Descriptions:自动从接收FIFO拷贝数据到接收缓冲区
    Parameter Name list	:
    ReturnType			:
    Refer doctuments	:
    ******************************************************************************/
    void	CANDriver_Rx_Loop(void)
    {
    	uint16_t msgCtrl;
    	//依次取出Message Object中数据,逐个存入接收缓冲
    	uint32_t u32Obj;
    	for(u32Obj = CANDRIVER_RXFIFO_OBJECT_FIRST;	u32Obj <= CANDRIVER_RXFIFO_OBJECT_LAST; u32Obj++)
    	{
    		// 接收缓冲区满,直接退出
    		if(FIFO_IsFull_Rx())	return;
    
    		if(HWREG_BP(CANDRIVER_BASE + CAN_O_NDAT_21) & (0x00000001 << (u32Obj - 1)))
    		{
    			// transfer message object to IF2
    			HWREG_BP(CANDRIVER_BASE + CAN_O_IF2CMD) =	(
    									(uint32_t)(CAN_IF2CMD_DATA_A | CAN_IF2CMD_DATA_B) |		// transfer Data Bytes 0 ~ 7
    									(uint32_t)CAN_IF2CMD_CONTROL | 							// transfer Message Control Bits
    									(uint32_t)CAN_IF2CMD_ARB 	 |							// transfer Message Arb Bits
    									(uint32_t)(u32Obj & CAN_IF2CMD_MSG_NUM_M));				// Number of message object which is used for data transfer
    			
    			//等待Message Object -> IFx 传输完成
    			while((HWREGH(CANDRIVER_BASE + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) == CAN_IF2CMD_BUSY);
    			//检查Message Object NewData 标志
    			msgCtrl	= HWREGH(CANDRIVER_BASE + CAN_O_IF2MCTL);
    			if((msgCtrl & CAN_IF2MCTL_NEWDAT) == CAN_IF2MCTL_NEWDAT)
    			{
    				canRxFrame.Data.DWords.DATA  = HWREG(CANDRIVER_BASE + CAN_O_IF2DATA);
    				canRxFrame.Data.DWords.DATB  = HWREG(CANDRIVER_BASE + CAN_O_IF2DATB);
    				canRxFrame.DataLen           = (msgCtrl & CAN_IF2MCTL_DLC_M);
    				canRxFrame.ID.all            = HWREG_BP(CANDRIVER_BASE + CAN_O_IF2ARB) & 0x1FFFFFFF;
    
    				// 清除NewData 标志
    				HWREG_BP(CANDRIVER_BASE + CAN_O_IF2CMD) = ((uint32_t)CAN_IF2CMD_TXRQST | (u32Obj & CAN_IF2CMD_MSG_NUM_M));
    
    				// 等待 IFx -> Message Object  传输完成
    				while((HWREGH(CANDRIVER_BASE + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) == CAN_IF2CMD_BUSY);
    
    				// 将读取的CanFrame放入缓冲区
    				FIFO_PushIn_Rx(&canRxFrame);
    
    				_rxCounter++;
    			}
    		}
    	}
    }

    循环发送函数

    /******************************************************************************
    自动发送缓冲区数据到发送FIFO
    ******************************************************************************/
    void	CANDriver_Tx_Loop(void)
    {
    	//发送缓冲为空
    	if(FIFO_IsEmpty_Tx())	return;
    
    	//发送FIFO还有Message Object待处理
    	if(HWREG_BP(CANDRIVER_BASE + CAN_O_TXRQ_21) & CANDRIVER_TXFIFO_TXRQ_MASK)	return;
    
    	uint32_t msgCtrl = 0U;
    	//依次取出发送缓冲中数据,逐个写入Message Object
    	Uint32 u32Obj = CANDRIVER_TXFIFO_OBJECT_FIRST;
    	for(;	u32Obj <= CANDRIVER_TXFIFO_OBJECT_LAST; u32Obj++)
    	{
    		if(FIFO_PopOut_Tx(&canTxFrame))	//有待发送的帧
    		{
    			//读取MessageObject Control寄存器到IF1
    			HWREG_BP(CANDRIVER_BASE + CAN_O_IF1CMD) = ((uint32_t)CAN_IF1CMD_CONTROL | (u32Obj & CAN_IF1CMD_MSG_NUM_M));
    			//等待Message Object -> IFx 传输完成
    			while((HWREGH(CANDRIVER_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY);
    			//获取Control寄存器值
    			msgCtrl = HWREGH(CANDRIVER_BASE + CAN_O_IF1MCTL);
    			//更新DLC,每帧发送的字节数不一定是 8
    			HWREGH(CANDRIVER_BASE + CAN_O_IF1MCTL) = (msgCtrl & (uint16_t)(~CAN_IF1MCTL_DLC_M)) | (canTxFrame.DataLen & CAN_IF1MCTL_DLC_M);
    			//更新Data
    			HWREG_BP(CANDRIVER_BASE + CAN_O_IF1DATA)	= canTxFrame.Data.DWords.DATA;
    			HWREG_BP(CANDRIVER_BASE + CAN_O_IF1DATB)	= canTxFrame.Data.DWords.DATB;
    			//更新Arb Id,
    			HWREG_BP(CANDRIVER_BASE + CAN_O_IF1ARB)		= canTxFrame.ID.all | CAN_IF1ARB_MSGVAL | CAN_IF1ARB_XTD | CAN_IF1ARB_DIR;
    			//开始 IFx -> Message Object方向的传输
    			HWREG_BP(CANDRIVER_BASE + CAN_O_IF1CMD) = (
    									(uint32_t)(CAN_IF1CMD_DATA_B | CAN_IF1CMD_DATA_A) |		// transfer Data Bytes 0 ~ 7
    									(uint32_t)CAN_IF1CMD_DIR |								// Direction = Write,IFx -> Message Object
                                        (uint32_t)CAN_IF1CMD_TXRQST |							// Set TxRqst in message object
    									(uint32_t)CAN_IF1CMD_CONTROL |							// transfer Message Control Bits
    									(uint32_t)CAN_IF1CMD_ARB |								// transfer Message Arb
                                        (u32Obj & CAN_IF1CMD_MSG_NUM_M));						// Number of message object which is used for data transfer
    
    		}
    		else	//已经没有待发送帧了,退出循环
    		{
    			break;
    		}
    	}
    }

    初始化:

    #define CANDRIVER_RXFIFO_OBJECT_FIRST		1				//接收FIFO:邮箱1~邮箱16
    #define CANDRIVER_RXFIFO_OBJECT_LAST		16
    
    #define CANDRIVER_TXFIFO_OBJECT_FIRST		17				//发送FIFO:邮箱17~邮箱32
    #define CANDRIVER_TXFIFO_OBJECT_LAST		32
    
    CANDriver_Init_TXFIFO(CANDRIVER_TXFIFO_OBJECT_FIRST,CANDRIVER_TXFIFO_OBJECT_LAST);
    CANDriver_Init_RXFIFO(CANDRIVER_RXFIFO_OBJECT_FIRST,CANDRIVER_RXFIFO_OBJECT_LAST,rxMsgID,rxMsgIDMask);

    9-16邮箱均设置成启用滤波,并且Mask设置为0(即接收所有ID的消息)

    邮箱16,设置EoB。

    注意即便不需要滤波功能,也要开启滤波,否则邮箱只能接收与其ArbID一致的消息。

  • 可以参考一下楼上的回复,感谢barbecue的分享

  • 好的,我try一下,谢谢!

  • 相比ECAN的OPC寄存器来说,这个要复杂很多。