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

📄 can_hw.c

📁 LPC2368 CAN总线例子程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*----------------------------------------------------------------------------
 *      R T L  -  C A N   D r i v e r
 *----------------------------------------------------------------------------
 *      Name:    CAN_Hw.c
 *      Purpose: CAN Driver, Hardware specific module for LPC2xxx
 *      Rev.:    V3.12
 *----------------------------------------------------------------------------
 *      This code is part of the RealView Run-Time Library.
 *      Copyright (c) 2004-2007 KEIL - An ARM Company. All rights reserved.
 *---------------------------------------------------------------------------*/

#include <RTL.h>                      /* RTX kernel functions & defines      */
#include <LPC23xx.h>                  /* LPC23xx definitions                 */
#include "RTX_CAN.h"                  /* CAN Generic functions & defines     */
#include "CAN_hw.h"                   /* CAN hw specific functions & defines */
#include "CAN_reg.h"                  /* LPC2xxx CAN registers               */

#pragma diag_suppress 550

/* Values of bit time register for different baudrates
   NT = Nominal bit time = TSEG1 + TSEG2 + 3
   SP = Sample point     = ((TSEG2 +1) / (TSEG1 + TSEG2 + 3)) * 100%
                                            SAM,  SJW, TSEG1, TSEG2, NT,  SP */
const U32 CAN_BIT_TIME[] = {          0, /*             not used             */
                                      0, /*             not used             */
                                      0, /*             not used             */
                                      0, /*             not used             */
                             0x0001C000, /* 0+1,  3+1,   1+1,   0+1,  4, 75% */
                                      0, /*             not used             */
                             0x0012C000, /* 0+1,  3+1,   2+1,   1+1,  6, 67% */
                                      0, /*             not used             */
                             0x0023C000, /* 0+1,  3+1,   3+1,   2+1,  8, 63% */
                                      0, /*             not used             */
                             0x0025C000, /* 0+1,  3+1,   5+1,   2+1, 10, 70% */
                                      0, /*             not used             */
                             0x0036C000, /* 0+1,  3+1,   6+1,   3+1, 12, 67% */
                                      0, /*             not used             */
                                      0, /*             not used             */
                             0x0048C000, /* 0+1,  3+1,   8+1,   4+1, 15, 67% */
                             0x0049C000, /* 0+1,  3+1,   9+1,   4+1, 16, 69% */
                           };


/*----------------------------------------------------------------------------
 *      CAN RTX Hardware Specific Driver Functions for LPC2xxx
 *----------------------------------------------------------------------------
 *  Functions implemented in this module:
 *    static CAN_ERROR CAN_hw_set_baudrate (U32 ctrl, U32 baudrate)
 *           CAN_ERROR CAN_hw_setup        (U32 ctrl)
 *           CAN_ERROR CAN_hw_init         (U32 ctrl, U32 baudrate)
 *           CAN_ERROR CAN_hw_start        (U32 ctrl)
 *           CAN_ERROR CAN_hw_tx_empty     (U32 ctrl)
 *           CAN_ERROR CAN_hw_wr           (U32 ctrl, CAN_msg *msg)
 *    static      void CAN_hw_rd           (U32 ctrl, CAN_msg *msg)
 *           CAN_ERROR CAN_hw_set          (U32 ctrl, CAN_msg *msg)
 *           CAN_ERROR CAN_hw_rx_object    (U32 ctrl, U32 ch, U32 id, CAN_FORMAT format)
 *           CAN_ERROR CAN_hw_tx_object    (U32 ctrl, U32 ch, CAN_FORMAT format)
 *    Interrupt fuctions
 *---------------------------------------------------------------------------*/

/* Static functions used only in this module                                 */
static void CAN_hw_rd          (U32 ctrl, CAN_msg *msg);
#if (USE_CAN_CTRL1 == 1) || (USE_CAN_CTRL2 == 1)
  static void CAN_ISR          (void) __irq;
#endif


/************************* Auxiliary Functions *******************************/

/*------------------------ CAN_hw_set_baudrate ------------------------------
 *
 *  Setup the requested baudrate
 *
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x)
 *              baudrate:   Baudrate
 *
 *  Return:     CAN_ERROR:  Error code
 *---------------------------------------------------------------------------*/

static CAN_ERROR CAN_hw_set_baudrate (U32 ctrl, U32 baudrate)  {
  U32 ctrl0 = ctrl-1;                 /* Controller index 0 .. x-1           */
  regCAN    *ptrcan    = (regCAN *) CAN_BASE[ctrl0];
  U32 result = 0;
  U32 nominal_time;

  /* Determine which nominal time to use for PCLK and baudrate               */
  if (baudrate <= 500000)  {
    nominal_time = 12;
  }  else if (((PCLK / 1000000) % 15) == 0)  {
    nominal_time = 15;
  }  else if (((PCLK / 1000000) % 16) == 0)  {
    nominal_time = 16;
  }  else  {
    nominal_time = 10;
  }

  /* Prepare value appropriate for bit time register                         */
  result  = (PCLK / nominal_time) / baudrate - 1;
  result &= 0x000003FF;
  result |= CAN_BIT_TIME[nominal_time];

  ptrcan->CANBTR  = result;                      /* Set bit timing           */

  return CAN_OK;
}


/*************************** Module Functions ********************************/

/*--------------------------- CAN_hw_setup ----------------------------------
 *
 *  Setup CAN transmit and receive PINs and interrupt vectors
 *
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x)
 *
 *  Return:     CAN_ERROR:  Error code
 *---------------------------------------------------------------------------*/

CAN_ERROR CAN_hw_setup (U32 ctrl)  {
  switch (ctrl) {
    case 1: 
      #if USE_CAN_CTRL1 == 1
        PCONP   |= 1 << 13;           /* Enable clock for CAN1               */
        PINSEL0 &= 0xFFFFFFF0;        /* Reset CAN1 bits                     */
        PINSEL0 |= 0x00000005;        /* Set CAN1 bits to b0101              */
    
        /* Set interrupt vector for CAN1                                     */
        *(&VICVectAddr23) = (unsigned long) CAN_ISR;
        *(&VICVectCntl23) = 1;
    
        VICIntEnable = (1 << 23);     /* Enable CAN1 Interrupt               */
      #endif
      break;
    case 2: 
      #if USE_CAN_CTRL2 == 1
        PCONP   |= 1 << 14;           /* Enable clock for CAN2               */
        PINSEL0 &= 0xFFFFF0FF;        /* Reset CAN2 bits                     */
        PINSEL0 |= 0x00000A00;        /* Set CAN2 bits to b1010              */
    
        /* Set interrupt vector for CAN2                                     */
        *(&VICVectAddr23) = (unsigned long) CAN_ISR;
        *(&VICVectCntl23) = 1;
    
        VICIntEnable = (1 << 23);     /* Enable CAN2 Interrupt               */
      #endif
      break;
    default:
      return CAN_UNEXIST_CTRL_ERROR;
  }

  return CAN_OK;
}

/*--------------------------- CAN_hw_init -----------------------------------
 *
 *  Initialize the CAN hardware
 *
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x)
 *              baudrate:   Baudrate
 *
 *  Return:     CAN_ERROR:  Error code
 *---------------------------------------------------------------------------*/

CAN_ERROR CAN_hw_init (U32 ctrl, U32 baudrate)  {
  U32 ctrl0 = ctrl-1;                 /* Controller index 0 .. x-1           */
  regCAN_AF *ptrcan_af = (regCAN_AF *) CAN_AF_BASE;
  regCAN    *ptrcan    = (regCAN *) CAN_BASE[ctrl0];

  ptrcan_af->AFMR = 2;                /* By default filter is not used       */
  ptrcan->CANMOD  = 1;                /* Enter reset mode                    */
  ptrcan->CANIER  = 0;                /* Disable all interrupts              */
  ptrcan->CANGSR  = 0;                /* Clear status register               */
  CAN_hw_set_baudrate(ctrl, baudrate);/* Set bit timing                      */
  ptrcan->CANIER  = 0x0003;           /* Enable Tx and Rx interrupt          */
      
  return CAN_OK;
}


