768 lines
26 KiB
C
768 lines
26 KiB
C
/**
|
||
ECAN Generated Driver File
|
||
|
||
@Company
|
||
Microchip Technology Inc.
|
||
|
||
@File Name
|
||
ecan.c
|
||
|
||
@Summary
|
||
This is the generated driver implementation for the CAN driver using PIC10 / PIC12 / PIC16 / PIC18 MCUs
|
||
|
||
@Description
|
||
This source file provides APIs for CAN.
|
||
Generation Information :
|
||
Product Revision : PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.81.8
|
||
Device : PIC18F25K83
|
||
Driver Version : 3.0.0
|
||
The generated drivers are tested against the following:
|
||
Compiler : XC8 2.36 and above
|
||
MPLAB : MPLAB X 6.00
|
||
*/
|
||
|
||
/*
|
||
(c) 2018 Microchip Technology Inc. and its subsidiaries.
|
||
|
||
Subject to your compliance with these terms, you may use Microchip software and any
|
||
derivatives exclusively with Microchip products. It is your responsibility to comply with third party
|
||
license terms applicable to your use of third party software (including open source software) that
|
||
may accompany Microchip software.
|
||
|
||
THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||
EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
|
||
IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
|
||
FOR A PARTICULAR PURPOSE.
|
||
|
||
IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
|
||
INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
|
||
WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
|
||
HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
|
||
THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
|
||
CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
|
||
OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
|
||
SOFTWARE.
|
||
*/
|
||
|
||
/**
|
||
Section: Included Files
|
||
*/
|
||
|
||
#include <xc.h>
|
||
#include "ecan.h"
|
||
|
||
static void (*RXBnInterruptHandler)(void);
|
||
static void (*RXBnOverflowHandler)(void);
|
||
static void (*BusOffHandler)(void);
|
||
static void (*TXPassiveHandler)(void);
|
||
static void (*RXPassiveHandler)(void);
|
||
static void (*TXWarningHandler)(void);
|
||
static void (*RXWarningHandler)(void);
|
||
|
||
/**
|
||
Local Functions
|
||
*/
|
||
static uint32_t convertReg2ExtendedCANid(uint8_t tempRXBn_EIDH, uint8_t tempRXBn_EIDL, uint8_t tempRXBn_SIDH, uint8_t tempRXBn_SIDL);
|
||
static uint32_t convertReg2StandardCANid(uint8_t tempRXBn_SIDH, uint8_t tempRXBn_SIDL);
|
||
static void convertCANid2Reg(uint32_t tempPassedInID, uint8_t canIdType, uint8_t *passedInEIDH, uint8_t *passedInEIDL, uint8_t *passedInSIDH, uint8_t *passedInSIDL);
|
||
|
||
static void RXBnDefaultInterruptHandler(void) {}
|
||
static void RXBnOverflowDefaultHandler(void) {}
|
||
static void BusOffDefaultHandler(void) {}
|
||
static void TXPassiveDefaultHandler(void) {}
|
||
static void RXPassiveDefaultHandler(void) {}
|
||
static void TXWarningDefaultHandler(void) {}
|
||
static void RXWarningDefaultHandler(void) {}
|
||
|
||
void ECAN_Initialize(void)
|
||
{
|
||
CANCON = 0x80;
|
||
while (0x80 != (CANSTAT & 0xE0)); // wait until ECAN is in config mode
|
||
|
||
/**
|
||
Mode 2
|
||
*/
|
||
ECANCON = 0x90;
|
||
|
||
/**
|
||
Initialize CAN I/O
|
||
*/
|
||
CIOCON = 0x00;
|
||
|
||
/**
|
||
Mask and Filter definitions
|
||
........................................................
|
||
CAN ID ID Type Mask Filter Buffer
|
||
........................................................
|
||
0x123 SID Acceptance Mask 0 Filter 0 FIFO
|
||
........................................................
|
||
*/
|
||
|
||
/**
|
||
Configure Generic Buffers to be Transmit or Receive
|
||
*/
|
||
BSEL0 = 0x00;
|
||
/**
|
||
Mask and Filter definitions
|
||
........................................................
|
||
CAN ID ID Type Mask Filter Buffer
|
||
........................................................
|
||
........................................................
|
||
*/
|
||
|
||
/*
|
||
* Mask 0 is 11 bits for filters 0 and 1 only
|
||
* filter set for 3 recipient bits
|
||
* Mask 1 is copy of mask 0 but for other filters
|
||
*/
|
||
convertCANid2Reg(0x070, dSTANDARD_CAN_MSG_ID_2_0B, &RXM0EIDH, &RXM0EIDL, &RXM0SIDH, &RXM0SIDL);
|
||
convertCANid2Reg(0x070, dSTANDARD_CAN_MSG_ID_2_0B, &RXM1EIDH, &RXM1EIDL, &RXM1SIDH, &RXM1SIDL);
|
||
|
||
// filter 0 is broadcast message
|
||
convertCANid2Reg(0x000, dSTANDARD_CAN_MSG_ID_2_0B, &RXF0EIDH, &RXF0EIDL, &RXF0SIDH, &RXF0SIDL);
|
||
|
||
// filter 1 is message for controller
|
||
convertCANid2Reg(0x010, dSTANDARD_CAN_MSG_ID_2_0B, &RXF1EIDH, &RXF1EIDL, &RXF1SIDH, &RXF1SIDL);
|
||
|
||
// filter 2 is message for recipient n<>7, not yet defined
|
||
convertCANid2Reg(0x070, dSTANDARD_CAN_MSG_ID_2_0B, &RXF2EIDH, &RXF2EIDL, &RXF2SIDH, &RXF2SIDL);
|
||
|
||
/*
|
||
* ENABLE FILTERS
|
||
*
|
||
* Filter 0 set on mask 0
|
||
* Filter 1 set on mask 0
|
||
* Filter 2 set on mask 1
|
||
*/
|
||
RXFCON0 = 0x07;
|
||
|
||
|
||
/**
|
||
Assign Filters to Masks
|
||
*/
|
||
// Filter 0 & 1 assigned to mask 0 and filter 2 assigned to mask 1
|
||
MSEL0 = 0x10;
|
||
|
||
/**
|
||
Initialize CAN Timings
|
||
*/
|
||
|
||
/**
|
||
Baud rate: 250kbps
|
||
System frequency: 64000000
|
||
ECAN clock frequency: 64000000
|
||
Time quanta: 8
|
||
Sample point: 1-1-4-2
|
||
Sample point: 75%
|
||
*/
|
||
|
||
BRGCON1 = 0x0F;
|
||
BRGCON2 = 0x98;
|
||
BRGCON3 = 0x81;
|
||
|
||
|
||
ECAN_SetRXBnInterruptHandler(RXBnDefaultInterruptHandler);
|
||
PIR5bits.RXBnIF = 0;
|
||
PIE5bits.RXBnIE = 1;
|
||
|
||
ECAN_SetRXBnOverflowHandler(RXBnOverflowDefaultHandler);
|
||
ECAN_SetBusOffHandler(BusOffDefaultHandler);
|
||
ECAN_SetTXPassiveHandler(TXPassiveDefaultHandler);
|
||
ECAN_SetRXPassiveHandler(RXPassiveDefaultHandler);
|
||
ECAN_SetTXWarningHandler(TXWarningDefaultHandler);
|
||
ECAN_SetRXWarningHandler(RXWarningDefaultHandler);
|
||
PIR5bits.ERRIF = 0;
|
||
PIE5bits.ERRIE = 1;
|
||
|
||
CANCON = 0x00;
|
||
while (0x00 != (CANSTAT & 0xE0)); // wait until ECAN is in Normal mode
|
||
|
||
}
|
||
/**
|
||
Section: ECAN APIs
|
||
*/
|
||
void CAN_sleep(void)
|
||
{
|
||
CANCON = 0x20; // request disable mode
|
||
while ((CANSTAT & 0xE0) != 0x20); // wait until ECAN is in disable mode
|
||
//Wake up from sleep should set the CAN module straight into Normal mode
|
||
}
|
||
|
||
uint8_t CAN_transmit(uCAN_MSG *tempCanMsg)
|
||
{
|
||
uint8_t tempEIDH = 0;
|
||
uint8_t tempEIDL = 0;
|
||
uint8_t tempSIDH = 0;
|
||
uint8_t tempSIDL = 0;
|
||
uint8_t returnValue = 0;
|
||
|
||
if (TXB0CONbits.TXREQ != 1)
|
||
{
|
||
convertCANid2Reg(tempCanMsg->frame.id, tempCanMsg->frame.idType, &tempEIDH, &tempEIDL, &tempSIDH, &tempSIDL);
|
||
|
||
TXB0EIDH = tempEIDH;
|
||
TXB0EIDL = tempEIDL;
|
||
TXB0SIDH = tempSIDH;
|
||
TXB0SIDL = tempSIDL;
|
||
TXB0DLC = tempCanMsg->frame.dlc | ((tempCanMsg->frame.rtr)<<6);
|
||
TXB0D0 = tempCanMsg->frame.data0;
|
||
TXB0D1 = tempCanMsg->frame.data1;
|
||
TXB0D2 = tempCanMsg->frame.data2;
|
||
TXB0D3 = tempCanMsg->frame.data3;
|
||
TXB0D4 = tempCanMsg->frame.data4;
|
||
TXB0D5 = tempCanMsg->frame.data5;
|
||
TXB0D6 = tempCanMsg->frame.data6;
|
||
TXB0D7 = tempCanMsg->frame.data7;
|
||
|
||
TXB0CONbits.TXREQ = 1; //Set the buffer to transmit
|
||
returnValue = 1;
|
||
|
||
}
|
||
else if (TXB1CONbits.TXREQ != 1)
|
||
{
|
||
|
||
convertCANid2Reg(tempCanMsg->frame.id, tempCanMsg->frame.idType, &tempEIDH, &tempEIDL, &tempSIDH, &tempSIDL);
|
||
|
||
TXB1EIDH = tempEIDH;
|
||
TXB1EIDL = tempEIDL;
|
||
TXB1SIDH = tempSIDH;
|
||
TXB1SIDL = tempSIDL;
|
||
TXB1DLC = tempCanMsg->frame.dlc | ((tempCanMsg->frame.rtr)<<6);
|
||
TXB1D0 = tempCanMsg->frame.data0;
|
||
TXB1D1 = tempCanMsg->frame.data1;
|
||
TXB1D2 = tempCanMsg->frame.data2;
|
||
TXB1D3 = tempCanMsg->frame.data3;
|
||
TXB1D4 = tempCanMsg->frame.data4;
|
||
TXB1D5 = tempCanMsg->frame.data5;
|
||
TXB1D6 = tempCanMsg->frame.data6;
|
||
TXB1D7 = tempCanMsg->frame.data7;
|
||
|
||
TXB1CONbits.TXREQ = 1; //Set the buffer to transmit
|
||
returnValue = 1;
|
||
}
|
||
else if (TXB2CONbits.TXREQ != 1)
|
||
{
|
||
|
||
convertCANid2Reg(tempCanMsg->frame.id, tempCanMsg->frame.idType, &tempEIDH, &tempEIDL, &tempSIDH, &tempSIDL);
|
||
|
||
TXB2EIDH = tempEIDH;
|
||
TXB2EIDL = tempEIDL;
|
||
TXB2SIDH = tempSIDH;
|
||
TXB2SIDL = tempSIDL;
|
||
TXB2DLC = tempCanMsg->frame.dlc | ((tempCanMsg->frame.rtr)<<6);
|
||
TXB2D0 = tempCanMsg->frame.data0;
|
||
TXB2D1 = tempCanMsg->frame.data1;
|
||
TXB2D2 = tempCanMsg->frame.data2;
|
||
TXB2D3 = tempCanMsg->frame.data3;
|
||
TXB2D4 = tempCanMsg->frame.data4;
|
||
TXB2D5 = tempCanMsg->frame.data5;
|
||
TXB2D6 = tempCanMsg->frame.data6;
|
||
TXB2D7 = tempCanMsg->frame.data7;
|
||
|
||
TXB2CONbits.TXREQ = 1; //Set the buffer to transmit
|
||
returnValue = 1;
|
||
}
|
||
|
||
return (returnValue);
|
||
}
|
||
|
||
|
||
/**
|
||
Version A2 has a silicon errata
|
||
This code works for all revisions
|
||
*/
|
||
//Fix for Errata
|
||
#define dRXB0CON_FIFO_POINTER_VALUE 0
|
||
#define dRXB1CON_FIFO_POINTER_VALUE 1
|
||
#define dB0CON_FIFO_POINTER_VALUE 2
|
||
#define dB1CON_FIFO_POINTER_VALUE 3
|
||
#define dB2CON_FIFO_POINTER_VALUE 4
|
||
#define dB3CON_FIFO_POINTER_VALUE 5
|
||
#define dB4CON_FIFO_POINTER_VALUE 6
|
||
#define dB5CON_FIFO_POINTER_VALUE 7
|
||
|
||
uint8_t CAN_receive(uCAN_MSG *tempCanMsg) {
|
||
uint8_t returnValue = 0;
|
||
uint8_t tempECANCON;
|
||
uint8_t tempReg;
|
||
|
||
tempReg = (CANCON & 0x0F); //get the next RX buffer to read
|
||
tempECANCON = ECANCON; //Backup
|
||
ECANCON |= (tempReg + 0x10);
|
||
|
||
//Per Errata need to use this method to read out BxCON register
|
||
switch (tempReg)
|
||
{
|
||
case dRXB0CON_FIFO_POINTER_VALUE:
|
||
if (RXB0CONbits.RXFUL != 0) // Check RXB0
|
||
{
|
||
if ((RXB0SIDL & 0x08) == 0x08) //If Extended Message
|
||
{
|
||
//message is extended
|
||
tempCanMsg->frame.idType = (uint8_t) dEXTENDED_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2ExtendedCANid(RXB0EIDH, RXB0EIDL, RXB0SIDH, RXB0SIDL);
|
||
}
|
||
else
|
||
{
|
||
//message is standard
|
||
tempCanMsg->frame.idType = (uint8_t) dSTANDARD_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2StandardCANid(RXB0SIDH, RXB0SIDL);
|
||
}
|
||
|
||
tempCanMsg->frame.dlc = RXB0DLC & 0x0F;
|
||
tempCanMsg->frame.rtr = RXB0DLC >> 6;
|
||
tempCanMsg->frame.data0 = RXB0D0;
|
||
tempCanMsg->frame.data1 = RXB0D1;
|
||
tempCanMsg->frame.data2 = RXB0D2;
|
||
tempCanMsg->frame.data3 = RXB0D3;
|
||
tempCanMsg->frame.data4 = RXB0D4;
|
||
tempCanMsg->frame.data5 = RXB0D5;
|
||
tempCanMsg->frame.data6 = RXB0D6;
|
||
tempCanMsg->frame.data7 = RXB0D7;
|
||
RXB0CONbits.RXFUL = 0;
|
||
returnValue = 1;
|
||
}
|
||
break;
|
||
case dRXB1CON_FIFO_POINTER_VALUE:
|
||
if (RXB1CONbits.RXFUL != 0) // Check RXB1
|
||
{
|
||
if ((RXB0SIDL & 0x08) == 0x08) //If Extended Message
|
||
{
|
||
//message is extended
|
||
tempCanMsg->frame.idType = (uint8_t) dEXTENDED_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2ExtendedCANid(RXB0EIDH, RXB0EIDL, RXB0SIDH, RXB0SIDL);
|
||
} else {
|
||
//message is standard
|
||
tempCanMsg->frame.idType = (uint8_t) dSTANDARD_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2StandardCANid(RXB0SIDH, RXB0SIDL);
|
||
}
|
||
|
||
tempCanMsg->frame.dlc = RXB0DLC & 0x0F;
|
||
tempCanMsg->frame.rtr = RXB0DLC >> 6;
|
||
tempCanMsg->frame.data0 = RXB0D0;
|
||
tempCanMsg->frame.data1 = RXB0D1;
|
||
tempCanMsg->frame.data2 = RXB0D2;
|
||
tempCanMsg->frame.data3 = RXB0D3;
|
||
tempCanMsg->frame.data4 = RXB0D4;
|
||
tempCanMsg->frame.data5 = RXB0D5;
|
||
tempCanMsg->frame.data6 = RXB0D6;
|
||
tempCanMsg->frame.data7 = RXB0D7;
|
||
RXB1CONbits.RXFUL = 0;
|
||
returnValue = 1;
|
||
}
|
||
break;
|
||
case dB0CON_FIFO_POINTER_VALUE:
|
||
if (B0CONbits.RXFUL != 0) //Check B0
|
||
{
|
||
if ((RXB0SIDL & 0x08) == 0x08) //If Extended Message
|
||
{
|
||
//message is extended
|
||
tempCanMsg->frame.idType = (uint8_t) dEXTENDED_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2ExtendedCANid(RXB0EIDH, RXB0EIDL, RXB0SIDH, RXB0SIDL);
|
||
} else {
|
||
//message is standard
|
||
tempCanMsg->frame.idType = (uint8_t) dSTANDARD_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2StandardCANid(RXB0SIDH, RXB0SIDL);
|
||
}
|
||
|
||
tempCanMsg->frame.dlc = RXB0DLC & 0x0F;
|
||
tempCanMsg->frame.rtr = RXB0DLC >> 6;
|
||
tempCanMsg->frame.data0 = RXB0D0;
|
||
tempCanMsg->frame.data1 = RXB0D1;
|
||
tempCanMsg->frame.data2 = RXB0D2;
|
||
tempCanMsg->frame.data3 = RXB0D3;
|
||
tempCanMsg->frame.data4 = RXB0D4;
|
||
tempCanMsg->frame.data5 = RXB0D5;
|
||
tempCanMsg->frame.data6 = RXB0D6;
|
||
tempCanMsg->frame.data7 = RXB0D7;
|
||
B0CONbits.RXFUL = 0;
|
||
returnValue = 1;
|
||
}
|
||
break;
|
||
case dB1CON_FIFO_POINTER_VALUE:
|
||
if (B1CONbits.RXFUL != 0) //CheckB1
|
||
{
|
||
if ((RXB0SIDL & 0x08) == 0x08) //If Extended Message
|
||
{
|
||
//message is extended
|
||
tempCanMsg->frame.idType = (uint8_t) dEXTENDED_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2ExtendedCANid(RXB0EIDH, RXB0EIDL, RXB0SIDH, RXB0SIDL);
|
||
}
|
||
else
|
||
{
|
||
//message is standard
|
||
tempCanMsg->frame.idType = (uint8_t) dSTANDARD_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2StandardCANid(RXB0SIDH, RXB0SIDL);
|
||
}
|
||
|
||
tempCanMsg->frame.dlc = RXB0DLC & 0x0F;
|
||
tempCanMsg->frame.rtr = RXB0DLC >> 6;
|
||
tempCanMsg->frame.data0 = RXB0D0;
|
||
tempCanMsg->frame.data1 = RXB0D1;
|
||
tempCanMsg->frame.data2 = RXB0D2;
|
||
tempCanMsg->frame.data3 = RXB0D3;
|
||
tempCanMsg->frame.data4 = RXB0D4;
|
||
tempCanMsg->frame.data5 = RXB0D5;
|
||
tempCanMsg->frame.data6 = RXB0D6;
|
||
tempCanMsg->frame.data7 = RXB0D7;
|
||
B1CONbits.RXFUL = 0;
|
||
returnValue = 1;
|
||
}
|
||
break;
|
||
case dB2CON_FIFO_POINTER_VALUE:
|
||
if (B2CONbits.RXFUL != 0) //CheckB2
|
||
{
|
||
if ((RXB0SIDL & 0x08) == 0x08) //If Extended Message
|
||
{
|
||
//message is extended
|
||
tempCanMsg->frame.idType = (uint8_t) dEXTENDED_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2ExtendedCANid(RXB0EIDH, RXB0EIDL, RXB0SIDH, RXB0SIDL);
|
||
}
|
||
else
|
||
{
|
||
//message is standard
|
||
tempCanMsg->frame.idType = (uint8_t) dSTANDARD_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2StandardCANid(RXB0SIDH, RXB0SIDL);
|
||
}
|
||
|
||
tempCanMsg->frame.dlc = RXB0DLC & 0x0F;
|
||
tempCanMsg->frame.rtr = RXB0DLC >> 6;
|
||
tempCanMsg->frame.data0 = RXB0D0;
|
||
tempCanMsg->frame.data1 = RXB0D1;
|
||
tempCanMsg->frame.data2 = RXB0D2;
|
||
tempCanMsg->frame.data3 = RXB0D3;
|
||
tempCanMsg->frame.data4 = RXB0D4;
|
||
tempCanMsg->frame.data5 = RXB0D5;
|
||
tempCanMsg->frame.data6 = RXB0D6;
|
||
tempCanMsg->frame.data7 = RXB0D7;
|
||
B2CONbits.RXFUL = 0;
|
||
returnValue = 1;
|
||
}
|
||
break;
|
||
case dB3CON_FIFO_POINTER_VALUE:
|
||
if (B3CONbits.RXFUL != 0) //CheckB3
|
||
{
|
||
if ((RXB0SIDL & 0x08) == 0x08) //If Extended Message
|
||
{
|
||
//message is extended
|
||
tempCanMsg->frame.idType = (uint8_t) dEXTENDED_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2ExtendedCANid(RXB0EIDH, RXB0EIDL, RXB0SIDH, RXB0SIDL);
|
||
}
|
||
else
|
||
{
|
||
//message is standard
|
||
tempCanMsg->frame.idType = (uint8_t) dSTANDARD_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2StandardCANid(RXB0SIDH, RXB0SIDL);
|
||
}
|
||
|
||
tempCanMsg->frame.dlc = RXB0DLC & 0x0F;
|
||
tempCanMsg->frame.rtr = RXB0DLC >> 6;
|
||
tempCanMsg->frame.data0 = RXB0D0;
|
||
tempCanMsg->frame.data1 = RXB0D1;
|
||
tempCanMsg->frame.data2 = RXB0D2;
|
||
tempCanMsg->frame.data3 = RXB0D3;
|
||
tempCanMsg->frame.data4 = RXB0D4;
|
||
tempCanMsg->frame.data5 = RXB0D5;
|
||
tempCanMsg->frame.data6 = RXB0D6;
|
||
tempCanMsg->frame.data7 = RXB0D7;
|
||
B3CONbits.RXFUL = 0;
|
||
returnValue = 1;
|
||
}
|
||
break;
|
||
case dB4CON_FIFO_POINTER_VALUE:
|
||
if (B4CONbits.RXFUL != 0) //CheckB4
|
||
{
|
||
if ((RXB0SIDL & 0x08) == 0x08) //If Extended Message
|
||
{
|
||
//message is extended
|
||
tempCanMsg->frame.idType = (uint8_t) dEXTENDED_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2ExtendedCANid(RXB0EIDH, RXB0EIDL, RXB0SIDH, RXB0SIDL);
|
||
}
|
||
else
|
||
{
|
||
//message is standard
|
||
tempCanMsg->frame.idType = (uint8_t) dSTANDARD_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2StandardCANid(RXB0SIDH, RXB0SIDL);
|
||
}
|
||
|
||
tempCanMsg->frame.dlc = RXB0DLC & 0x0F;
|
||
tempCanMsg->frame.rtr = RXB0DLC >> 6;
|
||
tempCanMsg->frame.data0 = RXB0D0;
|
||
tempCanMsg->frame.data1 = RXB0D1;
|
||
tempCanMsg->frame.data2 = RXB0D2;
|
||
tempCanMsg->frame.data3 = RXB0D3;
|
||
tempCanMsg->frame.data4 = RXB0D4;
|
||
tempCanMsg->frame.data5 = RXB0D5;
|
||
tempCanMsg->frame.data6 = RXB0D6;
|
||
tempCanMsg->frame.data7 = RXB0D7;
|
||
B4CONbits.RXFUL = 0;
|
||
returnValue = 1;
|
||
}
|
||
break;
|
||
case dB5CON_FIFO_POINTER_VALUE:
|
||
if (B5CONbits.RXFUL != 0) //CheckB5
|
||
{
|
||
if ((RXB0SIDL & 0x08) == 0x08) //If Extended Message
|
||
{
|
||
//message is extended
|
||
tempCanMsg->frame.idType = (uint8_t) dEXTENDED_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2ExtendedCANid(RXB0EIDH, RXB0EIDL, RXB0SIDH, RXB0SIDL);
|
||
}
|
||
else
|
||
{
|
||
//message is standard
|
||
tempCanMsg->frame.idType = (uint8_t) dSTANDARD_CAN_MSG_ID_2_0B;
|
||
tempCanMsg->frame.id = convertReg2StandardCANid(RXB0SIDH, RXB0SIDL);
|
||
}
|
||
|
||
tempCanMsg->frame.dlc = RXB0DLC & 0x0F;
|
||
tempCanMsg->frame.rtr = RXB0DLC >> 6;
|
||
tempCanMsg->frame.data0 = RXB0D0;
|
||
tempCanMsg->frame.data1 = RXB0D1;
|
||
tempCanMsg->frame.data2 = RXB0D2;
|
||
tempCanMsg->frame.data3 = RXB0D3;
|
||
tempCanMsg->frame.data4 = RXB0D4;
|
||
tempCanMsg->frame.data5 = RXB0D5;
|
||
tempCanMsg->frame.data6 = RXB0D6;
|
||
tempCanMsg->frame.data7 = RXB0D7;
|
||
B5CONbits.RXFUL = 0;
|
||
returnValue = 1;
|
||
}
|
||
break;
|
||
}
|
||
|
||
ECANCON = tempECANCON;
|
||
return (returnValue);
|
||
}
|
||
|
||
uint8_t CAN_messagesInBuffer(void) {
|
||
uint8_t messageCount = 0;
|
||
if (RXB0CONbits.RXFUL != 0) //CheckRXB0
|
||
{
|
||
messageCount++;
|
||
}
|
||
if (RXB1CONbits.RXFUL != 0) //CheckRXB1
|
||
{
|
||
messageCount++;
|
||
}
|
||
if (B0CONbits.RXFUL_TXBIF != 0) //CheckB0
|
||
{
|
||
messageCount++;
|
||
}
|
||
if (B1CONbits.RXFUL_TXBIF != 0) //CheckB1
|
||
{
|
||
messageCount++;
|
||
}
|
||
if (B2CONbits.RXFUL_TXBIF != 0) //CheckB2
|
||
{
|
||
messageCount++;
|
||
}
|
||
if (B3CONbits.RXFUL_TXBIF != 0) //CheckB3
|
||
{
|
||
messageCount++;
|
||
}
|
||
if (B4CONbits.RXFUL_TXBIF != 0) //CheckB4
|
||
{
|
||
messageCount++;
|
||
}
|
||
if (B5CONbits.RXFUL_TXBIF != 0) //CheckB5
|
||
{
|
||
messageCount++;
|
||
}
|
||
return (messageCount);
|
||
}
|
||
|
||
uint8_t CAN_isBusOff(void)
|
||
{
|
||
uint8_t returnValue = 0;
|
||
|
||
//COMSTAT bit 5 TXBO: Transmitter Bus-Off bit
|
||
//1 = Transmit error counter > 255
|
||
//0 = Transmit error counter less then or equal to 255
|
||
|
||
if (COMSTATbits.TXBO == 1) {
|
||
returnValue = 1;
|
||
}
|
||
return (returnValue);
|
||
}
|
||
|
||
uint8_t CAN_isRXErrorPassive(void)
|
||
{
|
||
uint8_t returnValue = 0;
|
||
|
||
//COMSTAT bit 3 RXBP: Receiver Bus Passive bit
|
||
//1 = Receive error counter > 127
|
||
//0 = Receive error counter less then or equal to 127
|
||
|
||
if (COMSTATbits.RXBP == 1) {
|
||
returnValue = 1;
|
||
}
|
||
return (returnValue);
|
||
}
|
||
|
||
uint8_t CAN_isTXErrorPassive(void)
|
||
{
|
||
uint8_t returnValue = 0;
|
||
|
||
//COMSTAT bit 4 TXBP: Transmitter Bus Passive bit
|
||
//1 = Transmit error counter > 127
|
||
//0 = Transmit error counter less then or equal to 127
|
||
|
||
if (COMSTATbits.TXBP == 1)
|
||
{
|
||
returnValue = 1;
|
||
}
|
||
return (returnValue);
|
||
}
|
||
|
||
/**
|
||
Internal functions
|
||
*/
|
||
|
||
static uint32_t convertReg2ExtendedCANid(uint8_t tempRXBn_EIDH, uint8_t tempRXBn_EIDL, uint8_t tempRXBn_SIDH, uint8_t tempRXBn_SIDL) {
|
||
uint32_t returnValue = 0;
|
||
uint32_t ConvertedID = 0;
|
||
uint8_t CAN_standardLo_ID_lo2bits;
|
||
uint8_t CAN_standardLo_ID_hi3bits;
|
||
|
||
CAN_standardLo_ID_lo2bits = (uint8_t)(tempRXBn_SIDL & 0x03);
|
||
CAN_standardLo_ID_hi3bits = (uint8_t)(tempRXBn_SIDL >> 5);
|
||
ConvertedID = (uint32_t)(tempRXBn_SIDH << 3);
|
||
ConvertedID = ConvertedID + CAN_standardLo_ID_hi3bits;
|
||
ConvertedID = (ConvertedID << 2);
|
||
ConvertedID = ConvertedID + CAN_standardLo_ID_lo2bits;
|
||
ConvertedID = (ConvertedID << 8);
|
||
ConvertedID = ConvertedID + tempRXBn_EIDH;
|
||
ConvertedID = (ConvertedID << 8);
|
||
ConvertedID = ConvertedID + tempRXBn_EIDL;
|
||
returnValue = ConvertedID;
|
||
return (returnValue);
|
||
}
|
||
|
||
static uint32_t convertReg2StandardCANid(uint8_t tempRXBn_SIDH, uint8_t tempRXBn_SIDL) {
|
||
uint32_t returnValue = 0;
|
||
uint32_t ConvertedID;
|
||
//if standard message (11 bits)
|
||
//EIDH = 0 + EIDL = 0 + SIDH + upper three bits SIDL (3rd bit needs to be clear)
|
||
//1111 1111 111
|
||
ConvertedID = (uint32_t)(tempRXBn_SIDH << 3);
|
||
ConvertedID = ConvertedID + (uint32_t)(tempRXBn_SIDL >> 5);
|
||
returnValue = ConvertedID;
|
||
return (returnValue);
|
||
}
|
||
|
||
static void convertCANid2Reg(uint32_t tempPassedInID, uint8_t canIdType, uint8_t *passedInEIDH, uint8_t *passedInEIDL, uint8_t *passedInSIDH, uint8_t *passedInSIDL) {
|
||
uint8_t wipSIDL = 0;
|
||
|
||
if (canIdType == dEXTENDED_CAN_MSG_ID_2_0B)
|
||
{
|
||
//EIDL
|
||
*passedInEIDL = 0xFF & tempPassedInID; //CAN_extendedLo_ID_TX1 = &HFF And CAN_UserEnter_ID_TX1
|
||
tempPassedInID = tempPassedInID >> 8; //CAN_UserEnter_ID_TX1 = CAN_UserEnter_ID_TX1 >> 8
|
||
|
||
//EIDH
|
||
*passedInEIDH = 0xFF & tempPassedInID; //CAN_extendedHi_ID_TX1 = &HFF And CAN_UserEnter_ID_TX1
|
||
tempPassedInID = tempPassedInID >> 8; //CAN_UserEnter_ID_TX1 = CAN_UserEnter_ID_TX1 >> 8
|
||
|
||
//SIDL
|
||
//push back 5 and or it
|
||
wipSIDL = 0x03 & tempPassedInID;
|
||
tempPassedInID = tempPassedInID << 3; //CAN_UserEnter_ID_TX1 = CAN_UserEnter_ID_TX1 << 3
|
||
wipSIDL = (0xE0 & tempPassedInID) + wipSIDL;
|
||
wipSIDL = (uint8_t)(wipSIDL + 0x08); // TEMP_CAN_standardLo_ID_TX1 = TEMP_CAN_standardLo_ID_TX1 + &H8
|
||
*passedInSIDL = (uint8_t)(0xEB & wipSIDL); //CAN_standardLo_ID_TX1 = &HEB And TEMP_CAN_standardLo_ID_TX1
|
||
|
||
//SIDH
|
||
tempPassedInID = tempPassedInID >> 8;
|
||
*passedInSIDH = 0xFF & tempPassedInID;
|
||
}
|
||
else //(canIdType == dSTANDARD_CAN_MSG_ID_2_0B)
|
||
{
|
||
*passedInEIDH = 0;
|
||
*passedInEIDL = 0;
|
||
tempPassedInID = tempPassedInID << 5;
|
||
*passedInSIDL = 0xFF & tempPassedInID;
|
||
tempPassedInID = tempPassedInID >> 8;
|
||
*passedInSIDH = 0xFF & tempPassedInID;
|
||
}
|
||
}
|
||
|
||
void ECAN_SetRXBnInterruptHandler(void (*handler)(void))
|
||
{
|
||
RXBnInterruptHandler = handler;
|
||
}
|
||
|
||
void ECAN_RXBnI_ISR(void)
|
||
{
|
||
RXBnInterruptHandler();
|
||
PIR5bits.RXBnIF = 0; // The ECAN hardware overrides the setting of this bit (to '1') when any receive buffer is not empty.
|
||
}
|
||
|
||
void ECAN_SetRXBnOverflowHandler(void (*handler)(void))
|
||
{
|
||
RXBnOverflowHandler = handler;
|
||
}
|
||
|
||
void ECAN_SetBusOffHandler(void (*handler)(void))
|
||
{
|
||
BusOffHandler = handler;
|
||
}
|
||
|
||
void ECAN_SetTXPassiveHandler(void (*handler)(void))
|
||
{
|
||
TXPassiveHandler = handler;
|
||
}
|
||
|
||
void ECAN_SetRXPassiveHandler(void (*handler)(void))
|
||
{
|
||
RXPassiveHandler = handler;
|
||
}
|
||
|
||
void ECAN_SetTXWarningHandler(void (*handler)(void))
|
||
{
|
||
TXWarningHandler = handler;
|
||
}
|
||
|
||
void ECAN_SetRXWarningHandler(void (*handler)(void))
|
||
{
|
||
RXWarningHandler = handler;
|
||
}
|
||
|
||
void ECAN_ERRI_ISR(void)
|
||
{
|
||
if (COMSTATbits.RXB1OVFL)
|
||
{
|
||
RXBnOverflowHandler();
|
||
COMSTATbits.RXB1OVFL = 0; // In mode 2, this clears RXBnOVFL
|
||
}
|
||
|
||
if (COMSTATbits.TXBO)
|
||
{
|
||
BusOffHandler();
|
||
}
|
||
|
||
if (COMSTATbits.TXBP)
|
||
{
|
||
TXPassiveHandler();
|
||
}
|
||
|
||
if (COMSTATbits.RXBP)
|
||
{
|
||
RXPassiveHandler();
|
||
}
|
||
|
||
if (COMSTATbits.TXWARN)
|
||
{
|
||
TXWarningHandler();
|
||
}
|
||
|
||
if (COMSTATbits.RXWARN)
|
||
{
|
||
RXWarningHandler();
|
||
}
|
||
|
||
PIR5bits.ERRIF = 0;
|
||
}
|
||
|
||
|