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

📄 can_hw.c

📁 LPC2368 CAN总线例子程序
💻 C
📖 第 1 页 / 共 2 页
字号:
  msg->len      = ((U8)(CANData >> 16)) & 0x0F;

  /* Read CAN message identifier                                             */
  msg->id = ptrcan->CANRID;

  /* Read the data if received message was DATA FRAME                        */
  if (msg->type == DATA_FRAME)  {     

    /* Read first 4 data bytes                                               */
    CANAddr = (U32 *) &msg->data[0];
    *CANAddr++ = ptrcan->CANRDA;

    /* Read second 4 data bytes                                              */
    *CANAddr   = ptrcan->CANRDB;
  }
}


/*--------------------------- CAN_hw_set ------------------------------------
 *  Set a message that will automatically be sent as an answer to the REMOTE
 *  FRAME message, as this functionality is not enabled by hardware this 
 *  function is not implemented
 *
 *  Parameter:  ctrl:       Ignored
 *              msg:        Pointer to CAN message to be set
 *
 *  Return:     CAN_ERROR:  Error code
 *---------------------------------------------------------------------------*/

CAN_ERROR CAN_hw_set (U32 ctrl, CAN_msg *msg)  {

  return CAN_NOT_IMPLEMENTED_ERROR;
}


/*--------------------------- CAN_hw_rx_object ------------------------------
 *
 *  Enable reception of messages, on specified controller with specified 
 *  identifier, by setting acceptance filter
 *
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x)
 *              ch:         Ignored for LPC2xxx
 *              id:         CAN message identifier
 *              CAN_FORMAT: Format of CAN identifier (standard or extended)
 *
 *  Return:     CAN_ERROR:  Error code
 *---------------------------------------------------------------------------*/

