📄 f50x_can0_transmit.c
字号:
//
// Return Value : None
// Parameters : None
//
// This function initializes the CAN peripheral and all of the message objects
//
// The following settings are chosen for the peripheral and message objects:
//
// CAN Bit Clock : 1 Mbps
// Auto Retransmit : Automatic Retransmission is enabled
// MsgVal : Set to Valid based on the #define MESSAGE_OBJECTS
// Filtering : Enabled for all valid message objects
// Message Identifier : 11-bit standard; Each message object is only used by
// one message ID and the ID is equal to the object number
// Direction : All valid message objects are configured for transmit
// 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
// Transmit 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 = 0x0880 | MESSAGE_SIZE; // Enable Transmit 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 send it.
// Arbitration Registers
CAN0IF1A2 = 0xA000 | (iter << 2); // Set MsgVal to valid
// Set Direction to write
// 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;
}
//-----------------------------------------------------------------------------
// Supporting Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// CAN0_TransferMO
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : U8 obj_num - message object number to send data
// range is 0x01 - 0x20
//
// Send data using the message object passed as the parameter. The data
// is generated using the message object number as the seed.
//
//-----------------------------------------------------------------------------
void CAN0_TransferMO (U8 obj_num)
{
// This function assumes that the message object is fully initialized
// in CAN0_Init and so all it has to do is fill the data registers and
// initiate transmission
U8 SFRPAGE_save = SFRPAGE;
SFRPAGE = CAN0_PAGE; // All CAN register are on page 0x0C
// Initialize all 8 data bytes even though they might not be sent
// The number to send was configured earlier by setting Message Control
CAN0IF1DA1H = obj_num; // Initialize data registers based
CAN0IF1DA1L = obj_num + 1; // on message object used
CAN0IF1DA2H = obj_num + 2;
CAN0IF1DA2L = obj_num + 3;
CAN0IF1DB1H = obj_num + 4;
CAN0IF1DB1L = obj_num + 5;
CAN0IF1DB2H = obj_num + 6;
CAN0IF1DB2L = obj_num + 7;
CAN0IF1CM = 0x0087; // Set Direction to Write
// Write TxRqst, all 8 data bytes
CAN0IF1CR = obj_num; // Start command request
while (!(CAN0IF1CRH & 0x80)); // Poll on Busy bit
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// CAN0_ISR
//-----------------------------------------------------------------------------
//
// The ISR is triggered upon any CAN errors or upon a complete transmission
//
// If an error occurs, a global counter is updated
//
//-----------------------------------------------------------------------------
INTERRUPT (CAN0_ISR, INTERRUPT_CAN0)
{
// 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
CAN0IF1CM = 0x0008; // Set Command Mask to clear pending
// interrupt for the message object
CAN0IF1CR = Interrupt_ID; // Start command request to actually
// clear the interrupt
while (!(CAN0IF1CRH & 0x80)); // Poll on Busy bit
if (status & TxOk) // If transmit completed successfully
{
// Set variable to indicate this message object's transfer completed
// Message Object 0 reports as 0x20 in the CAN0IID register, so
// convert it to 0x00
if (Interrupt_ID == 0x20)
{
Interrupt_ID = 0x00;
}
// Bit-shifting doesn't work with an operator greater than 15, so
// account for it
if (Interrupt_ID <= 15)
{
CAN_TX_COMPLETE.U32 |= (U16) (0x01 << Interrupt_ID);
}
else if (Interrupt_ID <= 0x1F)
{
CAN_TX_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 + -