// ============================================================================ // 函数名称: CANMessageReceive() // 函数功能: CAN接收函数 // 输 入: ui32Base is the base address of the CAN controller //! ui32ObjID is the object number to configure (1-32). //! pMsgObject is a pointer to a structure containing message object settings. //! eMsgType indicates the type of message for this object. // 输 出: 无 // 扇 入: BspCan_CanRx // CAN初始化 // 扇 出: 无 // 其它说明: 无 // =========================================================================== int16 CANMessageReceive(Uint32 ui32Base, Uint32 ui32ObjID, tCANMsgObject *pMsgObject, bool bClrPendingInt) { Uint32 ui32CmdMaskReg = 0; Uint32 ui32MaskReg = 0; Uint32 ui32ArbReg = 0; Uint32 ui32MsgCtrl = 0; Uint16 S_Temp = 0; int16 Rtv = SYS_CAN_OP_OK; ui32CmdMaskReg = (CAN_IF2CMD_DATA_A | CAN_IF2CMD_DATA_B | CAN_IF2CMD_CONTROL | CAN_IF2CMD_MASK | CAN_IF2CMD_ARB); // This is always a read to the Message object as this call is setting a message object. if(bClrPendingInt) // Clear a pending interrupt and new data in a message object. { ui32CmdMaskReg |= CAN_IF2CMD_CLRINTPND | CAN_IF2CMD_TXRQST; } else { ; } CAN_ADDR16(ui32Base + CAN_O_IF2CMD + 2) = ui32CmdMaskReg >> 16; // Set up the request for data from the message object. CAN_ADDR16(ui32Base + CAN_O_IF2CMD) = ui32ObjID & CAN_IF2CMD_MSG_NUM_M; // Transfer the message object to the message object specified by ui32ObjID. while(((CAN_ADDR16(ui32Base + CAN_O_IF2CMD) & \ CAN_IF2CMD_BUSY) != 0) && (S_Temp < 1000)) // 检查是否处于空闲状态,如果这里通不过,那下面的寄存器都无法操作,因为寄存器都受busy保护 { DELAY_US(1); // 最多等待1ms后退出 S_Temp++; // 通过做实验,这里在初始化的时候不会进入 } if (S_Temp >= 1000) { S_Temp = 0; // 退出后将等待计数清理处理 Rtv = SYS_CAN_OP_ERROR; // 返回CAN接收错误 } else { S_Temp = 0; } ui32MaskReg = CAN_ADDR32(ui32Base + CAN_O_IF2MSK); // Read out the IF Registers. ui32ArbReg = CAN_ADDR32(ui32Base + CAN_O_IF2ARB); ui32MsgCtrl = CAN_ADDR32(ui32Base + CAN_O_IF2MCTL); pMsgObject->ui32Flags = MSG_OBJ_NO_FLAGS; if((((!(ui32MsgCtrl & CAN_IF2MCTL_TXRQST)) != 0) && ((ui32ArbReg & CAN_IF2ARB_DIR) != 0)) \ || (((ui32MsgCtrl & CAN_IF2MCTL_TXRQST) != 0) && ((!(ui32ArbReg & CAN_IF2ARB_DIR)) != 0))) // Determine if this is a remote frame by checking the TXRQST and DIR bits. { pMsgObject->ui32Flags |= MSG_OBJ_REMOTE_FRAME; } else { ; } if((ui32ArbReg & CAN_IF2ARB_XTD) == CAN_IF2ARB_XTD) // Get the identifier out of the register, the format depends on size of the mask. { pMsgObject->ui32MsgID = ui32ArbReg & CAN_IF2ARB_ID_M; // Set the 29 bit version of the Identifier for this message object. pMsgObject->ui32Flags |= MSG_OBJ_EXTENDED_ID; } else { pMsgObject->ui32MsgID = (ui32ArbReg & CAN_IF2ARB_STD_ID_M) >> CAN_IF2ARB_STD_ID_S; // The Identifier is an 11 bit value. } if((ui32MsgCtrl & CAN_IF2MCTL_MSGLST) == CAN_IF2MCTL_MSGLST) // Indicate that we lost some data. { pMsgObject->ui32Flags |= MSG_OBJ_DATA_LOST; } else { ; } if((ui32MsgCtrl & CAN_IF2MCTL_UMASK) == CAN_IF2MCTL_UMASK) // Set the flag to indicate if ID masking was used. { if((ui32ArbReg & CAN_IF2ARB_XTD) == CAN_IF2ARB_XTD) { pMsgObject->ui32MsgIDMask = (ui32MaskReg & CAN_IF2MSK_MSK_M); // The Identifier Mask is assumed to also be a 29 bit value. if((pMsgObject->ui32MsgIDMask != 0x1fffffff) || ((pMsgObject->ui32Flags & MSG_OBJ_REMOTE_FRAME) == 0)) // If this is a fully specified Mask and a remote frame then don't set the MSG_OBJ_USE_ID_FILTER because the ID was not really filtered. { pMsgObject->ui32Flags |= MSG_OBJ_USE_ID_FILTER; } else { ; } } else { pMsgObject->ui32MsgIDMask = ((ui32MaskReg & CAN_IF2MSK_MSK_M) >> 18); // The Identifier Mask is assumed to also be an 11 bit value. if((pMsgObject->ui32MsgIDMask != 0x7ff) || ((pMsgObject->ui32Flags & MSG_OBJ_REMOTE_FRAME) == 0)) // If this is a fully specified Mask and a remote frame then don't set the MSG_OBJ_USE_ID_FILTER because the ID was not really filtered. { pMsgObject->ui32Flags |= MSG_OBJ_USE_ID_FILTER; } else { ; } } if((ui32MaskReg & CAN_IF2MSK_MXTD) == CAN_IF2MSK_MXTD) // Indicate if the extended bit was used in filtering. { pMsgObject->ui32Flags |= MSG_OBJ_USE_EXT_FILTER; } else { ; } if((ui32MaskReg & CAN_IF2MSK_MDIR) == CAN_IF2MSK_MDIR) // Indicate if direction filtering was enabled. { pMsgObject->ui32Flags |= MSG_OBJ_USE_DIR_FILTER; } else { ; } } else { ; } if ((ui32MsgCtrl & CAN_IF2MCTL_TXIE) == CAN_IF2MCTL_TXIE) // Set the interrupt flags. { pMsgObject->ui32Flags |= MSG_OBJ_TX_INT_ENABLE; } else { ; } if ((ui32MsgCtrl & CAN_IF2MCTL_RXIE) == CAN_IF2MCTL_RXIE) { pMsgObject->ui32Flags |= MSG_OBJ_RX_INT_ENABLE; } else { ; } if ((ui32MsgCtrl & CAN_IF2MCTL_NEWDAT) == CAN_IF2MCTL_NEWDAT) // See if there is new data available. { pMsgObject->ui32MsgLen = (ui32MsgCtrl & CAN_IF2MCTL_DLC_M); // Get the amount of data needed to be read. if ((pMsgObject->ui32Flags & MSG_OBJ_REMOTE_FRAME) == 0) // Don't read any data for a remote frame, there is nothing valid in that buffer anyway. { CANDataRegRead(pMsgObject->pucMsgData, (Uint32 *)(ui32Base + CAN_O_IF2DATA), pMsgObject->ui32MsgLen); // Read out the data from the CAN registers. } else { ; } CAN_ADDR16(ui32Base + CAN_O_IF2CMD + 2) = CAN_IF2CMD_TXRQST >> 16; // Now clear out the new data flag. CAN_ADDR16(ui32Base + CAN_O_IF2CMD) = ui32ObjID & CAN_IF2CMD_MSG_NUM_M; // Transfer the message object to the message object specified by ui32ObjID. while(((CAN_ADDR16(ui32Base + CAN_O_IF2CMD) & \ CAN_IF2CMD_BUSY) != 0) && (S_Temp < 1000)) // 检查是否处于空闲状态,如果这里通不过,那下面的寄存器都无法操作,因为寄存器都受busy保护 { DELAY_US(1); // 最多等待1ms后退出 S_Temp++; // 通过做实验,这里在初始化的时候不会进入 } if (S_Temp >= 1000) { S_Temp = 0; // 退出后将等待计数清理处理 Rtv = SYS_CAN_OP_ERROR; // 返回CAN接收错误 } else { S_Temp = 0; } pMsgObject->ui32Flags |= MSG_OBJ_NEW_DATA; // Indicate that there is new data in this message. } else { // pMsgObject->ui32MsgLen = 0; // Along with the MSG_OBJ_NEW_DATA not being set the amount of data needs to be set to zero if none was available. } return (Rtv); // 操作成功 }