/*--------------------------- CAN_hw_start ----------------------------------
 *
 *  Enable the CAN interrupts (recive or/and transmit)
 *
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x)
 *
 *  Return:     CAN_ERROR:  Error code
 *---------------------------------------------------------------------------*/

CAN_ERROR CAN_hw_start (U32 ctrl)  {
  U32 ctrl0 = ctrl-1;                 /* Controller index 0 .. x-1           */
  regCAN *ptrcan = (regCAN *) CAN_BASE[ctrl0];

  ptrcan->CANMOD = 0;                 /* Enter normal operating mode         */

  return CAN_OK;
}


/*--------------------------- CAN_hw_tx_empty -------------------------------
 *
 *  Check if controller is available for transmission
 *
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x)
 *
 *  Return:     CAN_ERROR:  Error code
 *---------------------------------------------------------------------------*/

CAN_ERROR CAN_hw_tx_empty (U32 ctrl)  {
  U32 ctrl0 = ctrl-1;                 /* Controller index 0 .. x-1           */
  regCAN *ptrcan = (regCAN *) CAN_BASE[ctrl0];

  if ((os_sem_wait (wr_sem[ctrl-1], 0) != OS_R_TMO)){ /* If semaphore is free*/
    if (ptrcan->CANSR & 0x00000004)               /* Transmitter ready for   */
                                                  /* transmission            */
      return CAN_OK;
    else 
      os_sem_send(wr_sem[ctrl-1]);    /* Return a token back to semaphore    */
  }

  return CAN_TX_BUSY_ERROR;
}


/*--------------------------- CAN_hw_wr -------------------------------------
 *
 *  Write CAN_msg to the hardware registers of the requested controller
 *
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x)
 *              msg:        Pointer to CAN message to be written to hardware
 *
 *  Return:     CAN_ERROR:  Error code
 *---------------------------------------------------------------------------*/

CAN_ERROR CAN_hw_wr (U32 ctrl, CAN_msg *msg)  {
  U32 ctrl0 = ctrl-1;                 /* Controller index 0 .. x-1           */
  U32 CANData;
  regCAN *ptrcan = (regCAN *) CAN_BASE[ctrl0];

  CANData       = (((U32) msg->len) << 16)          & 0x000F0000 | 
                  (msg->format == EXTENDED_FORMAT ) * 0x80000000 |
                  (msg->type   == REMOTE_FRAME)     * 0x40000000;

  if (ptrcan->CANSR & 0x00000004)  {  /* Transmit buffer 1 free              */
    ptrcan->CANTF1  = CANData;        /* Write frame informations            */
    ptrcan->CANTID1 = msg->id;        /* Write CAN message identifier        */
    ptrcan->CANTDA1 = *(U32 *) &msg->data[0]; /* Write first 4 data bytes    */
    ptrcan->CANTDB1 = *(U32 *) &msg->data[4]; /* Write second 4 data bytes   */
    //ptrcan->CANCMR  = 0x31;           /* Select Tx1 for Self Tx/Rx           */
    ptrcan->CANCMR  = 0x21;           /* Start transmission without loop-back*/
  }
  else
    return CAN_TX_BUSY_ERROR;

  return CAN_OK;
}


/*--------------------------- CAN_hw_rd -------------------------------------
 *
 *  Read CAN_msg from the hardware registers of the requested controller
 *
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x)
 *              msg:        Pointer where CAN message will be read
 *
 *  Return:     CAN_ERROR:  Error code
 *---------------------------------------------------------------------------*/

static void CAN_hw_rd (U32 ctrl, CAN_msg *msg)  {
  U32 ctrl0 = ctrl-1;                 /* Controller index 0 .. x-1           */
  U32 CANData;
  U32 *CANAddr;
  regCAN *ptrcan = (regCAN *) CAN_BASE[ctrl0];

  /* Read frame informations                                                 */
  CANData = ptrcan->CANRFS;
  msg->format   = (CANData & 0x80000000) == 0x80000000;
  msg->type     = (CANData & 0x40000000) == 0x40000000;

⌨️ 快捷键说明

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