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

📄 can.c

📁 freescale k40/k60 can 例程
💻 C
📖 第 1 页 / 共 3 页
字号:
   uint8   bFreezeMode;
   
   if(iTxMBNo >= NUMBER_OF_MB)
   {
      return; // out of range
   }    
    // Make sure FlexCAN is in Freeze mode
    if(!(pFlexCANReg->MCR & FLEXCAN_MCR_HALT)) //FLEXCAN_MCR_FRZ_ACK))
    {
        FlexCAN_Stop(); // halt FlexCAN safely
        bFreezeMode = 0;
    }
    else
    {
        bFreezeMode = 1;
    }      
    // Start transmit/receive with specified tx/rx code
    pFlexCANReg->MB[iTxMBNo].CS = (pFlexCANReg->MB[iTxMBNo].CS & ~(FLEXCAN_MB_CS_CODE_MASK)) 
          | FLEXCAN_MB_CS_CODE(txrxCode) // write code
            ;
   
    // Restore FlexCAN operation mode
    if(!bFreezeMode)
    {
        FlexCAN_Start();
    }       
}



/**************************************************************
					ReadCANMB
** Read directly from CAN Message Buffer up to 8 bytes and return
** the size in bytes of data read.
 					
** NOTE:
** So the ID format is:
** B31 30 29 28 27 26 ... 11 10 9 8 7 6 5 4 3 2 1 0
** |	|	 |									  |
** |    |    |------------------------------------|
** |	|					|--> 29 bits ID
** |	|
** |    |--> 1: RTR bit set, 0: RTR bit clear
** |
** |--> 1 : Extended ID, 0: Standardard ID
**************************************************************/
uint16 FlexCAN_ReadCANMB(uint16 iMB, uint32 *id, uint32 * timeStamp, uint8 *data, uint8 bUnlock )
{
	int8 i,wno,bno;
	uint16 code;
	uint8 *pMBData;
	int16 length;
        int8  leftBytes;
        int8  format;
        uint8 *pBytes = data;
	
        // Lock the MB
        code = FLEXCAN_get_code(pFlexCANReg->MB[iMB].CS);
 
	length = FLEXCAN_get_length(pFlexCANReg->MB[iMB].CS);       
        // 
        format = (pFlexCANReg->MB[iMB].CS & FLEXCAN_MB_CS_IDE)? 1:0;
	*id = (pFlexCANReg->MB[iMB].ID & FLEXCAN_MB_ID_EXT_MASK);
        if(!format)  
        {
            // standard ID
          *id >>= FLEXCAN_MB_ID_STD_BIT_NO;         
        }
        else
        { 
          *id |= CAN_MSG_IDE_MASK;          // flag extended ID
        }
        format = (pFlexCANReg->MB[iMB].CS & FLEXCAN_MB_CS_RTR)? 1:0;  
        if(format)
        {
          *id |= CAN_MSG_TYPE_MASK;         // flag Remote Frame type
        }
        // Read message bytes
        wno = (length-1)>>2;
        bno = length-1;
        if(wno>0)
        {
            //
            (*(uint32*)pBytes) = pFlexCANReg->MB[iMB].WORD0;
            swap_4bytes(pBytes);
            bno -= 4;
            pMBData = (uint8*)&pFlexCANReg->MB[iMB].WORD1+3;
        }
        else
        {
            pMBData = (uint8*)&pFlexCANReg->MB[iMB].WORD0+3;
        }
	for(i=0; i <= bno; i++)
	{
          pBytes[i+(wno<<2)] = *pMBData--;	
        }
       
       // Read time stamp
       *timeStamp = pFlexCANReg->MB[iMB].CS & FLEXCAN_MB_CS_TIMESTAMP_MASK ;
    
        if(bUnlock)
        {
          // Unlock the MB
          code = pFlexCANReg->TIMER;
        }
	return length;
}


/**************************************************************
					PrepareRxCANMB
** Prepare a CAN MB for rx.
 					
** NOTE:
** If using FCANMB_SET_ID or FCANMB_GET_ID, consider the condition:
** #define FCAN_ID_EXT 0x80000000	// specifies extended ID anywhere the ID is required
** #define FCAN_ID_RTR 0x40000000	// turns on the RTR bit when calling FCANMB_SET_ID (only)
** So the ID format is:
** B31 30 29 28 27 26 ... 11 10 9 8 7 6 5 4 3 2 1 0
** |	|	 |									  |
** |    |    |------------------------------------|
** |	|					|--> 29 bits ID
** |	|
** |    |--> 1: RTR bit set, 0: RTR bit clear
** |
** |--> 1 : Extended ID, 0: Standardard ID
**************************************************************/
void FlexCAN_PrepareRxCANMB(uint16 iMB, uint32 id)
{
      uint32 id2;
      
	// Deactivate the rx MB for cpu write 
        pFlexCANReg->MB[iMB].CS = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_RX_INACTIVE); // write inactive code	
	
	// Write ID
        id2 = id & ~(CAN_MSG_IDE_MASK | CAN_MSG_TYPE_MASK);
        if(id & CAN_MSG_IDE_MASK)
        {
           pFlexCANReg->MB[iMB].ID = id2;
        }
        else
        {
           pFlexCANReg->MB[iMB].ID = id2<<FLEXCAN_MB_ID_STD_BIT_NO;          
        }
         // Activate the MB for rx 
        pFlexCANReg->MB[iMB].CS = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_RX_EMPTY);    
        
        // flag to caller transfer is started
        bMBFlags1 &= ~(1<<iMB);
}


