void CAN0_Init (void)
{
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 Error and Module
// 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 for Transmit Message Object
// 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
// Message Control Registers
CAN0IF1MC = 0x0080 | MESSAGE_SIZE; // Disable Transmit Interrupt
// Message Object is a Single Message
// Message Size set by #define
// Arbitration Registers
CAN0IF1A1 = 0x0000; // 11-bit ID, so lower 16-bits not used
// Arbitration Registers
CAN0IF1A2 = 0xA000 | (LEDTX_ID << 2); // Set MsgVal to valid
// Set Direction to write
// Set 11-bit Identifier to iter
CAN0IF1CR = TRANSMIT_MO; // Start command request
while (CAN0IF1CRH & 0x80) {} // Poll on Busy bit
//---------Initialize settings for Receive Message Object
// Can use the same settings for Receive object, so no need reinitalize the
// first four CAN register again
// Command Mask Register
// CAN0IF1CM = 0x00F0;
// Mask Registers
// CAN0IF1M1 = 0x0000;
// CAN0IF1M2 = 0x5FFC;
// Arbitration Registers
// CAN0IF1A1 = 0x0000;
// Message Control Registers
CAN0IF1MC = 0x1480 | MESSAGE_SIZE; // Enable Receive Interrupt
// Message Object is a Single Message
// Message Size set by #define
// Arbitration Registers
CAN0IF1A2 = 0x8000 | (LEDRX_ID << 2); // Set MsgVal to valid
// Set Object Direction to read
// Set 11-bit Identifier to iter
CAN0IF1CR = RECEIVE_MO; // Start command request
while (CAN0IF1CRH & 0x80) {} // Poll on Busy bit
//--------- CAN Initalization is complete
CAN0CN &= ~0x41; // Return to Normal Mode and disable
// access to bit timing register
EIE2 |= 0x02; // Enable CAN interupts
SFRPAGE = SFRPAGE_save;
}
//-----------------------------------------------------------------------------
// Supporting Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// CAN0_SendMessage
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Send the data
//
//-----------------------------------------------------------------------------
void CAN0_SendMessage (U8 message)
{
// 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
CAN0IF1DA1L = message; // Transfer message to data register
CAN0IF1CM = 0x0087; // Set Direction to Write
// Write TxRqst, all 8 data bytes
CAN0IF1CR = TRANSMIT_MO; // Start command request
while (CAN0IF1CRH & 0x80) {} // Poll on Busy bit
SFRPAGE = SFRPAGE_save; // Restore SFRPAGE
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// TIMER0_ISR
//-----------------------------------------------------------------------------
//
// The ISR is triggered upon any CAN errors or upon a message reception
//
// If an error occurs, a global counter is updated
//
//-----------------------------------------------------------------------------
INTERRUPT (TIMER0_ISR, INTERRUPT_TIMER0)
{
// Timer0 ISR pending flag is automatically cleared by vectoring to ISR
if (SW != SW_status) // Switch has changed since last check
{
SW_status = SW; // Update the status
CAN0_SendMessage (SW_status); // Send the new status over CAN
}
}