CAN_ERROR CAN_hw_rx_object (U32 ctrl, U32 ch, U32 id, CAN_FORMAT format)  {
  U32 ctrl0 = ctrl-1;                 /* Controller index 0 .. x-1           */
  static S16 CAN_std_cnt = 0;
  static S16 CAN_ext_cnt = 0;
  regCAN_AF    *ptrcan_af    = (regCAN_AF *) CAN_AF_BASE;
  regCAN_AFRAM *ptrcan_afram = (regCAN_AFRAM *) CAN_AFRAM_BASE;
  U32 buf0, buf1;
  S16 cnt1, cnt2, bound1;

  /* Acceptance Filter Memory full                                           */
  if ((((CAN_std_cnt + 1) >> 1) + CAN_ext_cnt) >= 512)
    return CAN_OBJECTS_FULL_ERROR;

  /* Setup Acceptance Filter Configuration                                   
     Acceptance Filter Mode Register = Off                                   */
  ptrcan_af->AFMR = 0x00000001;

  if (format == STANDARD_FORMAT)  {   /* Add mask for standard identifiers   */
    id |= ctrl0 << 13;                /* Add controller number               */
    id &= 0x0000F7FF;                 /* Mask out 16-bits of ID              */

    /* Move all remaining extended mask entries one place up                 
       if new entry will increase standard ID filters list                   */
    if ((CAN_std_cnt & 0x0001) == 0 && CAN_ext_cnt != 0) {
      cnt1   = (CAN_std_cnt >> 1);
      bound1 = CAN_ext_cnt;
      buf0   = ptrcan_afram->mask[cnt1];
      while (bound1--)  {
        cnt1++;
        buf1 = ptrcan_afram->mask[cnt1];
        ptrcan_afram->mask[cnt1] = buf0;
        buf0 = buf1;
      }        
    }

    if (CAN_std_cnt == 0)  {          /* For entering first  ID              */
      ptrcan_afram->mask[0] = 0x0000FFFF | (id << 16);
    }  else if (CAN_std_cnt == 1)  {  /* For entering second ID              */
      if ((ptrcan_afram->mask[0] >> 16) > id)
        ptrcan_afram->mask[0] = (ptrcan_afram->mask[0] >> 16) | (id << 16);
      else
        ptrcan_afram->mask[0] = (ptrcan_afram->mask[0] & 0xFFFF0000) | id;
    }  else  {
      /* Find where to insert new ID                                         */
      cnt1 = 0;
      cnt2 = CAN_std_cnt;
      bound1 = (CAN_std_cnt - 1) >> 1;
      while (cnt1 <= bound1)  {       /* Loop through standard existing IDs  */
        if ((ptrcan_afram->mask[cnt1] >> 16) > id)  {
          cnt2 = cnt1 * 2;
          break;
        }
        if ((ptrcan_afram->mask[cnt1] & 0x0000FFFF) > id)  {
          cnt2 = cnt1 * 2 + 1;
          break;
        }
        cnt1++;                       /* cnt1 = U32 where to insert new ID   */
      }                               /* cnt2 = U16 where to insert new ID   */

      if (cnt1 > bound1)  {           /* Adding ID as last entry             */
        if ((CAN_std_cnt & 0x0001) == 0)/* Even number of IDs exists         */
          ptrcan_afram->mask[cnt1]  = 0x0000FFFF | (id << 16);
        else                              /* Odd  number of IDs exists       */
          ptrcan_afram->mask[cnt1]  = (ptrcan_afram->mask[cnt1] & 0xFFFF0000) | id;
      }  else  {
        buf0 = ptrcan_afram->mask[cnt1];/* Remember current entry            */
        if ((cnt2 & 0x0001) == 0)     /* Insert new mask to even address     */
          buf1 = (id << 16) | (buf0 >> 16);
        else                          /* Insert new mask to odd  address     */
          buf1 = (buf0 & 0xFFFF0000) | id;
     
        ptrcan_afram->mask[cnt1] = buf1;/* Insert mask                       */

        bound1 = CAN_std_cnt >> 1;
        /* Move all remaining standard mask entries one place up             */
        while (cnt1 < bound1)  {
          cnt1++;
          buf1  = ptrcan_afram->mask[cnt1];
          ptrcan_afram->mask[cnt1] = (buf1 >> 16) | (buf0 << 16);
          buf0  = buf1;
        }

        if ((CAN_std_cnt & 0x0001) == 0)/* Even number of IDs exists         */
          ptrcan_afram->mask[cnt1] = (ptrcan_afram->mask[cnt1] & 0xFFFF0000) | (0x0000FFFF);
      }
    }
    CAN_std_cnt++;
  }  else  {                          /* Add mask for extended identifiers   */
    id |= (ctrl0) << 29;              /* Add controller number               */

    cnt1 = ((CAN_std_cnt + 1) >> 1);
    cnt2 = 0;
    while (cnt2 < CAN_ext_cnt)  {     /* Loop through extended existing masks*/
      if (ptrcan_afram->mask[cnt1] > id)
        break;
      cnt1++;                         /* cnt1 = U32 where to insert new mask */
      cnt2++;
    }

    buf0 = ptrcan_afram->mask[cnt1];  /* Remember current entry              */
    ptrcan_afram->mask[cnt1] = id;    /* Insert mask                         */

    CAN_ext_cnt++;

    bound1 = CAN_ext_cnt - 1;
    /* Move all remaining extended mask entries one place up                 */
    while (cnt2 < bound1)  {
      cnt1++;
      cnt2++;
      buf1 = ptrcan_afram->mask[cnt1];
      ptrcan_afram->mask[cnt1] = buf0;
      buf0 = buf1;
    }        
  }
  
  /* Calculate std ID start address (buf0) and ext ID start address (buf1)   */
  buf0 = ((CAN_std_cnt + 1) >> 1) << 2;
  buf1 = buf0 + (CAN_ext_cnt << 2);

  /* Setup acceptance filter pointers                                        */
  ptrcan_af->SFF_sa     = 0;
  ptrcan_af->SFF_GRP_sa = buf0;
  ptrcan_af->EFF_sa     = buf0;
  ptrcan_af->EFF_GRP_sa = buf1;
  ptrcan_af->ENDofTable = buf1;

  ptrcan_af->AFMR = 0x00000000;       /* Use acceptance filter               */

  return CAN_OK;
}

/*--------------------------- CAN_hw_tx_object ------------------------------
 *
 *  This function has no usage on LPC2xxx, and so it does nothing
 *
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x)
 *              ch:         Ignored for LPC2xxx
 *              id:         CAN message identifier
 *              CAN_FORMAT: Format of CAN identifier (standard or extended)
 *
 *  Return:     CAN_ERROR:  Error code
 *---------------------------------------------------------------------------*/

CAN_ERROR CAN_hw_tx_object (U32 ctrl, U32 ch, CAN_FORMAT format)  {

  return CAN_OK;
}


/************************* Interrupt Functions *******************************/

/*--------------------------- CAN_ISR ---------------------------------------
 *
 *  CAN receive and transmit interrupt function for all controllers
 *  Reads message from hardware registers and puts it into receive mailboxes
 *  If there are messages in mailbox for transmit it writes it to hardware
 *  and starts the transmission
 *
 *  Parameter:  none
 *
 *  Return:     none
 *---------------------------------------------------------------------------*/

static void CAN_ISR (void) __irq  {
  CAN_msg *ptrmsg;
  U32 temp;

  /* If message is received and if mailbox isn't full read message from 
     hardware and send it to message queue                                   */
#if USE_CAN_CTRL1 == 1
  if (CAN1GSR & 0x01) {
    if (os_mbx_check (MBX_rx_ctrl[0]) > 0) {
      ptrmsg = _alloc_box (CAN_mpool);
      CAN_hw_rd (1, ptrmsg);
      CAN1CMR = 0x04;                   /* Release receive buffer            */
      isr_mbx_send (MBX_rx_ctrl[0], ptrmsg);
    }
  }
#endif
#if USE_CAN_CTRL2 == 1
  if (CAN2GSR & 0x01) {
    if (os_mbx_check (MBX_rx_ctrl[1]) > 0) {
      ptrmsg = _alloc_box (CAN_mpool);
      CAN_hw_rd (2, ptrmsg);
      CAN2CMR = 0x04;                   /* Release receive buffer            */
      isr_mbx_send (MBX_rx_ctrl[1], ptrmsg);
    }
  }
#endif

  /* If there is message in mailbox ready for send, and if transmission
     hardware is ready, read the message from mailbox and send it            */
#if USE_CAN_CTRL1 == 1
  if (CAN1GSR & (1 << 3)) {
    if (isr_mbx_receive (MBX_tx_ctrl[0], (void **)&ptrmsg) != OS_R_OK) {
      CAN_hw_wr (1, ptrmsg);
      _free_box(CAN_mpool, ptrmsg);
    } else {
      isr_sem_send(wr_sem[0]);    /* Return a token back to semaphore        */
    }
  }
#endif
#if USE_CAN_CTRL2 == 1
  if (CAN2GSR & (1 << 3)) {
    if (isr_mbx_receive (MBX_tx_ctrl[1], (void **)&ptrmsg) != OS_R_OK) {
      CAN_hw_wr (2, ptrmsg);
      _free_box(CAN_mpool, ptrmsg);
    } else {
      isr_sem_send(wr_sem[1]);    /* Return a token back to semaphore        */
    }
  }
#endif

  /* Read from interrupt register to acknowledge interrupt                   */
#if USE_CAN_CTRL1 == 1
  temp = ptrCAN1->CANICR;
#endif
#if USE_CAN_CTRL2 == 1
  temp = ptrCAN2->CANICR;
#endif
  VICVectAddr = 0xFFFFFFFF;           /* Acknowledge Interrupt               */
}


/*----------------------------------------------------------------------------
 * end of file
 *---------------------------------------------------------------------------*/

⌨️ 快捷键说明

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