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

📄 can.c

📁 freescale k40/k60 can 例程
💻 C
📖 第 1 页 / 共 3 页
字号:
         
         return (FLEXCAN_ERROR_SUCCESS);
}

void FlexCAN_Start(void)
{
      // De-assert Freeze Mode 
     pFlexCANReg->MCR &= ~(FLEXCAN_MCR_HALT);
     
     // Wait till exit of freeze mode
     while( pFlexCANReg->MCR & FLEXCAN_MCR_FRZ_ACK)
     {
     }
     
     // Wait till ready 
     while(pFlexCANReg->MCR & FLEXCAN_MCR_NOT_RDY)
     {
     }
}


void FlexCAN_Stop(void)
{
      // Assert Freeze Mode 
     pFlexCANReg->MCR |= (FLEXCAN_MCR_HALT);
     
     // Wait till enter freeze mode
     while(!(pFlexCANReg->MCR & FLEXCAN_MCR_FRZ_ACK))
     {
     }     
}


int16 FlexCAN_ConfigureRxFIFO_IDTable(uint32 idList[],uint16 idListNo)
{
    uint16  nTotalValidTabIDNo; // total # of Rx FIFO table RxIDs
    uint16  nIDTab;
    uint8   bIDAM;
    uint8   bIsExtID,bIsRTR;
    uint32  id;
    uint32  *pIDTabElement;
    int16   i,j;
    uint8   bFreezeMode;
    int16   status = FLEXCAN_ERROR_SUCCESS;
  

    // Calculate the total # of valid table elements
    bIDAM = (pFlexCANReg->MCR & FLEXCAN_MCR_IDAM_MASK)>>FLEXCAN_MCR_IDAM_BIT_NO;
    if(bIDAM == 3)
    {
        // all frames will be rejected, so just return without configuration
        status = FLEXCAN_ERROR_SUCCESS;
        return (status);
    }
    nTotalValidTabIDNo = (pFlexCANReg->CTRL2 & FLEXCAN_CTRL2_RFFN)>> FLEXCAN_CTRL2_RFFN_BIT_NO;
    nTotalValidTabIDNo = ((nTotalValidTabIDNo+1)<<3) * (1<<bIDAM);

    if((idListNo) > nTotalValidTabIDNo)
    {
        status = (FLEXCAN_ERROR_PARAM_OUT_OF_RANGE);
        return (status);
    }
    
    nIDTab = min(idListNo, nTotalValidTabIDNo);
   
    // Calculate the address of the starting ID Table Element corresponding startIDTabNo which bases 0
    pIDTabElement = (uint32*)&pFlexCANReg->MB[6];  // ID Filter Table Elements starts from MB6
  
    // Make sure FlexCAN is in Freeze mode before writing Filter tables
    if(!(pFlexCANReg->MCR & FLEXCAN_MCR_HALT))
    {
        FlexCAN_Stop(); // halt FlexCAN safely
        bFreezeMode = 0;
    }
    else
    {
        bFreezeMode = 1;
    }    
    // Configure the RX FIFO ID filter Tab elements
    for(i = 0; i < nIDTab; )
    {
        // Get IDE bit and RTR bit
        id = idList[i] & ~(CAN_MSG_IDE_MASK |CAN_MSG_TYPE_MASK);
        bIsExtID = (idList[i] &  CAN_MSG_IDE_MASK)>>CAN_MSG_IDE_BIT_NO;
        bIsRTR = (idList[i] &  CAN_MSG_TYPE_MASK)>>CAN_MSG_TYPE_BIT_NO;
        
        if(bIDAM==1)
        {
              // Format B two IDs
              *pIDTabElement = ((id & 0x03fff)<< (16+ (1-bIsExtID)*3)) | (bIsExtID<<30) | (bIsRTR<<31);        // RXIDB_0  
              i++;
              if(i < nIDTab)
              {
                id = idList[i] & ~(CAN_MSG_IDE_MASK |CAN_MSG_TYPE_MASK);
                bIsExtID = (idList[i] &  CAN_MSG_IDE_MASK)>>CAN_MSG_IDE_BIT_NO;
                bIsRTR = (idList[i] &  CAN_MSG_TYPE_MASK)>>CAN_MSG_TYPE_BIT_NO;
                *pIDTabElement |= ((id & 0x03fff)<< ((1-bIsExtID)*3)) | (bIsExtID<<14) | (bIsRTR<<15);    // RXIDB_1     
                i++;
              }              
        }
        else if (bIDAM==2)
        { 
            // Format C
            j = 0;
            *pIDTabElement = (id & 0x00ff) << (24-(j<<3));    // RXIDC_0
            i++;j++;
            do{
                if(i < nIDTab)
                {
                  id = idList[i] & ~(CAN_MSG_IDE_MASK |CAN_MSG_TYPE_MASK);
                  bIsExtID = (idList[i] &  CAN_MSG_IDE_MASK)>>CAN_MSG_IDE_BIT_NO;
                  bIsRTR = (idList[i] &  CAN_MSG_TYPE_MASK)>>CAN_MSG_TYPE_BIT_NO;
                  *pIDTabElement |= ((id & 0x00ff) << (24-(j<<3)));   // RXIDC_1 .. RXIDC_3
                  j++; i++;
                }
                else
                {
                  break;
                }
            }while(j<3);
        } 
        else if (!bIDAM)
        {
          if(bIsExtID)
          {   // Format A with extended ID
              *pIDTabElement = (id<<1) |  (bIsExtID<<30) | (bIsRTR<<31);    // single ID acceptance codes          
          }
          else
          {   // Format A with standard ID
               *pIDTabElement = (id<<19)  |  (bIsRTR<<31);    // single ID acceptance codes    RXIDA                 
          }
          i++;
        }
        pIDTabElement++;  // advance to the next ID table element
    } 
    // Enable Rx FIFO interrupt
   // pFlexCANReg->IMASK1 |=  FLEXCAN_IFLAG1_BUF5I;         
    
end:    
    // Restore FlexCAN operation mode
    if(!bFreezeMode)
    {
        FlexCAN_Start();
    }
    return (status);    
}


