⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can.c

📁 freescale k40/k60 can 例程
💻 C
📖 第 1 页 / 共 3 页
字号:

#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 + -