The controller area network (CAN) uses a serial multimaster communication protocol that efficiently supports distributed real-time control, with a very high level of security, and a communication rate of up to 1 Mbps. The CAN bus is ideal for applications operating in noisy and harsh environments, such as in the automatice and other industrial fields that require reliable communication. Prioritized messages of up to eight bytes in data length can be sent on a multimaster serial bus using an arbitration protocol and an error-detection mechanism for a high level of data integrity .
// eCAN-A/B Interrupt Service Function
#pragma CODE_SECTION(ecan0_inta_isr, "ramfuncs");
#pragma CODE_SECTION(ecan1_inta_isr, "ramfuncs");
#pragma CODE_SECTION(ecan0_intb_isr, "ramfuncs");
#pragma CODE_SECTION(ecan1_intb_isr, "ramfuncs");
interrupt void ecan0_inta_isr(void);
interrupt void ecan1_inta_isr(void);
interrupt void ecan0_intb_isr(void);
interrupt void ecan1_intb_isr(void);
// -----------------------------
extern BOOL cana_rx_flag;
extern LONG cana_rx_id;
extern BYTE cana_rx_length;
extern LONG cana_rx_low_data;
extern LONG cana_rx_high_data;
extern BOOL canb_rx_flag;
extern LONG canb_rx_id;
extern BYTE canb_rx_length;
extern LONG canb_rx_low_data;
extern LONG canb_rx_high_data;
//------------------------------------------------------------
// CAN-A
void SendDataToECanA(LONG id, BYTE length, LONG low_data, LONG high_data){
if(ECanaRegs.CANTRS.bit.TRS1 == 1) return;
ECanaRegs.CANME.bit.ME1 = 0;
ECanaMboxes.MBOX1.MSGID.all = 0x80000000 | (id & 0x1fffffff);
ECanaRegs.CANME.bit.ME1 = 1;
ECanaMboxes.MBOX1.MSGCTRL.bit.DLC = length & 0xf;
ECanaMboxes.MBOX1.MDL.all = low_data;
ECanaMboxes.MBOX1.MDH.all = high_data;
ECanaRegs.CANTRS.bit.TRS1 = 1;
}
// CAN-B
void SendDataToECanB(LONG id, BYTE length, LONG low_data, LONG high_data){
if(ECanbRegs.CANTRS.bit.TRS1 == 1) return;
ECanbRegs.CANME.bit.ME1 = 0;
ECanbMboxes.MBOX1.MSGID.all = 0x80000000 | (id & 0x1fffffff);
ECanbRegs.CANME.bit.ME1 = 1;
ECanbMboxes.MBOX1.MDL.all = low_data;
ECanbMboxes.MBOX1.MDH.all = high_data;
ECanbMboxes.MBOX1.MSGCTRL.bit.DLC = length & 0xf;
ECanbRegs.CANTRS.bit.TRS1 = 1;
}
void init_can(void){
// Initialize CAN-A/B peripheral with 1M Bps
InitECanGpio();
InitECan();
// Initialize CAN-A Transmiter/Receiver MailBox
// CAN-A MBOX0 -> Receiver MailBox
// CAN-A MBOX1 -> Transmiter MailBox
ECanaLAMRegs.LAM0.all = 0x1fffffff; // MBOX1 acceptance mask
ECanaMboxes.MBOX0.MSGID.all = 0xc0000000; // IDE=1, AME=1
ECanaRegs.CANME.bit.ME0 = 1;
ECanaRegs.CANMD.bit.MD0 = 1; // Receiver
ECanaRegs.CANMD.bit.MD1 = 0; // Transmiter
// Initialize CAN-B Transmiter/Receiver MailBox
// CAN-B MBOX0 -> Receiver MailBox
// CAN-B MBOX1 -> Transmiter MailBox
ECanbLAMRegs.LAM0.all = 0x1fffffff; // MBOX1 acceptance mask(IDE match, IDs is don't care)
ECanbMboxes.MBOX0.MSGID.all = 0xc0000000; // IDE=1, AME=1
ECanbRegs.CANME.bit.ME0 = 1;
ECanbRegs.CANMD.bit.MD0 = 1; // Receiver
ECanbRegs.CANMD.bit.MD1 = 0; // Transmiter
// Initialize CAN-A/B interrupt vector
EALLOW;
PieVectTable.ECAN0INTA = &ecan0_inta_isr;
PieVectTable.ECAN1INTA = &ecan1_inta_isr;
PieVectTable.ECAN0INTB = &ecan0_intb_isr;
PieVectTable.ECAN1INTB = &ecan1_intb_isr;
EDIS;
EALLOW;
// Initialize CAN-A/B Receiver and Transmiter MailBox interrupt level
// CAN-A/B Receiver interrupt level -> 0
// CAN-A/B Transmiter interrupt level -> 1
ECanaRegs.CANMIL.bit.MIL0 = 0;
ECanaRegs.CANMIL.bit.MIL1 = 1;
ECanbRegs.CANMIL.bit.MIL0 = 0;
ECanbRegs.CANMIL.bit.MIL1 = 1;
// Initialize CAN-A/B Receiver and Transmiter MailBox interrupt mask
ECanaRegs.CANMIM.bit.MIM0 = 1;
ECanaRegs.CANMIM.bit.MIM1 = 1;
ECanbRegs.CANMIM.bit.MIM0 = 1;
ECanbRegs.CANMIM.bit.MIM1 = 1;
// Initialize CAN-A/B Global interrupt mask
ECanaRegs.CANGIM.bit.I0EN = 1;
ECanaRegs.CANGIM.bit.I1EN = 1;
ECanbRegs.CANGIM.bit.I0EN = 1;
ECanbRegs.CANGIM.bit.I1EN = 1;
EDIS;
// Enable CPU INT9 for CAN-A/B interrupt
IER |= M_INT9;
// Enable CAN-A/B INT0/1 in the PIE: Group 9 interrupt 5/67
PieCtrlRegs.PIEIER9.bit.INTx5 = 1;
PieCtrlRegs.PIEIER9.bit.INTx6 = 1;
PieCtrlRegs.PIEIER9.bit.INTx7 = 1;
PieCtrlRegs.PIEIER9.bit.INTx8 = 1;
}
// CAN-A
interrupt void ecan0_inta_isr(void){
if(ECanaRegs.CANRMP.bit.RMP0 == 1){
if(!cana_rx_flag){
cana_rx_id = ECanaMboxes.MBOX0.MSGID.all & 0x1fffffff;
cana_rx_length = ECanaMboxes.MBOX0.MSGCTRL.bit.DLC;
cana_rx_low_data = ECanaMboxes.MBOX0.MDL.all;
cana_rx_high_data = ECanaMboxes.MBOX0.MDH.all;
cana_rx_flag = TRUE;
}
// Clear receive pending flag
ECanaRegs.CANRMP.bit.RMP0 = 1;
}
// Acknowledge this interrupt to receive more interrupts from group 9
PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
}
// CAN-A
interrupt void ecan1_inta_isr(void){
if(ECanaRegs.CANTA.bit.TA1 == 1){
// Clear transmit-acknowledge pending flag
ECanaRegs.CANTA.bit.TA1 = 1;
}
// Acknowledge this interrupt to receive more interrupts from group 9
PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
}
// CAN-B
interrupt void ecan0_intb_isr(void){
if(ECanbRegs.CANRMP.bit.RMP0 == 1){
if(!canb_rx_flag){
canb_rx_id = ECanbMboxes.MBOX0.MSGID.all & 0x1fffffff;
canb_rx_length = ECanbMboxes.MBOX0.MSGCTRL.bit.DLC;
canb_rx_low_data = ECanbMboxes.MBOX0.MDL.all;
canb_rx_high_data = ECanbMboxes.MBOX0.MDH.all;
canb_rx_flag = TRUE;
}
// Clear receive pending flag
ECanbRegs.CANRMP.bit.RMP0 = 1;
}
// Acknowledge this interrupt to receive more interrupts from group 9
PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
}
// CAN-B
interrupt void ecan1_intb_isr(void){
if(ECanbRegs.CANTA.bit.TA1 == 1){
// Clear transmit-acknowledge pending flag
ECanbRegs.CANTA.bit.TA1 = 1;
}
// Acknowledge this interrupt to receive more interrupts from group 9
PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
}