int16 FlexCAN_ConfigureRxMBMask(uint16 iMB,uint32 mask)
{
    uint8   bFreezeMode;
    
    if(iMB >  NUMBER_OF_MB)
    {
        return (FLEXCAN_ERROR_PARAM_OUT_OF_RANGE);
    }
    
    // Make sure FlexCAN is in Freeze mode
    if(!(pFlexCANReg->MCR & FLEXCAN_MCR_HALT))
    {
        FlexCAN_Stop(); // halt FlexCAN safely
        bFreezeMode = 0;
    }
    else
    {
        bFreezeMode = 1;
    }   
    // Check if individual masking is enabled
    if(pFlexCANReg->MCR & FLEXCAN_MCR_IRMQ)
    {
        // individual masks
        pFlexCANReg->RXIMR[iMB] = mask;
    }
    else
    {   // Legacy support with global masks
        if(iMB == 14)
        {
            pFlexCANReg->RX14MASK = mask;
        }
        else if (iMB == 15)
        {
            pFlexCANReg->RX15MASK = mask;        
        }
        else
        {
            pFlexCANReg->RXMGMASK = mask;
        }
    }
    // Restore FlexCAN operation mode
    if(!bFreezeMode)
    {
        FlexCAN_Start();
    }    
    return (FLEXCAN_ERROR_SUCCESS);
}


int16 FlexCAN_ConfigureRxFIFOFilterTabElementMask(uint16 iTabElement,uint32 mask)
{
    uint8   bFreezeMode;
    uint8   bIDAM;
    uint16  nTotalValidTabNo;
    
    bIDAM = (pFlexCANReg->MCR & FLEXCAN_MCR_IDAM_MASK)>>FLEXCAN_MCR_IDAM_BIT_NO;

    nTotalValidTabNo = (pFlexCANReg->CTRL2 & FLEXCAN_CTRL2_RFFN)>> FLEXCAN_CTRL2_RFFN_BIT_NO;
    nTotalValidTabNo = ((nTotalValidTabNo+1)<<3);

    
    if(iTabElement >  nTotalValidTabNo)
    {
        return (FLEXCAN_ERROR_PARAM_OUT_OF_RANGE);
    }
    
    // Make sure FlexCAN is in Freeze mode
    if(!(pFlexCANReg->MCR & FLEXCAN_MCR_HALT))
    {
        FlexCAN_Stop(); // halt FlexCAN safely
        bFreezeMode = 0;
    }
    else
    {
        bFreezeMode = 1;
    }   
    // Configure Rx FIFO table element filter
   // Check if individual masking is enabled
    if(pFlexCANReg->MCR & FLEXCAN_MCR_IRMQ)
    {
        // individual masks
        pFlexCANReg->RXIMR[iTabElement] = mask; // similar to MB RX IMR
    }
    else
    {   // Legacy support with global masks
         pFlexCANReg->RXFGMASK = mask;
    }    
  
    // Restore FlexCAN operation mode
    if(!bFreezeMode)
    {
        FlexCAN_Start();
    }    
    return (FLEXCAN_ERROR_SUCCESS);
}



int16 FlexCAN_ConfigureRxFIFOGlobalMask(uint32 mask)
{
    uint8   bFreezeMode;
    
    // 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;
    }   
    pFlexCANReg->RXFGMASK = mask;

    // Restore FlexCAN operation mode
    if(!bFreezeMode)
    {
        FlexCAN_Start();
    }    
    return (FLEXCAN_ERROR_SUCCESS);
}


                                 
void FlexCAN_Write(HANDLE h, uint32 msgID, uint8 prio,uint8 bBytes[], int8 iNoBytes)
{
     int16 i;

     
     if((wrTxMailBox+1) == rdTxMailBox)
     {
        // if queue full, return
        return;
     }
     TxMailBox[wrTxMailBox].identifier = msgID;
     TxMailBox[wrTxMailBox].priority = prio;
     TxMailBox[wrTxMailBox].data_len = iNoBytes;
     
     for(i = 0; i < iNoBytes; i++)
     {
      TxMailBox[wrTxMailBox].data[i] = bBytes[i];
     }
     //
     wrTxMailBox++;
     if(wrTxMailBox >=MAX_TX_MAILS)
     {
          wrTxMailBox = 0;
     }
     
     // Prepare transmit for the first time
     if(!occurence)
     {       
       occurence = 1;
       FlexCAN_PrepareAndStartTransmit(pFlexCANDrvObj->bTxMBStart,
                                 TxMailBox[rdTxMailBox].identifier, 
                                 TxMailBox[rdTxMailBox].priority,
                                 (uint8*)TxMailBox[rdTxMailBox].data,
                                 TxMailBox[rdTxMailBox].data_len,
                                 FLEXCAN_MB_CODE_TX_ONCE              // tx once
                                 );
        rdTxMailBox++;
          if(rdTxMailBox >=MAX_TX_MAILS)
          {
            rdTxMailBox = 0;
          }        
     }    
}


int16 FlexCAN_Read(HANDLE h, int16 iMailBoxQue, uint32 *id, uint8 data[])
{
     int16 i;
     int16 noBytes = 0;

     if(rdRxMailBox == wrRxMailBox)
     {
        // if queue empty, return
        return (noBytes);
     }
     
     *id = RxMailBox[rdRxMailBox].identifier; 
     noBytes =  RxMailBox[rdRxMailBox].data_len;
    
     for(i = 0; i < noBytes; i++)
     {
       data[i] =  RxMailBox[rdRxMailBox].data[i];
     }
     rdRxMailBox++;
     if(rdRxMailBox >=MAX_RX_MAILS)
     {
          rdRxMailBox = 0;
     } 
     return (noBytes);     
}