void    FlexCAN_EnableMB_Interrupt(uint16 iMB)
{
      pFlexCANReg->IMASK1 |= (1<<iMB);
}

void    FlexCAN_DisableMB_Interrupt(uint16 iMB)
{
      pFlexCANReg->IMASK1 &= ~(1<<iMB);
}


uint8   FlexCAN_Is_Transfer_Done(uint16 iMB)
{
   if(bMBFlags1 & (1<<iMB))
   {
     return 1;
   }
   return 0;
}

void	FlexCAN_MB_ISR(void)
{
	// Check Rx MB flags, so Rx MBs has highest priority than Tx MBs
        FlexCAN_Poll_RxMBs();
        
	// Check Tx MB flags
        FlexCAN_Poll_TxMBs();
        
        // Check Rx FIFO status and handle it
        // If Rx FIFO is enabled, check FIFO flag
        if(pFlexCANReg->MCR & FLEXCAN_MCR_FEN)	
        {        
          FlexCAN_Poll_RxFIFO();
        }
}

void    FlexCAN_Poll_RxMBs(void)
{
  	int16 iMB;

	for(iMB =  pFlexCANDrvObj->bRxMBStart; iMB <=  pFlexCANDrvObj->bRxMBEnd; iMB++)
	{
		if(pFlexCANReg->IFLAG1 & (1<<iMB))
		{
			 // Read the Message information
                         if((wrRxMailBox+1) != rdRxMailBox)
                         {
                           RxMailBox[wrRxMailBox].data_len = 
                              FlexCAN_ReadCANMB(iMB, 
                                                (uint32*)&RxMailBox[wrRxMailBox].identifier, 
                                                (uint32*)&RxMailBox[wrRxMailBox].timestamp, 
                                                (uint8*)RxMailBox[wrRxMailBox].data,
                                                 1);
                           wrRxMailBox++;
                           if(wrRxMailBox >=MAX_RX_MAILS)
                           {
                             wrRxMailBox = 0;
                           }
                         }
                         
			 // clear flag
			 pFlexCANReg->IFLAG1 = (1<<iMB);
                         
                         bMBFlags1 |= (1<<iMB);       // set flag to caller indicating this MB is done
			 
			 // Call custom Rx callback to do follow up processing 
                         FlexCAN_MB_Callback(iMB);
		}
	}  
}


void    FlexCAN_Poll_TxMBs(void)
{
      int16 iMB;
    
      for(iMB =  pFlexCANDrvObj->bTxMBStart; iMB <=  pFlexCANDrvObj->bTxMBEnd; iMB++)
      {
              if(pFlexCANReg->IFLAG1 & (1<<iMB))
              {
                       // Read the time stamp information
                       if(rdTxMailBox != wrTxMailBox)
                       {
                          // if Tx MailBox not empty,do
                          FlexCAN_PrepareAndStartTransmit(iMB,
                                       TxMailBox[rdTxMailBox].identifier, 
                                       TxMailBox[rdTxMailBox].priority,
                                       (uint8*)TxMailBox[rdTxMailBox].data,
                                       TxMailBox[rdTxMailBox].data_len,
                                       FLEXCAN_MB_CODE_TX_ONCE              // tx once code
                                       );
                          rdTxMailBox++;
                          if(rdTxMailBox >=MAX_TX_MAILS)
                          {
                            rdTxMailBox = 0;
                          } 
                       }
                       else
                       {
                          occurence = 0;  // flag to call PrepareTransmit again
                          bMBFlags1 |= (1<<iMB);       // set flag to caller indicating this MB is done by ISR
                       }
                       // clear flag
                       pFlexCANReg->IFLAG1 = (1<<iMB);
                                              
                       // Call custom Tx callback to do follow up processing
                       // such as queue another message to be transmitted
                       FlexCAN_MB_Callback(iMB);
              }	
      }  
}
  
  
void    FlexCAN_Poll_RxFIFO(void)
{
    uint16  iMatchHit;
    
          if(pFlexCANReg->IFLAG1 & FLEXCAN_IFLAG1_BUF5I)
           {
              // frames are available in Rx FIFO, read it into RxFIFO queue
               if((wrRxFIFOQue+1) != rdRxFIFOQue)
               {
                 RxFIFOQue[wrRxFIFOQue].data_len = 
                    FlexCAN_ReadCANMB(0, // MB0 is the read buffer of RxFIFO 
                                      (uint32*)&RxFIFOQue[wrRxFIFOQue].identifier, 
                                      (uint32*)&RxFIFOQue[wrRxFIFOQue].timestamp, 
                                      (uint8*)RxFIFOQue[wrRxFIFOQue].data,
                                       0);
                 // read RXFIR
		 iMatchHit = pFlexCANReg->RXFIR & 0x1FF;
                 
                 wrRxFIFOQue++;
                 if(wrRxFIFOQue >=MAX_RXFIFO_MAILS)
                 {
                   wrRxFIFOQue = 0;
                 }
               }              
              // clear Rx FIFO flag
              pFlexCANReg->IFLAG1 = FLEXCAN_IFLAG1_BUF5I;
           }
           // Check Rx FIFO Warning flag
           if(pFlexCANReg->IFLAG1 & FLEXCAN_IFLAG1_BUF6I)
           {
              pFlexCANReg->IFLAG1 = FLEXCAN_IFLAG1_BUF6I;
           }
           // Check Rx FIFO Overflow flag
           if(pFlexCANReg->IFLAG1 & FLEXCAN_IFLAG1_BUF7I)
           {
              // This should be error
              nCANErrorCount++;
              
              pFlexCANReg->IFLAG1 = FLEXCAN_IFLAG1_BUF7I;
              
              // Call RxFIFO error call back
              FlexCAN_RxFIFOErr_Callback();
           } 
}



