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

📄 can_hw.c

📁 can bus 源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*----------------------------------------------------------------------------
 *      A R T X  -  C A N   D r i v e r  -  H a r d w a r e   L a y e r
 *----------------------------------------------------------------------------
 *      Name:    CAN_Hw.c
 *      Purpose: CAN Driver, Hardware specific module for LPC2xxx
 *      Rev.:    V0.20 / october-14-2005
 *----------------------------------------------------------------------------
 *      This code is part of the ARTX-ARM kernel package of Keil Software.
 *      Copyright (c) 2004-2005 Keil Software. All rights reserved.
 *---------------------------------------------------------------------------*/

#include <ARTX.h>                     /* ARTX kernel functions & defines     */
#include <LPC21xx.h>                  /* LPC21xx definitions                 */
#include "ARTX_CAN.h"                 /* CAN Generic functions & defines     */
#include "CAN_hw.h"                   /* CAN hw specific functions & defines */
#include "CAN_reg.h"                  /* LPC2xxx CAN registers               */




/* 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% */
                           };

unsigned char		PutString(unsigned char *p);


//#define AFMR           (*((volatile unsigned long *) 0xE003C000))

extern	unsigned short	Can2RxOK;
/*----------------------------------------------------------------------------
 *      CAN ARTX Hardware Specific Driver Functions for LPC2xxx
 *----------------------------------------------------------------------------
 *  Functions implemented in this module:
 *           CAN_ERROR CAN_hw_setup      (void)
 *    static       U32 CAN_calc_baudrate (U32 baudrate)
 *           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  U32 CAN_calc_baudrate (U32 baudrate);
static void CAN_hw_rd         (U32 ctrl, CAN_msg *msg);
static void CAN_TX1_ISR       (void) __irq;
static void CAN_RX1_ISR       (void) __irq;
static void CAN_TX2_ISR       (void) __irq;
static void CAN_RX2_ISR       (void) __irq;
static void CAN_TX3_ISR       (void) __irq;
static void CAN_RX3_ISR       (void) __irq;
static void CAN_TX4_ISR       (void) __irq;
static void CAN_RX4_ISR       (void) __irq;


/*--------------------------- CAN_hw_setup ----------------------------------
 *
 *  Setup CAN transmit and receive PINs and interrupt vectors
 *
 *  Parameter:  none
 *
 *  Return:     CAN_ERROR:  Error code
 *---------------------------------------------------------------------------*/

CAN_ERROR CAN_hw_setup (void)  {
  #if USE_CAN_CTRL1 == 1
    PINSEL1 &= 0xFFEBFFFF;            /* Reset CAN1 bits                     */
    PINSEL1 |= 0x00040000;            /* Set CAN1 bits to 01                 */

    /* Set interrupt vector for Tx1                                          */
    *(&VICVectAddr0 + VIC_NUM_CTRL1_TX) = (unsigned long) CAN_TX1_ISR;
    *(&VICVectCntl0 + VIC_NUM_CTRL1_TX) = 0x20 | 20;
    /* Set interrupt vector for Rx1                                          */
    *(&VICVectAddr0 + VIC_NUM_CTRL1_RX) = (unsigned long) CAN_RX1_ISR;       
    *(&VICVectCntl0 + VIC_NUM_CTRL1_RX) = 0x20 | 26;

    VICIntEnable |= 0x04100000;        /* Enable CAN Tx1 and Rx1 Interrupt    */
  #endif
  #if USE_CAN_CTRL2 == 1
    PINSEL1 &= 0xFFFC3FFF;            /* Reset CAN2 bits                     */
    PINSEL1 |= 0x00014000;            /* Set CAN2 bits to 11                 */

    /* Set interrupt vector for Tx2                                          */
    *(&VICVectAddr0 + VIC_NUM_CTRL2_TX) = (unsigned long) CAN_TX2_ISR;
    *(&VICVectCntl0 + VIC_NUM_CTRL2_TX) = 0x20 | 21;
    /* Set interrupt vector for Rx2                                          */
    *(&VICVectAddr0 + VIC_NUM_CTRL2_RX) = (unsigned long) CAN_RX2_ISR;
    *(&VICVectCntl0 + VIC_NUM_CTRL2_RX) = 0x20 | 27;

    VICIntEnable |= 0x08200000;        /* Enable CAN Tx2 and Rx2 Interrupt    */
  #endif
  #if USE_CAN_CTRL3 == 1
    PINSEL1 &= 0xFFFFC3FF;            /* Reset CAN3 bits                     */
    PINSEL1 |= 0x00001800;            /* Set CAN3 bits to 11                 */

    /* Set interrupt vector for Tx3                                          */
    *(&VICVectAddr0 + VIC_NUM_CTRL3_TX) = (unsigned long) CAN_TX3_ISR;
    *(&VICVectCntl0 + VIC_NUM_CTRL3_TX) = 0x20 | 22;
    /* Set interrupt vector for Rx3                                          */
    *(&VICVectAddr0 + VIC_NUM_CTRL3_RX) = (unsigned long) CAN_RX3_ISR;
    *(&VICVectCntl0 + VIC_NUM_CTRL3_RX) = 0x20 | 28;

    VICIntEnable = 0x10400000;        /* Enable CAN Tx3 and Rx3 Interrupt    */
  #endif
  #if USE_CAN_CTRL4 == 1
    PINSEL0 &= 0xF0FFFFFF;            /* Reset CAN4 bits                     */
    PINSEL0 |= 0x0F000000;            /* Set CAN4 bits to 1111               */

    /* Set interrupt vector for Tx4                                          */
    *(&VICVectAddr0 + VIC_NUM_CTRL4_TX) = (unsigned long) CAN_TX4_ISR;
    *(&VICVectCntl0 + VIC_NUM_CTRL4_TX) = 0x20 | 23;
    /* Set interrupt vector for Rx4                                          */
    *(&VICVectAddr0 + VIC_NUM_CTRL4_RX) = (unsigned long) CAN_RX4_ISR;
    *(&VICVectCntl0 + VIC_NUM_CTRL4_RX) = 0x20 | 29;

    VICIntEnable = 0x20800000;        /* Enable CAN Tx4 and Rx4 Interrupt    */
  #endif

  return CAN_OK;
}


/*--------------------------- CAN_calc_baudrate -----------------------------
 *
 *  Calculate baudrate register value for requested baudrate
 *
 *  Parameter:  baudrate:   Baudrate
 *
 *  Return:     U32:        Bitrate register value
 *---------------------------------------------------------------------------*/

static U32 CAN_calc_baudrate (U32 baudrate)  {
  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];

  return result;
}


/*--------------------------- CAN_hw_init -----------------------------------
 *
 *  Initialize the CAN hardware
 *
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x)
 *              baudrate:   Baudrate
 *
 *  Return:     CAN_ERROR:  Error code
 *---------------------------------------------------------------------------*/
 
#define AFMReg           (*((volatile unsigned long *) 0xE003C000)) 

CAN_ERROR CAN_hw_init (U32 ctrl, U32 baudrate)  
{
  #if(CAN_REG_USE_POINT)
  U32 ctrl0 = ctrl-1;                 /* Controller index 0 .. x-1           */
  regCAN_AF *ptrcan_af = CAN_AF_BASE;
  regCAN    *ptrcan    = (regCAN *) CAN_BASE[ctrl0];  
  ptrcan_af->AFMR = 1;                /* Disable acceptance filter           */
  ptrcan->CANMOD  = 1;                /* Enter reset mode                    */
  ptrcan->CANMOD  = 1;
  ptrcan->CANMOD  = 1;
  os_dly_wait(1);
  
  
  
  ptrcan->CANIER  = 0;                /* Disable all interrupts              */
  ptrcan->CANGSR  = 0;                /* Clear status register               */
  ptrcan->CANBTR  = CAN_calc_baudrate(baudrate); /* Set bit timing           */
  ptrcan->CANIER  = 0xffffff;//0x0603;           /* Enable Tx and Rx interrupt          */
  #else
  if(ctrl == 1)
  {  		
  		C1MOD  = 1;
  		C1EWL = 0x60;
  		C2IER	 = 0;
  		C1GSR  = 0;
  		C1BTR  = CAN_calc_baudrate(baudrate);
  		AFMReg = 0x00000002L;
  		C1IER	 = 0x0603;
  		
	}
	else if(ctrl ==2)
	{
		
  		C2MOD  = 1;
  		C2EWL = 0x60;
  		C2IER	 = 0;
  		C2GSR  = 0;
  		C2BTR  = CAN_calc_baudrate(baudrate);  		
  		C2IER	 = 0x0603;  		
	}
  #endif 
  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)  
{
	#if(CAN_REG_USE_POINT)
  U32 ctrl0 = ctrl-1;             s    /* Controller index 0 .. x-1           */
  regCAN *ptrcan = (regCAN *) CAN_BASE[ctrl0];

  ptrcan->CANMOD = 0x06;                 /* Enter normal operating mode         */
  
  #else
  
  
  #if(CAN_TEST_STATUS_TO_UART0)
  GetCanRegValue();
  #endif
  
  if(ctrl == 1)
  	C1MOD = 0x86;
  else if(ctrl == 2)
  	C2MOD = 0x86;
  
  #endif
  
  

  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 (!(ptrcan->CANSR & 0x00000004))  /* Transmitter 1 busy                  */
    return CAN_TX_BUSY_ERROR;

  return CAN_OK;
}


/*--------------------------- 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              */
  {
  	
  	#if(CAN_TEST_STATUS_TO_UART0)
  	PutString("Can Transmit buffer 1 free!\r\n\0");
  	#endif
  	
    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  = 0x30;           /* Start self-transmission             */
  }
  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;
  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:       Ignorred
 *              msg:        Pointer to CAN message to be set
 *
 *  Return:     CAN_ERROR:  Error code
 *---------------------------------------------------------------------------*/

CAN_ERROR CAN_hw_set (U32 ctrl, CAN_msg *msg)  {
  ctrl = ctrl;                        /* To avoid compiler warning           */
  msg  = msg;                         /* "unreferenced parameter"            */

  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:         Ignorred 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)  {
  static S16 CAN_std_cnt = 0;
  static S16 CAN_ext_cnt = 0;
  regCAN_AF    *ptrcan_af    = CAN_AF_BASE;
  regCAN_AFRAM *ptrcan_afram = CAN_AFRAM_BASE;
  U32 buf0, buf1;
  S16 cnt1, cnt2, bound1;

⌨️ 快捷键说明

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