📄 can.c
字号:
//*****************************************************************************
//
//! Sets the CAN controller auto-retransmission behavior.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param bAutoRetry enables auto-retransmission
//!
//! Enables or disables automatic retransmission of messages with detected
//! errors. If \e bAutoRetry is \b true, then auto-retransmission is enabled,
//! otherwise it is disabled.
//!
//! \return None.
//
//*****************************************************************************
void
CANRetrySet(unsigned long ulBase, tBoolean bAutoRetry)
{
unsigned long ulCtlReg;
//
// Check the arguments.
//
ASSERT((ulBase == CAN0_BASE) ||
(ulBase == CAN1_BASE) ||
(ulBase == CAN2_BASE));
ulCtlReg = CANReadReg(ulBase + CAN_O_CTL);
//
// Conditionally set the DAR bit to enable/disable auto-retry.
//
if(bAutoRetry)
{
//
// Clearing the DAR bit tells the controller to not disable the
// auto-retry of messages which were not transmited or received
// correctly.
//
ulCtlReg &= ~CAN_CTL_DAR;
}
else
{
//
// Setting the DAR bit tells the controller to disable the auto-retry
// of messages which were not transmited or received correctly.
//
ulCtlReg |= CAN_CTL_DAR;
}
CANWriteReg(ulBase + CAN_O_CTL, ulCtlReg);
}
//*****************************************************************************
//
//! Gets the current setting for auto-retransmission.
//!
//! \param ulBase is the base address of the CAN controller.
//!
//! Reads the current setting of the auto-retransmission setting in the CAN
//! controller and returns it to the caller.
//!
//! \return \b true if automatic retransmission is enabled, false otherwise
//
//*****************************************************************************
tBoolean
CANRetryGet(unsigned long ulBase)
{
//
// Check the arguments.
//
ASSERT((ulBase == CAN0_BASE) ||
(ulBase == CAN1_BASE) ||
(ulBase == CAN2_BASE));
if(CANReadReg(ulBase + CAN_O_CTL) & CAN_CTL_DAR)
{
return(0);
}
return(1);
}
//*****************************************************************************
//
//! Reads one of the controller status registers.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param eStatusReg is the status register to read
//!
//! Reads a status register of the CAN controller and returns it to the
//! caller. The different status registers are:
//! - CAN_STS_CONTROL - the main controller status
//! - CAN_STS_TXREQUEST - bit mask of objects pending transmission
//! - CAN_STS_NEWDAT - bit mask of objects with new data
//! - CAN_STS_MSGVAL - bit mask of objects with valid configuration
//!
//! When reading the main controller status register, a pending status
//! interrupt will be cleared. This should be used in the interrupt handler
//! for the CAN controller if the cause is a status interrupt. The fields of
//! controller status register are as follows:
//! - CAN_STS_BOFF - controller is in bus-off condition
//! - CAN_STS_EWARN - an error counter has reached a limit of at least 96
//! - CAN_STS_EPASS - CAN controller is in the error passive state
//! - CAN_STS_RXOK - a message was received successfully (independent of
//! any message filtering.
//! - CAN_STS_TXOK - a message was successfully transmitted
//! - CAN_STS_LEC_MSK - mask of last error code bits (3 bits)
//! - CAN_STS_LEC_NONE - no error
//! - CAN_STS_LEC_STUFF - stuffing error detected
//! - CAN_STS_LEC_FORM - a format error in the fixed format part of a message
//! - CAN_STS_LEC_ACK - a transmitted message was not acknowledged
//! - CAN_STS_LEC_BIT1 - dominant level detected when trying to send recessive
//! - CAN_STS_LEC_BIT0 - recessive level detected when trying to send dominant
//! - CAN_STS_LEC_CRC - CRC error in received message
//!
//! The remaining status registers are 32-bit bit maps to the message
//! objects. They can be used to quickly obtain information about the status
//! of all the message object without needing to query each one. They contain
//! the following information:
//! - CAN_STS_TXREQUEST - if a message object's TxRequest bit is set, that
//! means that a transmission is pending on that object. The application
//! can use this to determine which objects are still waiting to send a
//! message.
//! - CAN_STS_NEWDAT - if a message object's NewDat bit is set, that means
//! that a new message has been received in that object, and has not yet
//! been picked up by the host application
//! - CAN_STS_MSGVAL - if a message object's MsgVal bit is set, that means
//! it has a valid configuration programmed. The host application can use
//! this to determine which message objects are empty/unused.
//!
//! \return The value of the status register.
//
//*****************************************************************************
unsigned long
CANStatusGet(unsigned long ulBase, tCANStsReg eStatusReg)
{
unsigned long ulStatus;
//
// Check the arguments.
//
ASSERT((ulBase == CAN0_BASE) ||
(ulBase == CAN1_BASE) ||
(ulBase == CAN2_BASE));
switch (eStatusReg)
{
//
// Just return the global CAN status register since that is what was
// requested.
//
case CAN_STS_CONTROL:
{
ulStatus = CANReadReg(ulBase + CAN_O_STS);
CANWriteReg(ulBase + CAN_O_STS,
~(CAN_STS_RXOK | CAN_STS_TXOK | CAN_STS_LEC_MSK));
break;
}
//
// Combine the Transmit status bits into one 32bit value.
//
case CAN_STS_TXREQUEST:
{
ulStatus = CANReadReg(ulBase + CAN_O_TXRQ1);
ulStatus |= CANReadReg(ulBase + CAN_O_TXRQ2) << 16;
break;
}
//
// Combine the New Data status bits into one 32bit value.
//
case CAN_STS_NEWDAT:
{
ulStatus = CANReadReg(ulBase + CAN_O_NWDA1);
ulStatus |= CANReadReg(ulBase + CAN_O_NWDA2) << 16;
break;
}
//
// Combine the Message valid status bits into one 32bit value.
//
case CAN_STS_MSGVAL:
{
ulStatus = CANReadReg(ulBase + CAN_O_MSGVAL1);
ulStatus |= CANReadReg(ulBase + CAN_O_MSGVAL2) << 16;
break;
}
default:
{
ulStatus = 0;
break;
}
}
return(ulStatus);
}
//*****************************************************************************
//
//! Reads the CAN controller error counter register.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param pulRxCount points to storage for the receive error counter
//! \param pulTxCount points 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
//! - \b true if the receive error count has reached the error passive limit.
//! - \b false if the error count is below the error passive limit.
//*****************************************************************************
tBoolean
CANErrCntrGet(unsigned long ulBase, unsigned long *pulRxCount,
unsigned long *pulTxCount)
{
unsigned long ulCANError;
//
// Check the arguments.
//
ASSERT((ulBase == CAN0_BASE) ||
(ulBase == CAN1_BASE) ||
(ulBase == CAN2_BASE));
//
// Read the current count of transmit/receive errors.
//
ulCANError = CANReadReg(ulBase + CAN_O_ERR);
//
// Extract the error numbers from the register value.
//
*pulRxCount = (ulCANError & CAN_ERR_REC_MASK) >> CAN_ERR_REC_SHIFT;
*pulTxCount = (ulCANError & CAN_ERR_TEC_MASK) >> CAN_ERR_TEC_SHIFT;
if(ulCANError & CAN_ERR_RP)
{
return(1);
}
return(0);
}
//*****************************************************************************
//! Sets up a message object in the CAN controller.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param ulObjID is the object number to configure (1-32)
//! \param pMsgObject points to a structure containing message object fields
//! \param eMsgType Indicates what type of message this object is.
//! This value will be one of the following:
//! - MSG_OBJ_TYPE_TX - CAN transmit message object.
//! - MSG_OBJ_TYPE_TX_REMOTE - CAN transmit remote request message
//! object.
//! - MSG_OBJ_TYPE_RX - CAN receive message object.
//! - MSG_OBJ_TYPE_RX_REMOTE - CAN receive remote request message object.
//! - MSG_OBJ_TYPE_RXTX_REMOTE - CAN remote frame receive remote, then
//! transmit message object.
//!
//! This function is used to configure any one of the 32 highly configurable
//! message objects in the CAN controller. A message object can be set up
//! with a remote or data frame along with several options for automatic
//! transmission and reception. It can be configured to generate interrupts
//! on completion of message receipt or transmission. The object can also
//! be set up with filter/mask so that action is only taken when a message
//! that meets certain parameters is seen on the bus.
//!
//! The message object pointed to by \e pMsgObject 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
//! - \e ulFlags
//! Set MSG_OBJ_TX_INT_ENABLE flag to enable interrupt on transmission
//! Set MSG_OBJ_RX_INT_ENABLE flag to enable interrupt on receipt
//! Set MSG_OBJ_USE_ID_FILTER flag to enable filtering based on the
//! identifier mask specified by /e ulMsgIDMask.
//! - 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
//! - pchMsgData - points to a buffer containing up to 8 bytes of data
//! for a data frame
//!
//! To send a data frame or remote frame directly, take the following steps:
//! - set \e tMsgObjType - set to MSG_OBJ_TYPE_TX.
//! - set \e ulMsgID to the message ID
//! - set \e ulFlags
//! Set MSG_OBJ_TX_INT_ENABLE to to get an interrupt when the message is
//! sent.
//! Do not set MSG_OBJ_USE_ID_FILTER so that no identifier filtering is
//! used.
//! - set \e ulMsgLen to the number of bytes in the data frame
//! - set \e pchMsgData to point to an array containing the bytes in the
//! message (if a data frame, n/a if remote frame, though it is a good
//! idea to set this to point to a valid buffer)
//! - call this function with \e ulObjID set to one of the 32 object buffers
//!
//! To receive a specific data frame, take the following steps:
//! - set \e tMsgObjType - set to MSG_OBJ_TYPE_RX.
//! - set \e ulMsgID to the full message ID, or a partial mask to use partial
//! ID matching.
//! - set \e ulMsgIDMask bits that should be used for masking during
//! comparison.
//! - \e ulFlags
//! Set MSG_OBJ_TX_INT_ENABLE flag to be interrupted when the data frame is
//! received.
//! Set MSG_OBJ_USE_ID_FILTER flag to enable identifier based filtering.
//! - set \e ulMsgLen to the number of bytes in the expected data frame
//! - the buffer pointed to by \e pchMsgData is not used for this 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.
//
//*****************************************************************************
long
CANMessageSet(unsigned long ulBase, unsigned long ulObjID,
tCANMsgObject *pMsgObject, tMsgObjType eMsgType)
{
unsigned short usCmdMaskReg;
unsigned short usMaskReg[2];
unsigned short usArbReg[2];
unsigned short usMsgCtrl;
tBoolean bTransferData;
tBoolean bUseExtendedID;
bTransferData = 0;
//
// Check the arguments.
//
ASSERT((ulBase == CAN0_BASE) ||
(ulBase == CAN1_BASE) ||
(ulBase == CAN2_BASE));
ASSERT((ulObjID <= 32) && (ulObjID != 0));
//
// Wait for busy bit to clear
//
while(CANReadReg(ulBase + CAN_O_IF1CRQ) & CAN_IFCRQ_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_IFCMSK_WRNRD | CAN_IFCMSK_DATAA | CAN_IFCMSK_DATAB |
CAN_IFCMSK_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)
{
case MSG_OBJ_TYPE_TX:
{
//
// Set the TXRQST bit and the reset the rest of the register.
//
usMsgCtrl |= CAN_IFMCTL_TXRQST;
usArbReg[1] = CAN_IFARB2_DIR;
bTransferData = 1;
break;
}
case MSG_OBJ_TYPE_TX_REMOTE:
{
//
// Set the TXRQST bit and the reset the rest of the register.
//
usMsgCtrl |= CAN_IFMCTL_TXRQST;
usArbReg[1] = 0;
break;
}
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;
}
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_IFARB2_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_IFMCTL_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_IFCMSK_MASK;
break;
}
case MSG_OBJ_TYPE_RXTX_REMOTE:
{
//
// Oddly the DIR bit is set to one for remote receivers.
//
usArbReg[1] = CAN_IFARB2_DIR;
//
// Set this object to auto answer if a matching identifier is seen.
//
usMsgCtrl = CAN_IFMCTL_RMTEN | CAN_IFMCTL_UMASK;
//
// The data to be returned needs to be filled in.
//
bTransferData = 1;
break;
}
default:
{
return(-1);
}
}
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -