📄 can.c
字号:
//! \return Returns the value of the status register.
//
//*****************************************************************************
unsigned long CANStatusGet(unsigned long ulBaseAddr, CAN_STS_REG eStatusReg)
{
unsigned long ulStatus;
LPC_CAN_TypeDef *ptBase = (LPC_CAN_TypeDef *)ulBaseAddr;
//
// Check the arguments.
//
ASSERT(CANBaseValid((unsigned long)ptBase));
switch(eStatusReg)
{
//
// Just return the global CAN status register since that is what was
// requested.
//
case CAN_STS_CONTROL:
{
ulStatus = canRegRead((unsigned long)&ptBase->STAT);
canRegWrite((unsigned long)&ptBase->STAT,
~(CAN_STS_RXOK | CAN_STS_TXOK | CAN_STS_LEC_M));
break;
}
//
// Combine the Transmit status bits into one 32bit value.
//
case CAN_STS_TXREQUEST:
{
ulStatus = canRegRead((unsigned long)&ptBase->TXREQ1);
ulStatus |= canRegRead((unsigned long)&ptBase->TXREQ2) << 16;
break;
}
//
// Combine the New Data status bits into one 32bit value.
//
case CAN_STS_NEWDAT:
{
ulStatus = canRegRead((unsigned long)&ptBase->ND1);
ulStatus |= canRegRead((unsigned long)&ptBase->ND2) << 16;
break;
}
//
// Combine the Message valid status bits into one 32bit value.
//
case CAN_STS_MSGVAL:
{
ulStatus = canRegRead((unsigned long)&ptBase->MSGV1);
ulStatus |= canRegRead((unsigned long)&ptBase->MSGV2) << 16;
break;
}
//
// Unknown CAN status requested so return 0.
//
default:
{
ulStatus = 0;
break;
}
}
return(ulStatus);
}
//*****************************************************************************
//
//! Reads the CAN controller error counter register.
//!
//! \param ptBase is the base address of the CAN controller.
//! \param pulRxCount is a pointer to storage for the receive error counter.
//! \param pulTxCount is a pointer to storage for the transmit error counter.
//!
//! Reads the error counter register and returns the transmit and receive error
//! counts to the caller along with a flag indicating if the controller receive
//! counter has reached the error passive limit. The values of the receive and
//! transmit error counters are returned through the pointers provided as
//! parameters.
//!
//! After this call, \e *pulRxCount will hold the current receive error count
//! and \e *pulTxCount will hold the current transmit error count.
//!
//! \return Returns \b true if the receive error count has reached the error
//! passive limit, and \b false if the error count is below the error passive
//! limit.
//
//*****************************************************************************
tBoolean CANErrCntrGet(unsigned long ulBaseAddr, unsigned long *pulRxCount,
unsigned long *pulTxCount)
{
unsigned long ulCANError;
LPC_CAN_TypeDef *ptBase = (LPC_CAN_TypeDef *)ulBaseAddr;
//
// Check the arguments.
//
ASSERT(CANBaseValid((unsigned long)ptBase));
//
// Read the current count of transmit/receive errors.
//
ulCANError = canRegRead((unsigned long)&ptBase->EC);
//
// Extract the error numbers from the register value.
//
*pulRxCount = (ulCANError & CAN_ERR_REC_M) >> CAN_ERR_REC_S;
*pulTxCount = (ulCANError & CAN_ERR_TEC_M) >> CAN_ERR_TEC_S;
if(ulCANError & CAN_ERR_RP)
{
return(true);
}
return(false);
}
//*****************************************************************************
//
//! Configures a message object in the CAN controller.
//!
//! \param ptBase is the base address of the CAN controller.
//! \param ulObjID is the object number to configure (1-32).
//! \param ptMsgObj is a pointer to a structure containing message object
//! settings.
//! \param eMsgType indicates the type of message for this object.
//!
//! This function is used to configure any one of the 32 message objects in the
//! CAN controller. A message object can be configured as any type of CAN
//! message object as well as several options for automatic transmission and
//! reception. This call also allows the message object to be configured to
//! generate interrupts on completion of message receipt or transmission. The
//! message object can also be configured with a filter/mask so that actions
//! are only taken when a message that meets certain parameters is seen on the
//! CAN bus.
//!
//! The \e eMsgType parameter must be one of the following values:
//!
//! - \b MSG_OBJ_TYPE_TX - CAN transmit message object.
//! - \b MSG_OBJ_TYPE_TX_REMOTE - CAN transmit remote request message object.
//! - \b MSG_OBJ_TYPE_RX - CAN receive message object.
//! - \b MSG_OBJ_TYPE_RX_REMOTE - CAN receive remote request message object.
//! - \b MSG_OBJ_TYPE_RXTX_REMOTE - CAN remote frame receive remote, then
//! transmit message object.
//!
//! The message object pointed to by \e ptMsgObj must be populated by the
//! caller, as follows:
//!
//! - \e ulMsgID - contains the message ID, either 11 or 29 bits.
//! - \e ulMsgIDMask - mask of bits from \e ulMsgID that must match if
//! identifier filtering is enabled.
//! - \e ulFlags
//! - Set \b MSG_OBJ_TX_INT_ENABLE flag to enable interrupt on transmission.
//! - Set \b MSG_OBJ_RX_INT_ENABLE flag to enable interrupt on receipt.
//! - Set \b MSG_OBJ_USE_ID_FILTER flag to enable filtering based on the
//! identifier mask specified by \e ulMsgIDMask.
//! - \e ulMsgLen - the number of bytes in the message data. This should be
//! non-zero even for a remote frame; it should match the expected bytes of the
//! data responding data frame.
//! - \e pucMsgData - points to a buffer containing up to 8 bytes of data for a
//! data frame.
//!
//! \b Example: To send a data frame or remote frame(in response to a remote
//! request), take the following steps:
//!
//! -# Set \e eMsgType to \b MSG_OBJ_TYPE_TX.
//! -# Set \e ptMsgObj->ulMsgID to the message ID.
//! -# Set \e ptMsgObj->ulFlags. Make sure to set \b MSG_OBJ_TX_INT_ENABLE to
//! allow an interrupt to be generated when the message is sent.
//! -# Set \e ptMsgObj->ulMsgLen to the number of bytes in the data frame.
//! -# Set \e ptMsgObj->pucMsgData to point to an array containing the bytes
//! to send in the message.
//! -# Call this function with \e ulObjID set to one of the 32 object buffers.
//!
//! \b Example: To receive a specific data frame, take the following steps:
//!
//! -# Set \e eMsgObjType to \b MSG_OBJ_TYPE_RX.
//! -# Set \e ptMsgObj->ulMsgID to the full message ID, or a partial mask to
//! use partial ID matching.
//! -# Set \e ptMsgObj->ulMsgIDMask bits that should be used for masking
//! during comparison.
//! -# Set \e ptMsgObj->ulFlags as follows:
//! - Set \b MSG_OBJ_TX_INT_ENABLE flag to be interrupted when the data frame
//! is received.
//! - Set \b MSG_OBJ_USE_ID_FILTER flag to enable identifier based filtering.
//! -# Set \e ptMsgObj->ulMsgLen to the number of bytes in the expected data
//! frame.
//! -# The buffer pointed to by \e ptMsgObj->pucMsgData and
//! \e ptMsgObj->ulMsgLen are not used by this call as no data is present at
//! the time of the call.
//! -# Call this function with \e ulObjID set to one of the 32 object buffers.
//!
//! If you specify a message object buffer that already contains a message
//! definition, it will be overwritten.
//!
//! \return None.
//
//*****************************************************************************
void CANMessageSet(unsigned long ulBaseAddr, unsigned long ulObjID,
CAN_MSG_OBJ *ptMsgObj, MSG_OBJ_TYPE eMsgType)
{
unsigned short usCmdMaskReg;
unsigned short usMaskReg[2];
unsigned short usArbReg[2];
unsigned short usMsgCtrl;
tBoolean bTransferData;
tBoolean bUseExtendedID;
LPC_CAN_TypeDef *ptBase = (LPC_CAN_TypeDef *)ulBaseAddr;
bTransferData = 0;
//
// Check the arguments.
//
ASSERT(CANBaseValid((unsigned long)ptBase));
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((unsigned long)&ptBase->IF1_CMDREQ) & CAN_IF1CRQ_BUSY)
{
}
//
// See if we need to use an extended identifier or not.
//
if((ptMsgObj->ulMsgID > CAN_MAX_11BIT_MSG_ID) ||
(ptMsgObj->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.
//
usArbReg[0] = 0;
usMsgCtrl = 0;
usMaskReg[0] = 0;
usMaskReg[1] = 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;
usArbReg[1] = 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;
usArbReg[1] = 0;
break;
}
//
// Receive message object.
//
case MSG_OBJ_TYPE_RX:
{
//
// This clears the DIR bit along with everthing else. The TXRQST
// bit was cleard by defaulting usMsgCtrl to 0.
//
usArbReg[1] = 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 cleard by defaulting usMsgCtrl to 0.
//
usArbReg[1] = 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.
//
usMaskReg[0] = 0xffff;
usMaskReg[1] = 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.
//
usArbReg[1] = 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;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -