📄 can.c
字号:
#include "can.h"
// Globals
TFCAN_MailBox RxMailBox[MAX_RX_MAILS]; // receive mail box queue
TFCAN_MailBox TxMailBox[MAX_TX_MAILS]; // transmit mail box queue
TFCAN_MailBox RxFIFOQue[MAX_RXFIFO_MAILS]; // rx FIFO queue
volatile int16 rdRxMailBox, // read pointer for RxMailBox
wrRxMailBox, // write pointer for RxMailBox
rdTxMailBox, // read pointer for TxMailBox
wrTxMailBox; // write pointer for TxMailBox
volatile int16 rdRxFIFOQue; // read pointer for RxFIFO queue
volatile int16 wrRxFIFOQue; // write pointer for RxFIFO queue
volatile uint32 nCANErrorCount;
volatile uint32 bMBFlags1,bMBFlags2; // flag if a MB is done by ISR
static int8 occurence;
static CAN_MemMapPtr pFlexCANReg = // pointer to the CAN register
#ifndef USE_FLEXCAN0
CAN1_BASE_PTR
#else
CAN0_BASE_PTR
#endif
;
static TFCANDrv_Obj FlexCANDrvObj;
static PTFCANDrv_Obj pFlexCANDrvObj;
// Prototypes
static void FlexCAN_MB_Callback(uint16 iMBNo);
static void FlexCAN_Err_Callback(uint32 status);
static void FlexCAN_RxFIFOErr_Callback(void);
// Functions
HANDLE FlexCAN_Open(void)
{
int16 i;
// Initialize the driver structures
for(i = 0; i < MAX_RX_MAILS; i++)
{
RxMailBox[i].dev_num = 0;
}
for(i = 0; i < MAX_TX_MAILS; i++)
{
TxMailBox[i].dev_num = 0;
}
for(i = 0; i < MAX_RXFIFO_MAILS; i++)
{
RxFIFOQue[i].dev_num = 0;
}
rdRxMailBox = wrRxMailBox = 0;
rdTxMailBox = wrTxMailBox = 0;
rdRxFIFOQue = wrRxFIFOQue = 0;
occurence = 0; nCANErrorCount = 0;
bMBFlags1 = bMBFlags2 = 0;
// Initialize driver object based on custom macro definitions
pFlexCANDrvObj = &FlexCANDrvObj;
pFlexCANDrvObj->ctrlWord.Bits.bClockSource = (FLEXCAN_CLOCK_SOURCE? 1 : 0);
pFlexCANDrvObj->ctrlWord.Bits.bSelfRxDis = (FLEXCAN_SELF_RECEPTION? 0 : 1);
pFlexCANDrvObj->ctrlWord.Bits.bScanPrio = (FLEXCAN_SCAN_PRIORITY? 1 : 0);
pFlexCANDrvObj->ctrlWord.Bits.bStoreRTR = (FLEXCAN_STORE_RTR? 1 : 0);
pFlexCANDrvObj->ctrlWord.Bits.bEACEN = (FLEXCAN_ENTIRE_ARB_CMP? 1: 0);
pFlexCANDrvObj->ctrlWord.Bits.bIRMQ = (FLEXCAN_INDIVIDUAL_MASK? 1 : 0);
pFlexCANDrvObj->ctrlWord.Bits.bLoopBack = (FLEXCAN_LOOP_BACK? 1 : 0);
pFlexCANDrvObj->ctrlWord.Bits.bLocalPrio = (FLEXCAN_LOCAL_PRIO? 1 : 0);
pFlexCANDrvObj->bRxMBStart = FLEXCAN_RX_MB_START; /* start index of Rx MB# */
pFlexCANDrvObj->bRxMBEnd = FLEXCAN_RX_MB_END; /* end index of Rx MB# */
pFlexCANDrvObj->bTxMBStart = FLEXCAN_TX_MB_START; /* start index of Tx MB# */
pFlexCANDrvObj->bTxMBEnd = FLEXCAN_TX_MB_END; /* end index of Tx MB# */
pFlexCANDrvObj->bRxFIFOFilterNo = FLEXCAN_NO_RXFIFO_FILTERS;
pFlexCANDrvObj->bRxFIFOIDFormat = FLEXCAN_ID_TAB_FORMAT;
pFlexCANDrvObj->pCANRegs = pFlexCANReg;
return ((HANDLE) pFlexCANReg);
}
int16 FlexCAN_Init(uint32 baudrateKHz )
{
int16 i;
int8 isCAN0;
// Enable clock to FlexCAN
isCAN0 = (pFlexCANReg == CAN0_BASE_PTR);
if(isCAN0)
{
SIM_SCGC6 |= SIM_SCGC6_FLEXCAN0_MASK;
}
else
{
SIM_SCGC3 |= SIM_SCGC3_FLEXCAN1_MASK;
}
// Configure NVIC to enable interrupts
if(isCAN0)
{
NVICICPR0 = (NVICICPR0 & ~(0x07<<29)) | (0x07<<29); // Clear any pending interrupts on FLEXCAN0
NVICISER0 = (NVICISER0 & ~(0x07<<29)) | (0x07<<29); // Enable interrupts for FLEXCAN0
NVICICPR1 = (NVICICPR1 & ~(0x1F<<0)) | (0x1F); // Clear any pending interrupts on FLEXCAN0
NVICISER1 = (NVICISER1 & ~(0x1F<<0)) | (0x1F); // Enable interrupts for FLEXCAN0
}
else
{
NVICICPR1 = (NVICICPR1 & ~(0xFF<<5)) | (0xFF<<5); // Clear any pending interrupts on FLEXCAN1
NVICISER1 = (NVICISER1 & ~(0xFF<<5)) | (0xFF<<5); // Enable interrupts for FLEXCAN1
}
// Select clock source for CAN first
// NOTE: must ensure that LPM_ACK = 1 before changing clock source bit
if(pFlexCANDrvObj->ctrlWord.Bits.bClockSource)
{
pFlexCANReg->CTRL1 |= FLEXCAN_CTRL_CLK_SRC; //Source --> bus clock
}
else
{
pFlexCANReg->CTRL1 &= ~FLEXCAN_CTRL_CLK_SRC; //Source --> external oscillator
}
// Enable CAN module
pFlexCANReg->MCR |= FLEXCAN_MCR_FRZ; // enable HALT feature
pFlexCANReg->MCR &= ~FLEXCAN_MCR_MDIS;
while((FLEXCAN_MCR_LPM_ACK & pFlexCANReg->MCR));
// Now can apply Soft Reset
pFlexCANReg->MCR ^= FLEXCAN_MCR_SOFT_RST;
while(FLEXCAN_MCR_SOFT_RST & pFlexCANReg->MCR);
// Now it should be in Freeze mode
while(!(FLEXCAN_MCR_FRZ_ACK & pFlexCANReg->MCR));
// Disable self-reception
if(pFlexCANDrvObj->ctrlWord.Bits.bSelfRxDis)
{
pFlexCANReg->MCR |= FLEXCAN_MCR_SRX_DIS;
}
// Enable individual masking and queue
if(pFlexCANDrvObj->ctrlWord.Bits.bIRMQ)
{
pFlexCANReg->MCR |= FLEXCAN_MCR_IRMQ;
}
// Set local priority
if(pFlexCANDrvObj->ctrlWord.Bits.bLocalPrio)
{
pFlexCANReg->MCR |= FLEXCAN_MCR_LPRIO_EN;
}
/* Initialize all 16 MBs */
for(i=0;i<NUMBER_OF_MB;i++)
{
pFlexCANReg->MB[i].CS = 0x00000000;
pFlexCANReg->MB[i].ID = 0x00000000;
pFlexCANReg->MB[i].WORD0 = 0x00000000;
pFlexCANReg->MB[i].WORD1 = 0x00000000;
}
// Set RRS and EACEN bits in CTRL2
if(pFlexCANDrvObj->ctrlWord.Bits.bEACEN)
{
pFlexCANReg->CTRL2 |= FLEXCAN_CTRL2_EACEN;
}
else
{
pFlexCANReg->CTRL2 &= ~FLEXCAN_CTRL2_EACEN;
}
if(pFlexCANDrvObj->ctrlWord.Bits.bStoreRTR)
{
pFlexCANReg->CTRL2 |= FLEXCAN_CTRL2_RRS;
}
else
{
pFlexCANReg->CTRL2 &= ~FLEXCAN_CTRL2_RRS;
}
// Set Scan priority (Mailbxes reception priority)
if(pFlexCANDrvObj->ctrlWord.Bits.bScanPrio)
{
pFlexCANReg->CTRL2 |= FLEXCAN_CTRL2_MRP;
}
else
{
pFlexCANReg->CTRL2 &= ~FLEXCAN_CTRL2_MRP;
}
// Eanble RxFIFO if # of RxFIFO filters is >0
if(pFlexCANDrvObj->bRxFIFOFilterNo)
{
pFlexCANReg->MCR |= FLEXCAN_MCR_FEN;
// Configure RFFN field with # of Rx FIFO filters
FLEXCAN_set_rffn(pFlexCANReg->CTRL2,((pFlexCANDrvObj->bRxFIFOFilterNo>>3)-1));
}
// Set ID filter table format
pFlexCANReg->MCR |= (pFlexCANReg->MCR & ~FLEXCAN_MCR_IDAM_MASK) | FLEXCAN_MCR_IDAM(pFlexCANDrvObj->bRxFIFOIDFormat);
// Configure bit rate
switch (baudrateKHz)
{
case (33): // 33.33K
if(pFlexCANReg->CTRL1 & FLEXCAN_CTRL_CLK_SRC)
{
/*
** 48M/120= 400k sclock, 12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 3, PSEG1 = 4, PSEG2 = 4,PRESDIV = 120
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(119));
}
else
{
/*
** 12M/20= 600k sclock, 18Tq
** PROPSEG = 1, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 4, PSEG1 = 8, PSEG2 = 8,PRESDIV = 20
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(0) | FLEXCAN_CTRL_RJW(3)
| FLEXCAN_CTRL_PSEG1(7) | FLEXCAN_CTRL_PSEG2(7)
| FLEXCAN_CTRL_PRESDIV(19));
}
break;
case (83): // 83.33K
if(pFlexCANReg->CTRL1 & FLEXCAN_CTRL_CLK_SRC)
{
/*
** 48M/48= 1M sclock, 12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 3, PSEG1 = 4, PSEG2 = 4,PRESDIV = 48
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(47));
}
else
{
/*
** 12M/12= 1M sclock, 12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 3, PSEG1 = 4, PSEG2 = 4,PRESDIV = 12
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(11));
}
break;
case (50):
if(pFlexCANReg->CTRL1 & FLEXCAN_CTRL_CLK_SRC)
{
/*
** 48M/80= 0.6M sclock, 12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 3, PSEG1 = 4, PSEG2 = 4, PRESDIV = 40
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(79));
}
else
{
/*
** 12M/20= 0.6M sclock, 12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 3, PSEG1 = 4, PSEG2 = 4, PRESDIV = 20
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(19));
}
break;
case (100):
if(pFlexCANReg->CTRL1 & FLEXCAN_CTRL_CLK_SRC)
{
/*
** 48M/40= 1.2M sclock, 12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 3, PSEG1 = 4, PSEG2 = 4, PRESDIV = 40
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(39));
}
else
{
/*
** 12M/10= 1.2M sclock, 12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 3, PSEG1 = 4, PSEG2 = 4, PRESDIV = 10
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(9));
}
break;
case (125):
if(pFlexCANReg->CTRL1 & FLEXCAN_CTRL_CLK_SRC)
{
/*
** 48M/32= 1.5M sclock, 12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 3, PSEG1 = 4, PSEG2 = 4, PRESDIV = 32
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(31));
}
else
{
/*
** 12M/8= 1.5M sclock, 12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 3, PSEG1 = 4, PSEG2 = 4, PRESDIV = 8
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(2)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(7));
}
break;
case (250):
if(pFlexCANReg->CTRL1 & FLEXCAN_CTRL_CLK_SRC)
{
/*
** 48M/16= 3M sclock, 12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 2, PSEG1 = 4, PSEG2 = 4, PRESDIV = 16
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(15));
}
else
{
/*
** 12M/4= 3M sclock, 12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 2, PSEG1 = 4, PSEG2 = 4, PRESDIV = 4
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(3));
}
break;
case (500):
if(pFlexCANReg->CTRL1 & FLEXCAN_CTRL_CLK_SRC)
{
/*
** 48M/8=6M sclock, 12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 2, PSEG1 = 4, PSEG2 = 4, PRESDIV = 6
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(7));
}
else
{
/*
** 12M/2=6M sclock, 12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 2, PSEG1 = 4, PSEG2 = 4, PRESDIV = 2
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(1)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(1));
}
break;
case (1000):
if(pFlexCANReg->CTRL1 & FLEXCAN_CTRL_CLK_SRC)
{
/*
** 48M/6=8M sclock
** PROPSEG = 4, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 1, PSEG1 = 1, PSEG2 = 2, PRESCALER = 6
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(3) | FLEXCAN_CTRL_RJW(0)
| FLEXCAN_CTRL_PSEG1(0) | FLEXCAN_CTRL_PSEG2(1)
| FLEXCAN_CTRL_PRESDIV(5));
}
else
{
/*
** 12M/1=12M sclock,12Tq
** PROPSEG = 3, LOM = 0x0, LBUF = 0x0, TSYNC = 0x0, SAMP = 1
** RJW = 4, PSEG1 = 4, PSEG2 = 4, PRESCALER = 1
*/
pFlexCANReg->CTRL1 = (0 | FLEXCAN_CTRL_PROPSEG(2) | FLEXCAN_CTRL_RJW(3)
| FLEXCAN_CTRL_PSEG1(3) | FLEXCAN_CTRL_PSEG2(3)
| FLEXCAN_CTRL_PRESDIV(0));
}
break;
default:
return (FLEXCAN_ERROR_INVALID_BAUD);
}
if(pFlexCANDrvObj->ctrlWord.Bits.bLoopBack)
{
// use loopback for single node
pFlexCANReg->CTRL1 |= FLEXCAN_CTRL_LPB;
}
else
{
// use external CAN bus
pFlexCANReg->CTRL1 &= ~FLEXCAN_CTRL_LPB;
}
/* Initialize mask registers */
pFlexCANReg->RXMGMASK = 0x1FFFFFFF;
pFlexCANReg->RX14MASK = 0x1FFFFFFF;
pFlexCANReg->RX15MASK = 0x1FFFFFFF;
/* Initialize individual mask registers for the queue */
if(pFlexCANReg->MCR & FLEXCAN_MCR_IRMQ)
{
for(i = 0; i < NUMBER_OF_MB ; i++)
{
pFlexCANReg->RXIMR[i] = 0x1FFFFFFFL;
}
}
// Enable interrupts
//pFlexCANReg->IMASK1 |= (1<<FLEXCAN_RX_MB_START) | (1<<FLEXCAN_TX_MB_START);
// Start communication
FlexCAN_Start();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -