📄 can.c
字号:
{
//
// Set the 29 bit version of the Identifier for this message object.
//
usArbReg[0] |= pMsgObject->ulMsgID & CAN_IFARB1_ID;
usArbReg[1] |= (pMsgObject->ulMsgID >> 16) & CAN_IFARB2_ID;
//
// Mark the message as valid and set the extended ID bit.
//
usArbReg[1] |= CAN_IFARB2_MSGVAL | CAN_IFARB2_XTD;
}
else
{
//
// Set the 11 bit version of the Identifier for this message object.
// The lower 18 bits are set to zero.
//
usArbReg[1] |= (pMsgObject->ulMsgID << 2) & CAN_IFARB2_ID;
//
// Mark the message as valid.
//
usArbReg[1] |= CAN_IFARB2_MSGVAL;
}
//
// Set the data length since this is set for all transfers.
// This is also a single transfer and not a FIFO transfer so set EOB bit.
//
usMsgCtrl |= (pMsgObject->ulMsgLen & CAN_IFMCTL_DLC) | CAN_IFMCTL_EOB;
//
// Enable transmit interrupts if they should be enabled.
//
if(pMsgObject->ulFlags & MSG_OBJ_TX_INT_ENABLE)
{
usMsgCtrl |= CAN_IFMCTL_TXIE;
}
//
// Enable receive interrupts if they should be enabled.
//
if(pMsgObject->ulFlags & MSG_OBJ_RX_INT_ENABLE)
{
usMsgCtrl |= CAN_IFMCTL_RXIE;
}
//
// Write the data out to the CAN Data registers if needed.
//
if(bTransferData)
{
CANWriteDataReg(
pMsgObject->pucMsgData,
(unsigned long *)(ulBase + CAN_O_IF1DA1), pMsgObject->ulMsgLen);
}
//
// Write out the registers to program the message object.
//
CANWriteReg(ulBase + CAN_O_IF1CMSK, usCmdMaskReg);
CANWriteReg(ulBase + CAN_O_IF1MSK1, usMaskReg[0]);
CANWriteReg(ulBase + CAN_O_IF1MSK2, usMaskReg[1]);
CANWriteReg(ulBase + CAN_O_IF1ARB1, usArbReg[0]);
CANWriteReg(ulBase + CAN_O_IF1ARB2, usArbReg[1]);
CANWriteReg(ulBase + CAN_O_IF1MCTL, usMsgCtrl);
//
// Transfer the message object to the message object specifiec by ulObjID.
//
CANWriteReg(ulBase + CAN_O_IF1CRQ, ulObjID & CAN_IFCRQ_MNUM_MSK);
return;
}
//*****************************************************************************
//
//! Reads a CAN message from one of the message object buffers
//!
//! \param ulBase is the base address of the CAN controller.
//! \param ulObjID is the object number to read (1-32)
//! \param pMsgObject points to a structure containing message object fields
//! \param bClrPendingInt indicates whether an associated interrupt should
//! be cleared
//!
//! This function is used to read the contents of one of the 32 message
//! objects in the CAN controller, and return it to the caller. The data
//! returned is stored in the fields of the caller supplied structure pointed
//! to by \e pMsgObject. The data consists of all of the parts of a CAN
//! message, plus some control and status information.
//!
//! Normally this is used to read a message object that has received and
//! stored a CAN message with a certain identifier. However this could also be
//! used to read the contents of a message object in order to load the fields
//! of the structure in case only part of the structure needs to be changed
//! from a previous setting.
//!
//! When using CANMessageGet, all of the same fields of the structure are
//! populated in the same way as when the CANMessageSet() function is used,
//! with the following exceptions:
//!
//! \e pMsgObject->ulFlags:
//!
//! - MSG_OBJ_NEW_DATA indicates if this is new data since the last
//! time it was read
//! - MSG_OBJ_DATA_LOST indicates that at least one message was received
//! on this message object, and not read by the host before being
//! overwritten.
//!
//! \return None.
//
//*****************************************************************************
void
CANMessageGet(unsigned long ulBase, unsigned long ulObjID,
tCANMsgObject *pMsgObject, tBoolean bClrPendingInt)
{
unsigned short usCmdMaskReg;
unsigned short usMaskReg[2];
unsigned short usArbReg[2];
unsigned short usMsgCtrl;
//
// Check the arguments.
//
ASSERT((ulBase == CAN0_BASE) ||
(ulBase == CAN1_BASE));
ASSERT((ulObjID <= 32) && (ulObjID != 0));
//
// This is always a read to the Message object as this call is setting
// a message object.
//
usCmdMaskReg = CAN_IFCMSK_DATAA | CAN_IFCMSK_DATAB | CAN_IFCMSK_CONTROL |
CAN_IFCMSK_MASK | CAN_IFCMSK_ARB;
//
// Clear a pending interrupt and new data in a message object.
//
if(bClrPendingInt)
{
usCmdMaskReg |= CAN_IFCMSK_CLRINTPND;
}
//
// Set up the request for data from the message object.
//
CANWriteReg(ulBase + CAN_O_IF2CMSK, usCmdMaskReg);
//
// Transfer the message object to the message object specifiec by ulObjID.
//
CANWriteReg(ulBase + CAN_O_IF2CRQ, ulObjID & CAN_IFCRQ_MNUM_MSK);
//
// Wait for busy bit to clear
//
while(CANReadReg(ulBase + CAN_O_IF2CRQ) & CAN_IFCRQ_BUSY)
{
}
//
// Read out the IF Registers.
//
usMaskReg[0] = CANReadReg(ulBase + CAN_O_IF2MSK1);
usMaskReg[1] = CANReadReg(ulBase + CAN_O_IF2MSK2);
usArbReg[0] = CANReadReg(ulBase + CAN_O_IF2ARB1);
usArbReg[1] = CANReadReg(ulBase + CAN_O_IF2ARB2);
usMsgCtrl = CANReadReg(ulBase + CAN_O_IF2MCTL);
pMsgObject->ulFlags = MSG_OBJ_NO_FLAGS;
//
// Determine if this is a remote frame by checking the TXRQST and DIR bits.
//
if((!(usMsgCtrl & CAN_IFMCTL_TXRQST) && (usArbReg[1] & CAN_IFARB2_DIR)) ||
((usMsgCtrl & CAN_IFMCTL_TXRQST) && (!(usArbReg[1] & CAN_IFARB2_DIR))))
{
pMsgObject->ulFlags |= MSG_OBJ_REMOTE_FRAME;
}
//
// Get the Identifier out of the register, the format depends on size of
// the Mask.
//
if(usArbReg[1] & CAN_IFARB2_XTD)
{
//
// Set the 29 bit version of the Identifier for this message object.
//
pMsgObject->ulMsgID = ((usArbReg[1] & CAN_IFARB2_ID) << 16) |
usArbReg[0];
pMsgObject->ulFlags |= MSG_OBJ_EXTENDED_ID;
}
else
{
//
// The Identifier is an 11 bit value.
//
pMsgObject->ulMsgID = (usArbReg[1] & CAN_IFARB2_ID) >> 2;
}
//
// Indicate that we lost some data.
//
if(usMsgCtrl & CAN_IFMCTL_MSGLST)
{
pMsgObject->ulFlags |= MSG_OBJ_DATA_LOST;
}
//
// Set the flag to indicate if ID masking was used.
//
if(usMsgCtrl & CAN_IFMCTL_UMASK)
{
if(usArbReg[1] & CAN_IFARB2_XTD)
{
//
// The Identifier Mask is assumed to also be a 29 bit value.
//
pMsgObject->ulMsgIDMask =
((usMaskReg[1] & CAN_IFMSK2_MSK) << 16) | usMaskReg[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.
//
if((pMsgObject->ulMsgIDMask != 0x1fffffff) ||
((pMsgObject->ulFlags & MSG_OBJ_REMOTE_FRAME) == 0))
{
pMsgObject->ulFlags |= MSG_OBJ_USE_ID_FILTER;
}
}
else
{
//
// The Identifier Mask is assumed to also be an 11 bit value.
//
pMsgObject->ulMsgIDMask = (usMaskReg[1] & CAN_IFMSK2_MSK) >> 2;
//
// 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.
//
if((pMsgObject->ulMsgIDMask != 0x7ff) ||
((pMsgObject->ulFlags & MSG_OBJ_REMOTE_FRAME) == 0))
{
pMsgObject->ulFlags |= MSG_OBJ_USE_ID_FILTER;
}
}
//
// Indicate if the extended bit was used in filtering.
//
if(usMaskReg[1] & CAN_IFMSK2_MXTD)
{
pMsgObject->ulFlags |= MSG_OBJ_USE_EXT_FILTER;
}
//
// Indicate if direction filtering was enabled.
//
if(usMaskReg[1] & CAN_IFMSK2_MDIR)
{
pMsgObject->ulFlags |= MSG_OBJ_USE_DIR_FILTER;
}
}
//
// Set the interupt flags.
//
if(usMsgCtrl & CAN_IFMCTL_TXIE)
{
pMsgObject->ulFlags |= MSG_OBJ_TX_INT_ENABLE;
}
if(usMsgCtrl & CAN_IFMCTL_RXIE)
{
pMsgObject->ulFlags |= MSG_OBJ_RX_INT_ENABLE;
}
//
// See if there is new data available.
//
if(usMsgCtrl & CAN_IFMCTL_NEWDAT)
{
//
// Get the amount of data needed to be read.
//
pMsgObject->ulMsgLen = (usMsgCtrl & CAN_IFMCTL_DLC);
//
// Don't read any data for a remote frame, there is nothing valid
// in that buffer anyway.
//
if((pMsgObject->ulFlags & MSG_OBJ_REMOTE_FRAME) == 0)
{
//
// Read out the data from the CAN registers.
//
CANReadDataReg(pMsgObject->pucMsgData,
(unsigned long *)(ulBase + CAN_O_IF2DA1),
pMsgObject->ulMsgLen);
}
//
// Now clear out the new data flag.
//
CANWriteReg(ulBase + CAN_O_IF2CMSK, CAN_IFCMSK_NEWDAT);
//
// Transfer the message object to the message object specifiec by
// ulObjID.
//
CANWriteReg(ulBase + CAN_O_IF2CRQ, ulObjID & CAN_IFCRQ_MNUM_MSK);
//
// Wait for busy bit to clear
//
while(CANReadReg(ulBase + CAN_O_IF2CRQ) & CAN_IFCRQ_BUSY)
{
}
//
// Indicate that there is new data in this message.
//
pMsgObject->ulFlags |= MSG_OBJ_NEW_DATA;
}
else
{
//
// Along with the MSG_OBJ_NEW_DATA not being set the amount of data
// needs to be set to zero if none was available.
//
pMsgObject->ulMsgLen = 0;
}
}
//*****************************************************************************
//
//! Clears a message object so that it is no longer used
//!
//! \param ulBase is the base address of the CAN controller.
//! \param ulObjID is the message object number to disable (1-32)
//!
//! This function frees the specified message object from use. Once a
//! message object has been "cleared" it will no longer automatically
//! send or receive messages, or generate interrupts.
//!
//! \return None.
//
//*****************************************************************************
void
CANMessageClear(unsigned long ulBase, unsigned long ulObjID)
{
//
// Check the arguments.
//
ASSERT((ulBase == CAN0_BASE) ||
(ulBase == CAN1_BASE));
ASSERT((ulObjID >= 1) && (ulObjID <= 32));
//
// Wait for busy bit to clear
//
while(CANReadReg(ulBase + CAN_O_IF1CRQ) & CAN_IFCRQ_BUSY)
{
}
//
// Clear the message value bit in the arbitration register.
// This indicates the message is not valid.
//
CANWriteReg(ulBase + CAN_O_IF1CMSK, CAN_IFCMSK_WRNRD | CAN_IFCMSK_ARB);
CANWriteReg(ulBase + CAN_O_IF1ARB1, 0);
CANWriteReg(ulBase + CAN_O_IF1ARB2, 0);
//
// Initiate programming the message object
//
CANWriteReg(ulBase + CAN_O_IF1CRQ, ulObjID & CAN_IFCRQ_MNUM_MSK);
}
//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -