📄 can.c
字号:
CANMessageSet(unsigned long ulBase, unsigned long ulObjID,
tCANMsgObject *pMsgObject, tMsgObjType eMsgType)
{
unsigned short usCmdMaskReg;
unsigned short usMaskReg0, usMaskReg1;
unsigned short usArbReg0, usArbReg1;
unsigned short usMsgCtrl;
tBoolean bTransferData;
tBoolean bUseExtendedID;
bTransferData = 0;
//
// Check the arguments.
//
ASSERT(CANBaseValid(ulBase));
ASSERT((ulObjID <= 32) && (ulObjID != 0));
ASSERT((eMsgType == MSG_OBJ_TYPE_TX) ||
(eMsgType == MSG_OBJ_TYPE_TX_REMOTE) ||
(eMsgType == MSG_OBJ_TYPE_RX) ||
(eMsgType == MSG_OBJ_TYPE_RX_REMOTE) ||
(eMsgType == MSG_OBJ_TYPE_TX_REMOTE) ||
(eMsgType == MSG_OBJ_TYPE_RXTX_REMOTE));
//
// Wait for busy bit to clear
//
while(CANRegRead(ulBase + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
{
}
//
// See if we need to use an extended identifier or not.
//
if((pMsgObject->ulMsgID > CAN_MAX_11BIT_MSG_ID) ||
(pMsgObject->ulFlags & MSG_OBJ_EXTENDED_ID))
{
bUseExtendedID = 1;
}
else
{
bUseExtendedID = 0;
}
//
// This is always a write to the Message object as this call is setting a
// message object. This call will also always set all size bits so it sets
// both data bits. The call will use the CONTROL register to set control
// bits so this bit needs to be set as well.
//
usCmdMaskReg = (CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_DATAA | CAN_IF1CMSK_DATAB |
CAN_IF1CMSK_CONTROL);
//
// Initialize the values to a known state before filling them in based on
// the type of message object that is being configured.
//
usArbReg0 = 0;
usArbReg1 = 0;
usMsgCtrl = 0;
usMaskReg0 = 0;
usMaskReg1 = 0;
switch(eMsgType)
{
//
// Transmit message object.
//
case MSG_OBJ_TYPE_TX:
{
//
// Set the TXRQST bit and the reset the rest of the register.
//
usMsgCtrl |= CAN_IF1MCTL_TXRQST;
usArbReg1 = CAN_IF1ARB2_DIR;
bTransferData = 1;
break;
}
//
// Transmit remote request message object
//
case MSG_OBJ_TYPE_TX_REMOTE:
{
//
// Set the TXRQST bit and the reset the rest of the register.
//
usMsgCtrl |= CAN_IF1MCTL_TXRQST;
usArbReg1 = 0;
break;
}
//
// Receive message object.
//
case MSG_OBJ_TYPE_RX:
{
//
// This clears the DIR bit along with everything else. The TXRQST
// bit was cleared by defaulting usMsgCtrl to 0.
//
usArbReg1 = 0;
break;
}
//
// Receive remote request message object.
//
case MSG_OBJ_TYPE_RX_REMOTE:
{
//
// The DIR bit is set to one for remote receivers. The TXRQST bit
// was cleared by defaulting usMsgCtrl to 0.
//
usArbReg1 = CAN_IF1ARB2_DIR;
//
// Set this object so that it only indicates that a remote frame
// was received and allow for software to handle it by sending back
// a data frame.
//
usMsgCtrl = CAN_IF1MCTL_UMASK;
//
// Use the full Identifier by default.
//
usMaskReg0 = 0xffff;
usMaskReg1 = 0x1fff;
//
// Make sure to send the mask to the message object.
//
usCmdMaskReg |= CAN_IF1CMSK_MASK;
break;
}
//
// Remote frame receive remote, with auto-transmit message object.
//
case MSG_OBJ_TYPE_RXTX_REMOTE:
{
//
// Oddly the DIR bit is set to one for remote receivers.
//
usArbReg1 = CAN_IF1ARB2_DIR;
//
// Set this object to auto answer if a matching identifier is seen.
//
usMsgCtrl = CAN_IF1MCTL_RMTEN | CAN_IF1MCTL_UMASK;
//
// The data to be returned needs to be filled in.
//
bTransferData = 1;
break;
}
//
// This case should never happen due to the ASSERT statement at the
// beginning of this function.
//
default:
{
return;
}
}
//
// Configure the Mask Registers.
//
if(pMsgObject->ulFlags & MSG_OBJ_USE_ID_FILTER)
{
if(bUseExtendedID)
{
//
// Set the 29 bits of Identifier mask that were requested.
//
usMaskReg0 = pMsgObject->ulMsgIDMask & CAN_IF1MSK1_IDMSK_M;
usMaskReg1 = ((pMsgObject->ulMsgIDMask >> 16) &
CAN_IF1MSK2_IDMSK_M);
}
else
{
//
// Lower 16 bit are unused so set them to zero.
//
usMaskReg0 = 0;
//
// Put the 11 bit Mask Identifier into the upper bits of the field
// in the register.
//
usMaskReg1 = ((pMsgObject->ulMsgIDMask << 2) &
CAN_IF1MSK2_IDMSK_M);
}
}
//
// If the caller wants to filter on the extended ID bit then set it.
//
if((pMsgObject->ulFlags & MSG_OBJ_USE_EXT_FILTER) ==
MSG_OBJ_USE_EXT_FILTER)
{
usMaskReg1 |= CAN_IF1MSK2_MXTD;
}
//
// The caller wants to filter on the message direction field.
//
if((pMsgObject->ulFlags & MSG_OBJ_USE_DIR_FILTER) ==
MSG_OBJ_USE_DIR_FILTER)
{
usMaskReg1 |= CAN_IF1MSK2_MDIR;
}
if(pMsgObject->ulFlags & (MSG_OBJ_USE_ID_FILTER | MSG_OBJ_USE_DIR_FILTER |
MSG_OBJ_USE_EXT_FILTER))
{
//
// Set the UMASK bit to enable using the mask register.
//
usMsgCtrl |= CAN_IF1MCTL_UMASK;
//
// Set the MASK bit so that this gets transferred to the Message Object.
//
usCmdMaskReg |= CAN_IF1CMSK_MASK;
}
//
// Set the Arb bit so that this gets transferred to the Message object.
//
usCmdMaskReg |= CAN_IF1CMSK_ARB;
//
// Configure the Arbitration registers.
//
if(bUseExtendedID)
{
//
// Set the 29 bit version of the Identifier for this message object.
//
usArbReg0 |= pMsgObject->ulMsgID & CAN_IF1ARB1_ID_M;
usArbReg1 |= (pMsgObject->ulMsgID >> 16) & CAN_IF1ARB2_ID_M;
//
// Mark the message as valid and set the extended ID bit.
//
usArbReg1 |= CAN_IF1ARB2_MSGVAL | CAN_IF1ARB2_XTD;
}
else
{
//
// Set the 11 bit version of the Identifier for this message object.
// The lower 18 bits are set to zero.
//
usArbReg1 |= (pMsgObject->ulMsgID << 2) & CAN_IF1ARB2_ID_M;
//
// Mark the message as valid.
//
usArbReg1 |= CAN_IF1ARB2_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_IF1MCTL_DLC_M);
//
// Mark this as the last entry if this is not the last entry in a FIFO.
//
if((pMsgObject->ulFlags & MSG_OBJ_FIFO) == 0)
{
usMsgCtrl |= CAN_IF1MCTL_EOB;
}
//
// Enable transmit interrupts if they should be enabled.
//
if(pMsgObject->ulFlags & MSG_OBJ_TX_INT_ENABLE)
{
usMsgCtrl |= CAN_IF1MCTL_TXIE;
}
//
// Enable receive interrupts if they should be enabled.
//
if(pMsgObject->ulFlags & MSG_OBJ_RX_INT_ENABLE)
{
usMsgCtrl |= CAN_IF1MCTL_RXIE;
}
//
// Write the data out to the CAN Data registers if needed.
//
if(bTransferData)
{
CANDataRegWrite(pMsgObject->pucMsgData,
(unsigned long *)(ulBase + CAN_O_IF1DA1),
pMsgObject->ulMsgLen);
}
//
// Write out the registers to program the message object.
//
CANRegWrite(ulBase + CAN_O_IF1CMSK, usCmdMaskReg);
CANRegWrite(ulBase + CAN_O_IF1MSK1, usMaskReg0);
CANRegWrite(ulBase + CAN_O_IF1MSK2, usMaskReg1);
CANRegWrite(ulBase + CAN_O_IF1ARB1, usArbReg0);
CANRegWrite(ulBase + CAN_O_IF1ARB2, usArbReg1);
CANRegWrite(ulBase + CAN_O_IF1MCTL, usMsgCtrl);
//
// Transfer the message object to the message object specifiec by ulObjID.
//
CANRegWrite(ulBase + CAN_O_IF1CRQ, ulObjID & CAN_IF1CRQ_MNUM_M);
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:
//!
//! - \b MSG_OBJ_NEW_DATA indicates if this is new data since the last time it
//! was read
//! - \b 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 usMaskReg0, usMaskReg1;
unsigned short usArbReg0, usArbReg1;
unsigned short usMsgCtrl;
//
// Check the arguments.
//
ASSERT(CANBaseValid(ulBase));
ASSERT((ulObjID <= 32) && (ulObjID != 0));
//
// This is always a read to the Message object as this call is setting a
// message object.
//
usCmdMaskReg = (CAN_IF1CMSK_DATAA | CAN_IF1CMSK_DATAB |
CAN_IF1CMSK_CONTROL | CAN_IF1CMSK_MASK | CAN_IF1CMSK_ARB);
//
// Clear a pending interrupt and new data in a message object.
//
if(bClrPendingInt)
{
usCmdMaskReg |= CAN_IF1CMSK_CLRINTPND;
}
//
// Set up the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -