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

📄 can.c

📁 利用xc167单片机上的双口can
💻 C
字号:
#ifdef TargetA
  #define ID0  0x100
  #define ID1  0x101
#else
  #define ID0  0x101
  #define ID1  0x100
#endif

#include "MAIN.H"

// Structure for a single TwinCAN object
// A total of 31 such object structures exists

struct stCanObj 
{
  ubyte  ubData[8];  // Message Data 0..7
  ulong  ulCANAR;    // Arbitration Register
  ulong  ulCANAMR;   // Acceptance Mask Register
  uword  uwMSGCTR;   // Message Control Register
  uword  uwCounter;  // Frame Counter
  uword  uwMSGCFG;   // Message Configuration Register
  uword  uwINP;      // Interrupt Node Pointer
  uword  uwCANFCR;   // FIFO / Gateway Control Register 
  uword  uwCANPTR;   // FIFO Pointer
  ulong  ulReserved; // Reserved
};

#define CAN_HWOBJ ((struct stCanObj volatile far *) 0x200300)


static ubyte aubFIFOWritePtr[16];
static ubyte aubFIFOReadPtr[16];


void CAN_vInit(void)
{
ubyte i;

  ///  -----------------------------------------------------------------------
  ///  Configuration of CAN Node A:
  ///  -----------------------------------------------------------------------

  ///  General Configuration of the Node A:
  ///  - set INIT and CCE

  CAN_ACR        =  0x0041;      // load global control register
  CAN_AGINP      =  0x0000;      // load global interrupt node pointer 
                                 // register

  ///  Configuration of the Node A Error Counter:
  ///  - the error warning threshold value (warning level) is 96

  CAN_AECNTH     =  0x0060;      // load error counter register high

  ///  Configuration of the used CAN Port Pins:
  ///  - P4.5 is used for CAN Interface Input (RXDCA)
  ///  - P4.6 is used for CAN Interface Output (TXDCA)

  ALTSEL0P4     |=  0x0040;      // select alternate output function
  DP4  = (DP4  & ~(uword)0x0040) | 0x0040;    //set direction register

  ///  Configuration of the Node A Baud Rate:
  ///  - required baud rate = 100,000 kbaud
  ///  - real baud rate     = 100,000 kbaud
  ///  - sample point       = 60,00 %
  ///  - there are 5 time quanta before sample point
  ///  - there are 4 time quanta after sample point
  ///  - the (re)synchronization jump width is 2 time quanta

  CAN_ABTRL      =  0x3453;      // load bit timing register low

  CAN_ABTRH      =  0x0000;      // load bit timing register high

  CAN_AFCRL      =  0x0000;      // load frame counter timing register low

  CAN_AFCRH      =  0x0000;      // load frame counter timing register high

  ///  -----------------------------------------------------------------------
  ///  Configuration of CAN Node B:
  ///  -----------------------------------------------------------------------

  ///  General Configuration of the Node B:
  ///  - set INIT and CCE

  CAN_BCR        =  0x0041;      // load global control register

  ///  -----------------------------------------------------------------------
  ///  Configuration of the CAN Message Objects 0 - 31:
  ///  -----------------------------------------------------------------------

  ///  -----------------------------------------------------------------------
  ///  Configuration of Message Object 0:
  ///  -----------------------------------------------------------------------
  ///  - message object 0 is valid

  CAN_MSGCTRL0   =  0x5595;      // load message control register low

  CAN_MSGCTRH0   =  0x0000;      // load message control register high

  ///  - message object is used as transmit object
  ///  - extended 29-bit identifier
  ///  - 1 valid data bytes
  ///  - this message object works with CAN node A
  ///  - remote monitoring is disabled

  CAN_MSGCFGL0   =  0x001C;      // load message configuration register low


  CAN_MSGCFGH0   =  0x0000;      // load message configuration register high

  ///  - acceptance mask 29-bit: 0xFFFF
  ///  - identifier 29-bit:      0x0100

  CAN_MSGAMRL0   =  0xFFFF;      // load acceptance mask register low

  CAN_MSGAMRH0   =  0x1FFF;      // load acceptance mask register high
  CAN_MSGARL0    =  ID1;         // load arbitration register low

  CAN_MSGARH0    =  0x0000;      // load arbitration register high

  CAN_MSGDRL00   =  0x0000;      // load data register 0 low
  CAN_MSGDRH00   =  0x0000;      // load data register 0 high
  CAN_MSGDRL04   =  0x0000;      // load data register 4 low

  CAN_MSGDRH04   =  0x0000;      // load data register 4 high

  ///  - functionality of standard message object

  CAN_MSGFGCRL0  =  0x0000;      // load FIFO/gateway control register low


  CAN_MSGFGCRH0  =  0x0000;      // load FIFO/gateway control register high

  ///  -----------------------------------------------------------------------
  ///  Configuration of Message Object 1:
  ///  -----------------------------------------------------------------------
  ///  - message object 1 is valid

  CAN_MSGCTRL1   =  0x5595;      // load message control register low

  CAN_MSGCTRH1   =  0x0000;      // load message control register high

  ///  - message object is used as receive object
  ///  - extended 29-bit identifier
  ///  - 1 valid data bytes
  ///  - this message object works with CAN node A
  ///  - remote monitoring is disabled

  CAN_MSGCFGL1   =  0x0014;      // load message configuration register low


  CAN_MSGCFGH1   =  0x0000;      // load message configuration register high

  ///  - acceptance mask 29-bit: 0xFFFF
  ///  - identifier 29-bit:      0x0101

  CAN_MSGAMRL1   =  0xFFFF;      // load acceptance mask register low

  CAN_MSGAMRH1   =  0x1FFF;      // load acceptance mask register high
  CAN_MSGARL1    =  ID0;         // load arbitration register low

  CAN_MSGARH1    =  0x0000;      // load arbitration register high

  CAN_MSGDRL10   =  0x0000;      // load data register 0 low
  CAN_MSGDRH10   =  0x0000;      // load data register 0 high
  CAN_MSGDRL14   =  0x0000;      // load data register 4 low

  CAN_MSGDRH14   =  0x0000;      // load data register 4 high

  ///  - functionality of standard message object

  CAN_MSGFGCRL1  =  0x0000;      // load FIFO/gateway control register low


  CAN_MSGFGCRH1  =  0x0001;      // load FIFO/gateway control register high


  ///  -----------------------------------------------------------------------
  ///  Configuration of Service Request Nodes 0 - 7:
  ///  -----------------------------------------------------------------------

  ///  -----------------------------------------------------------------------
  ///  Initialization of the FIFO Pointer:
  ///  -----------------------------------------------------------------------

  for (i = 0; i < 16; i++)
  {
    aubFIFOWritePtr[i] = i * 2;
    aubFIFOReadPtr[i]  = i * 2;
  }


  CAN_PISEL      =  0x0000;      // load port input select register

  //   -----------------------------------------------------------------------
  //   Start the CAN Nodes:
  //   -----------------------------------------------------------------------

  CAN_ACR       &= ~(uword)0x0041; // reset INIT and CCE

} 

void CAN_vGetMsgObj(ubyte ubObjNr, TCAN_SWObj *pstObj)
{
  ubyte i;

  for(i = 0; i < (CAN_HWOBJ[ubObjNr].uwMSGCFG & 0x00f0) >> 4; i++)
  {
    pstObj->ubData[i] = CAN_HWOBJ[ubObjNr].ubData[i];
  }

  if(CAN_HWOBJ[ubObjNr].uwMSGCFG & 0x04)  // extended identifier
  {
    pstObj->ulID   = CAN_HWOBJ[ubObjNr].ulCANAR;
    pstObj->ulMask = CAN_HWOBJ[ubObjNr].ulCANAMR;
  }
  else                                    // standard identifier 
  {
    pstObj->ulID   = CAN_HWOBJ[ubObjNr].ulCANAR >> 18;
    pstObj->ulMask = CAN_HWOBJ[ubObjNr].ulCANAMR >> 18;
  }

  pstObj->uwCounter = CAN_HWOBJ[ubObjNr].uwCounter;
  pstObj->uwMsgCfg  = CAN_HWOBJ[ubObjNr].uwMSGCFG;

} 

ubyte CAN_ubRequestMsgObj(ubyte ubObjNr)
{
  ubyte ubReturn;

  ubReturn = 0;
  if((CAN_HWOBJ[ubObjNr].uwMSGCTR & 0x3000) == 0x1000)  // if reset TXRQ 
  {
    CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xfbff;               // set CPUUPD 
    ubReturn = 1;
  }
  return(ubReturn);

} 

ubyte CAN_ubNewData(ubyte ubObjNr)
{
  ubyte ubReturn;

  ubReturn = 0;
  if((CAN_HWOBJ[ubObjNr].uwMSGCTR & 0x0300) == 0x0200)  // if NEWDAT
  {
    ubReturn = 1;
  }
  return(ubReturn);

} 

void CAN_vTransmit(ubyte ubObjNr)
{
  CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xe7ff;  // set TXRQ, reset CPUUPD

} 

