📄 f50x_can0_receive.c
字号:
// one message ID and the ID is equal to the object number
// Direction : All valid message objects are configured for receive
// End of Buffer : All message objects are treated as separate buffers
//
// The following interrupts are enabled and are handled by CAN0_ISR
//
// Error Interrupts
// Status Change Interrupt
// Receive Interrupt
//
//-----------------------------------------------------------------------------
void CAN0_Init (void)
{
U8 iter;
U8 SFRPAGE_save = SFRPAGE;
SFRPAGE = CAN0_PAGE; // All CAN register are on page 0x0C
CAN0CN |= 0x01; // Start Intialization mode
//---------Initialize general CAN peripheral settings
CAN0CN |= 0x4E; // Enable Status, Error,
// Module Interrupts
// Enable access to bit timing register
// See the CAN Bit Timing Spreadsheet for how to calculate this value
CAN0BT = 0x1402; // Based on 24 Mhz CAN clock, set the
// CAN bit rate to 1 Mbps
//---------Initialize settings common to all message objects
// Command Mask Register
CAN0IF1CM = 0x00F0; // Write Operation
// Transfer ID Mask, MDir, MXtd
// Transfer ID, Dir, Xtd, MsgVal
// Transfer Control Bits
// Don't set TxRqst or transfer data
// Mask Registers
CAN0IF1M1 = 0x0000; // Mask Bits 15-0 not used for filtering
CAN0IF1M2 = 0x5FFC; // Ignore Extended Identifier for
// filtering
// Used Direction bit for filtering
// Use ID bits 28-18 for filtering
// Arbitration Registers
CAN0IF1A1 = 0x0000; // 11-bit ID, so lower 16-bits not used
// Message Control Registers
CAN0IF1MC = 0x1480 | MESSAGE_SIZE; // Enable Receive Interrupt
// Message Object is a Single Message
// Message Size set by #define
//---------Initialize unique settings for each valid message object
for (iter = 0; iter < MESSAGE_OBJECTS; iter++)
{
// For example purposes, set 11-bit identifier based on the message
// object that is used to receive it.
// Arbitration Registers
CAN0IF1A2 = 0x8000 | (iter << 2); // Set MsgVal to valid
// Set Object Direction to read
// Set 11-bit Identifier to iter
CAN0IF1CR = iter; // Start command request
while (!(CAN0IF1CRH & 0x80)); // Poll on Busy bit
}
//---------Initialize settings for unused message objects
for (iter = MESSAGE_OBJECTS; iter < MESSAGE_OBJECTS; iter++)
{
// Set remaining message objects to be Ignored
CAN0IF1A2 = 0x0000; // Set MsgVal to 0 to Ignore
CAN0IF1CR = iter; // Start command request
while (!(CAN0IF1CRH & 0x80)); // Poll on Busy bit
}
CAN0CN &= ~0x41; // Return to Normal Mode and disable
// access to bit timing register
SFRPAGE = SFRPAGE_save;
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// CAN0_ISR
//-----------------------------------------------------------------------------
//
// The ISR is triggered upon any CAN errors or upon reception of message
//
// If an error occurs, a global counter is updated
//
//-----------------------------------------------------------------------------
INTERRUPT (CAN0_ISR, INTERRUPT_CAN0)
{
U8 iter;
U8 carry;
UU64 rx_data;
UU32 new_data;
// SFRPAGE is set to CAN0_Page automatically when ISR starts
U8 status = CAN0STAT; // Read status, which clears the Status
// Interrupt bit pending in CAN0IID
U8 Interrupt_ID = CAN0IID; // Read which message object caused
// the interrupt
/*--------------------------------------------------------------------
If you are working with Revision A of the F50x, the CAN0ND registers
have a misaligned organization that appears as a 1-bit left shift
from the expected alignment as described in the Bosch CAN User抯
Guide.
The Bosch CAN User抯 Guide documents the bit organization for all
of these registers as follows:
Register 1 (16-9 : 8-1)
Register 2 (32-25 : 24-17)
On Revision A devices, the bit organization for these four sets of
registers is as follows:
Register 1 (15-8 : 7-1, 32)
Register 2 (31-24 : 23-16)
The following code will show how to shift the registers to match
the alignment presented in the Bosch CAN User's Guide. You can find
more information on this error in "C8051F50x_ErrataRevA.pdf".
---------------------------------------------------------------------*/
// The CAN0ND registers tell which of the 32 message objects are new.
// Read data from CAN registers and perform 1-bit right shift with carry
new_data.U8[b0] = CAN0ND1L; // With a big endian compiler, assign LSB
new_data.U8[b1] = CAN0ND1H;
new_data.U8[b2] = CAN0ND2L;
new_data.U8[b3] = CAN0ND2H; // Assign MSB
carry = new_data.U8[b0] & 0x01; // Store carry bit
new_data.U32 = new_data.U32 >> 1; // Perform 1-bit shift to realign
if (carry)
{ // Add carry if necessary
new_data.U8[b3] = new_data.U8[b3] | 0x80;
}
// new_data variable will now tell which message object is new.
CAN0IF1CM = 0x007F; // Read all of message object to IF1
// Clear IntPnd and newData
CAN0IF1CR = Interrupt_ID; // Start command request
while (!(CAN0IF1CRH & 0x80)); // Poll on Busy bit
if (status & RxOk) // If transmit completed successfully
{
// Read all 8 data bytes to rxdata, even though they might not be valid
rx_data.U16[0] = CAN0IF1DA1; // First pair of bytes
rx_data.U16[1] = CAN0IF1DA2; // Second pair of bytes
rx_data.U16[2] = CAN0IF1DB1; // Third pair of bytes
rx_data.U16[3] = CAN0IF1DB2; // Fourth and last pair of bytes
// Message Object 0 reports as 0x20 in the CAN0IID register, so
// convert it to 0x00
if (Interrupt_ID == 0x20)
{
Interrupt_ID = 0x00;
}
for (iter = 0; iter < MESSAGE_SIZE; iter++)
{
if (rx_data.U8[iter] != (Interrupt_ID + iter))
{
CAN_ERROR = 1;
}
}
// Set variable to indicate this message object's transfer completed
// Bit-shifting doesn't work with an operator greater than 15, so
// account for it
if (Interrupt_ID <= 15)
{
CAN_RX_COMPLETE.U32 |= (U16) (0x01 << Interrupt_ID);
}
else if (Interrupt_ID <= 0x1F)
{
CAN_RX_COMPLETE.U16[MSB] |= (U16) (0x01 << (Interrupt_ID - 16));
}
}
// If an error occured, simply update the global variable and continue
if (status & LEC)
{
// The LEC bits identify the type of error, but those are grouped here
if ((status & LEC) != 0x07)
{
CAN_ERROR = 1;
}
}
if (status & BOff)
{
CAN_ERROR = 1;
}
if (status & EWarn)
{
CAN_ERROR = 1;
}
// Old SFRPAGE is popped off stack when ISR exits
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -