如前所述,由于 CAN 通信可能很忙,因此设计使用邮箱 1-8 发送消息,使用邮箱 9-16 接收消息。
接收邮箱9-16设置为接收所有消息。使用can工具软件一次发送5条消息。由于邮箱号码越小,优先级越高,因此预计消息应该按顺序接收并保存到邮箱9~13。
实测发现只有9号邮箱收到了第一帧报文,其余四帧没有被其他邮箱收到而是被丢弃了。
请问这是怎么回事?应该如何配置呢?请帮忙回复,谢谢!
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.
如前所述,由于 CAN 通信可能很忙,因此设计使用邮箱 1-8 发送消息,使用邮箱 9-16 接收消息。
接收邮箱9-16设置为接收所有消息。使用can工具软件一次发送5条消息。由于邮箱号码越小,优先级越高,因此预计消息应该按顺序接收并保存到邮箱9~13。
实测发现只有9号邮箱收到了第一帧报文,其余四帧没有被其他邮箱收到而是被丢弃了。
请问这是怎么回事?应该如何配置呢?请帮忙回复,谢谢!
配置函数:
/******************************************************************************
初始化发送缓冲,扩展帧
******************************************************************************/
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一致的消息。