void CAN_vConfigMsgObj(ubyte ubObjNr, TCAN_SWObj *pstObj)
{
  ubyte i;

  CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xfb7f;     // set CPUUPD, reset MSGVAL

  if(pstObj->uwMsgCfg & 0x0004)             // extended identifier
  {
    CAN_HWOBJ[ubObjNr].uwMSGCFG |= 0x0004;
    CAN_HWOBJ[ubObjNr].ulCANAR   = pstObj->ulID ;
    CAN_HWOBJ[ubObjNr].ulCANAMR  = pstObj->ulMask ;
  }
  else                                      // standard identifier
  {
    CAN_HWOBJ[ubObjNr].uwMSGCFG &= ~(uword)0x0004;
    CAN_HWOBJ[ubObjNr].ulCANAR   = pstObj->ulID << 18;
    CAN_HWOBJ[ubObjNr].ulCANAMR  = pstObj->ulMask << 18;
  }

  CAN_HWOBJ[ubObjNr].uwCounter = pstObj->uwCounter;

  CAN_HWOBJ[ubObjNr].uwMSGCFG  = (CAN_HWOBJ[ubObjNr].uwMSGCFG & 0x000f) | (pstObj->uwMsgCfg & 0x00f0);

  if(CAN_HWOBJ[ubObjNr].uwMSGCFG & 0x0008)  // if transmit direction
  {
    for(i = 0; i < (pstObj->uwMsgCfg & 0x00f0) >> 4; i++)
    {
      CAN_HWOBJ[ubObjNr].ubData[i] = pstObj->ubData[i];
    }
    CAN_HWOBJ[ubObjNr].uwMSGCTR  = 0xf6bf;  // set NEWDAT, reset CPUUPD, 
  }                                         // set MSGVAL
  else                                      // if receive direction
  {
    CAN_HWOBJ[ubObjNr].uwMSGCTR  = 0xf7bf;  // reset CPUUPD, set MSGVAL
  }

} 


void CAN_vLoadData(ubyte ubObjNr, ubyte *pubData)
{
  ubyte i;

  CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xfaff;       // set CPUUPD and NEWDAT

  for(i = 0; i < (CAN_HWOBJ[ubObjNr].uwMSGCFG & 0xf0) >> 4; i++)
  {
    CAN_HWOBJ[ubObjNr].ubData[i] = *(pubData++);
  }

  CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xf7ff;       // reset CPUUPD

} 

ubyte CAN_ubMsgLost(ubyte ubObjNr)
{
  ubyte ubReturn;

  ubReturn = 0;
  if((CAN_HWOBJ[ubObjNr].uwMSGCTR & 0x0c00) == 0x0800)  // if set MSGLST 
  {
    CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xf7ff;               // reset MSGLST 
    ubReturn = 1;
  }
  return(ubReturn);

} 


ubyte CAN_ubDelMsgObj(ubyte ubObjNr)
{
  ubyte ubReturn;

  ubReturn = 0;
  if(!(CAN_HWOBJ[ubObjNr].uwMSGCTR & 0xa200)) // if set RMTPND, TXRQ or NEWDAT
  {
    CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xff7f;     // reset MSGVAL
    ubReturn = 1;
  }
  return(ubReturn);

} 

void CAN_vReleaseObj(ubyte ubObjNr)
{
  CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xfdff;       // reset NEWDAT

} 

void CAN_vSetMSGVAL(ubyte ubObjNr)
{
  CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xffbf;  // set MSGVAL

} //  End of function CAN_vSetMSGVAL


ubyte CAN_ubWriteFIFO(ubyte ubObjNr, TCAN_SWObj *pstObj)
{
  ubyte i,j;
  ubyte ubReturn;

  ubReturn = 2;

  if((CAN_HWOBJ[ubObjNr].uwCANPTR & 0x0700) == 0x0200)  // if FIFO base object 
  {
    j = aubFIFOWritePtr[ubObjNr / 2];

    ubReturn = 0;
    if((CAN_HWOBJ[j].uwMSGCTR & 0x3000) == 0x1000)      // if reset TXRQ 
    {
      // CANPTRn(new) = CANPTR(old) & ~(uword)FSIZEn | (CANPTRn(old) + 1) & FZIZEn
      aubFIFOWritePtr[ubObjNr / 2] = ((aubFIFOWritePtr[ubObjNr / 2] & ~(uword)(CAN_HWOBJ[ubObjNr].uwCANFCR & 0x001f)) |
                                     ((aubFIFOWritePtr[ubObjNr / 2] + 1) & (CAN_HWOBJ[ubObjNr].uwCANFCR & 0x001f)));

      CAN_HWOBJ[j].uwMSGCTR = 0xf9ff;         // set CPUUPD, reset NEWDAT 

      if(CAN_HWOBJ[j].uwMSGCFG & 0x0004)      // if extended identifier
      {
        CAN_HWOBJ[j].ulCANAR   = pstObj->ulID ;
      }
      else                                    // if standard identifier
      {
        CAN_HWOBJ[j].ulCANAR   = pstObj->ulID << 18;
      }

      CAN_HWOBJ[j].uwMSGCFG  = (CAN_HWOBJ[j].uwMSGCFG & 0x000f) | 
                               (pstObj->uwMsgCfg & 0x00f0); // set DLC

      for(i = 0; i < (pstObj->uwMsgCfg & 0x00f0) >> 4; i++)
      {
        CAN_HWOBJ[j].ubData[i] = pstObj->ubData[i];
      }
      CAN_HWOBJ[j].uwMSGCTR  = 0x66bf;        // set TXRQ, NEWDAT, MSGVAL 
                                              // reset CPUUPD, RMTPND
      ubReturn = 1;
    }
  }
  return(ubReturn);

} 

ubyte CAN_ubReadFIFO(ubyte ubObjNr, TCAN_SWObj *pstObj)
{
  ubyte i,j;
  ubyte ubReturn;

  ubReturn = 2;

  if((CAN_HWOBJ[ubObjNr].uwCANPTR & 0x0700) == 0x0200)  // if FIFO base object 
  {
    j = aubFIFOReadPtr[ubObjNr / 2];

    ubReturn = 0;
    if((CAN_HWOBJ[j].uwMSGCTR & 0x0300) == 0x0200)    // if NEWDAT 
    {
      CAN_HWOBJ[j].uwMSGCTR = 0xfdff;                 // clear NEWDAT

      // CANPTRn(new) = CANPTR(old) & ~(uword)FSIZEn | (CANPTRn(old) + 1) & FZIZEn
      aubFIFOReadPtr[ubObjNr / 2] = ((aubFIFOReadPtr[ubObjNr / 2] & ~(uword)(CAN_HWOBJ[ubObjNr].uwCANFCR & 0x001f)) |
                                    ((aubFIFOReadPtr[ubObjNr / 2] + 1) & (CAN_HWOBJ[ubObjNr].uwCANFCR & 0x001f)));

      // check if the previous message was lost 
      if((CAN_HWOBJ[j].uwMSGCTR & 0x0c00) == 0x0800)  // if set MSGLST 
      {
        CAN_HWOBJ[j].uwMSGCTR = 0xf7ff;               // reset MSGLST 
        return(3);
      }

      for(i = 0; i < (CAN_HWOBJ[j].uwMSGCFG & 0x00f0) >> 4; i++)
      {
        pstObj->ubData[i] = CAN_HWOBJ[j].ubData[i];
      }

      if(CAN_HWOBJ[j].uwMSGCFG & 0x04)        // if extended identifier
      {
        pstObj->ulID   = CAN_HWOBJ[j].ulCANAR;
      }
      else                                    // if standard identifier 
      {
        pstObj->ulID   = CAN_HWOBJ[j].ulCANAR >> 18;
      }

      pstObj->uwMsgCfg  = CAN_HWOBJ[j].uwMSGCFG;

      // check if the message was corrupted 
      if((CAN_HWOBJ[j].uwMSGCTR & 0x0300) == 0x0200)  // if NEWDAT 
      {
        CAN_HWOBJ[j].uwMSGCTR = 0xfdff;               // clear NEWDAT
        return(4);
      }
      ubReturn = 1;
    }
  }
  return(ubReturn);

} 

ubyte CAN_ubFlushReadFIFO(ubyte ubObjNr)
{
  ubyte j;
  ubyte ubReturn;

  ubReturn = 0;

  if((CAN_HWOBJ[ubObjNr].uwCANPTR & 0x0700) == 0x0200)  // if FIFO base object 
  {
    aubFIFOReadPtr[ubObjNr / 2] = ubObjNr;
    CAN_HWOBJ[ubObjNr].uwCANPTR = (CAN_HWOBJ[ubObjNr].uwCANPTR & ~(uword)0x001F) | ubObjNr;

    for(j = ubObjNr; j < ubObjNr + (CAN_HWOBJ[ubObjNr].uwCANFCR & 0x001f); j++)
    {
      CAN_HWOBJ[j].uwMSGCTR = 0xf5ff;                   // reset MSGLST, NEWDAT 
    }
    // make sure that no new frame was received
    CAN_HWOBJ[ubObjNr].uwCANPTR = (CAN_HWOBJ[ubObjNr].uwCANPTR & ~(uword)0x001F) | ubObjNr;
    CAN_HWOBJ[ubObjNr].uwMSGCTR = 0xf5ff;               // reset MSGLST, NEWDAT 

    ubReturn = 1;
  }
  return(ubReturn);

} 

⌨️ 快捷键说明

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