int16 FlexCAN_Read_RxFIFOQueue(HANDLE h, uint32 *id, uint8 data[])
{
     int16 i;
     int16 noBytes = 0;
                 
     if(rdRxFIFOQue == wrRxFIFOQue)
     {
        // if queue empty, return
        return (noBytes);
     }
     
     *id = RxFIFOQue[rdRxFIFOQue].identifier; 
     noBytes =  RxFIFOQue[rdRxFIFOQue].data_len;
    
     for(i = 0; i < noBytes; i++)
     {
       data[i] =  RxFIFOQue[rdRxFIFOQue].data[i];
     }
     rdRxFIFOQue++;
     if(rdRxFIFOQue >=MAX_RXFIFO_MAILS)
     {
          rdRxFIFOQue = 0;
     } 
     return (noBytes);     
}


void FlexCAN_PrepareTransmit(uint16 iTxMBNo,uint32 msgID, uint8 prio,uint8 bBytes[], int8 iNoBytes)
{
   int16  i,wno,bno;
   uint32 word[2] = {0, 0};
   
   if(iTxMBNo >= NUMBER_OF_MB || iNoBytes >8)
   {
      return; // out of range
   }
    // convert data bytes to words
    wno = (iNoBytes-1)>>2;
    bno = (iNoBytes-1)%4;
    if(wno >0)
    {
    	word[0] = ((bBytes[0]<<24) | (bBytes[1]<<16) | (bBytes[2]<< 8) | bBytes[3]);
    }
    for(i=0;i<=bno;i++)
    {
       word[wno] |=   bBytes[(wno<<2)+i] << (24-(i<<3)); 
    } 
    // Get IDE bit and RTR bit
    wno = (msgID &  CAN_MSG_IDE_MASK)>>CAN_MSG_IDE_BIT_NO;
    bno = (msgID &  CAN_MSG_TYPE_MASK)>>CAN_MSG_TYPE_BIT_NO;
    
    // Get ID bit no
    i =  wno? 0: FLEXCAN_MB_ID_STD_BIT_NO;
    
    // Follow 4 steps for Transmit Process
    pFlexCANReg->MB[iTxMBNo].CS = FLEXCAN_MB_CS_CODE(FLEXCAN_MB_CODE_TX_INACTIVE) // write inactive code
    				| (wno<<FLEXCAN_MB_CS_IDE_BIT_NO)
    				| (bno<<FLEXCAN_MB_CS_RTR_BIT_NO)
                                | FLEXCAN_MB_CS_LENGTH(iNoBytes)      // can write size here
    				;
    pFlexCANReg->MB[iTxMBNo].ID = (prio << FLEXCAN_MB_ID_PRIO_BIT_NO) | ((msgID & ~(CAN_MSG_IDE_MASK|CAN_MSG_TYPE_MASK))<<i);    
    pFlexCANReg->MB[iTxMBNo].WORD0 = word[0];
    pFlexCANReg->MB[iTxMBNo].WORD1 = word[1];   
   
    // do not start transmit
}


void FlexCAN_PrepareAndStartTransmit(uint16 iTxMBNo,uint32 msgID, uint8 prio,uint8 bBytes[], int8 iNoBytes, uint8 txCode)
{
   int16  i,wno,bno;
   uint32 word[2] = {0, 0};
   
   if(iTxMBNo >= NUMBER_OF_MB || iNoBytes >8)
   {
      return; // out of range
   }
   
   // Enable tx MB interrupt
   //pFlexCANReg->IMASK1 |=  (1<<iTxMBNo);    
   
   // Flag transfer starts
   bMBFlags1 &= ~(1<<iTxMBNo);
   
   //
   FlexCAN_PrepareTransmit(iTxMBNo,msgID,prio, bBytes,iNoBytes);
    
   
    // Start transmit with specified tx code
    pFlexCANReg->MB[iTxMBNo].CS = (pFlexCANReg->MB[iTxMBNo].CS & ~(FLEXCAN_MB_CS_CODE_MASK)) | FLEXCAN_MB_CS_CODE(txCode) // write activate code
    				|  FLEXCAN_MB_CS_LENGTH(iNoBytes);     
}


void FlexCAN_WriteCode(uint16 iTxMBNo, uint8 txrxCode)
{

⌨️ 快捷键说明

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