void	FlexCAN_BusOff_ISR(void)
{
       pFlexCANReg->ESR1 = FLEXCAN_ESR_BOFF_INT;  
}

void	FlexCAN_Error_ISR(void)
{
	// check error flags
	uint32_t status;
	
	status = pFlexCANReg->ESR1;
	
	if( status  & FLEXCAN_ESR_ERR_INT)
	{
		nCANErrorCount++;
                
                // Call CAN error call back                		
		FlexCAN_Err_Callback(status);
                
		// clear the error flag
		pFlexCANReg->ESR1 = status;		
	}	
}

void	FlexCAN_TxWarning_ISR(void)
{
      pFlexCANReg->ESR1 = FLEXCAN_ESR_TX_WRN;  
      //printf("FlexCAN Transmit warning occured!\n");
}

void	FlexCAN_RxWarning_ISR(void)
{
      pFlexCANReg->ESR1 = FLEXCAN_ESR_RX_WRN;  
      //printf("FlexCAN Receive warning occured!\n");  
}

void	FlexCAN_Wakeup_ISR(void)
{

      pFlexCANReg->ESR1 = FLEXCAN_ESR_WAK_INT;	// clear wakeup interrupt
      //printf("FlexCAN wakeup interrupt occurs!\n");
}

void	FlexCAN_IMEU_ISR(void)
{
    pFlexCANReg->ESR2 = FLEXCAN_ESR2_IMEUF; 
}


void	FlexCAN_LostRx_ISR(void)
{
    if( pFlexCANReg->ESR2  & FLEXCAN_ESR2_LOSTRLF)
    {
        // Lost Rx is locked 
        pFlexCANReg->ESR2 = FLEXCAN_ESR2_LOSTRLF;
    }
    if( pFlexCANReg->ESR2  & FLEXCAN_ESR2_LOSTRMF)
    {
        // Lost Rx is matched
        pFlexCANReg->ESR2 = FLEXCAN_ESR2_LOSTRMF;      
    }    
    //printf("FlexCAN Lost receive interrupt occurs!\n");  
}


uint16 FlexCAN_CheckAbortStatus(uint16 iMB)
{
  uint8 code;
  // If it is still pending, just return pending status
  if(!(pFlexCANReg->IFLAG1 & (1<<iMB)))
  {
      return (FLEXCAN_ERROR_PENDING_TX);
  }
  // Check CODE field to see if it is aborted or not
  code = FLEXCAN_get_code(pFlexCANReg->MB[iMB].CS);
  if(code == FLEXCAN_MB_CODE_TX_ABORT)
  {
    // Abort success
    return (FLEXCAN_ERROR_SUCCESS);
  }
  else if(code == FLEXCAN_MB_CODE_TX_INACTIVE )
  {
      // MB is not aborted but transmitted instead
      return (FLEXCAN_ERROR_TX_DONE);
  }
  // Other status
  return (FLEXCAN_ERROR_TX_ERR);
}


// Callback routines
void    FlexCAN_MB_Callback(uint16 iMBNo)
{
}

void    FlexCAN_RxFIFOErr_Callback(void)
{
}

void    FlexCAN_Err_Callback(uint32 status)
{
        if(status & FLEXCAN_ESR_BIT0_ERR)
        {
                printf("BIT0 error occured!\n");
        }	
        if(status & FLEXCAN_ESR_BIT1_ERR)
        {
                printf("BIT1 error occured!\n");
        }
        if(status & FLEXCAN_ESR_STF_ERR)
        {
                printf("Stuffing error occured!\n");
        }
        if(status & FLEXCAN_ESR_FRM_ERR)
        {
                printf("Form error occured!\n");
        }
        if(status & FLEXCAN_ESR_CRC_ERR)
        {
                printf("CRC error occured!\n");
        }
        if(status & FLEXCAN_ESR_ACK_ERR)
        {
                printf("Ack error occured!\n");
        }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -