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

📄 mcohw_lpc2.c

📁 CanOpen的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************
MODULE:    MCOHW_LPC2
CONTAINS:  Driver implementation for NXP LPC2000 derivatives with 
           CAN interface. Compiled and Tested with Keil Tools www.keil.com
COPYRIGHT: Embedded Systems Academy, Inc. 2002-2007.
           All rights reserved. www.microcanopen.com
           This software was written in accordance to the guidelines at
           www.esacademy.com/software/softwarestyleguide.pdf
DISCLAIM:  Read and understand our disclaimer before using this code!
           www.esacademy.com/disclaim.htm
LICENSE:   THIS IS THE EDUCATIONAL VERSION OF MICROCANOPEN
           See file license_educational.txt or
           www.microcanopen.com/license_educational.txt
           A commercial MicroCANopen license is available at
           www.CANopenStore.com
VERSION:   3.30, ESA 30-JAN-07
           $LastChangedDate: 2007-01-30 10:38:13 -0800 (Tue, 30 Jan 2007) $
           $LastChangedRevision: 232 $
***************************************************************************/ 

#include "mcohw.h"
#include <string.h>
#include <LPC21XX.H> // LPC21XX Peripheral Registers


#define NROF_CANPORTS 1
#define FIRST_CANPORT 1


// Define CAN SFR address bases 
#define CAN_REG_BASE                    (0xE0000000)
#define ACCEPTANCE_FILTER_RAM_BASE      (CAN_REG_BASE + 0x00038000)
#define ACCEPTANCE_FILTER_REGISTER_BASE (CAN_REG_BASE + 0x0003C000)
#define CENTRAL_CAN_REGISTER_BASE       (CAN_REG_BASE + 0x00040000)              
#define CAN_1_BASE                      (CAN_REG_BASE + 0x00044000)              
#define CAN_2_BASE                      (CAN_REG_BASE + 0x00048000)              

// Common CAN bit rates
#define   CANBitrate125k_12MHz          0x001C001D
#define   CANBitrate250k_12MHz          0x001C000E

// Maximum number of FullCAN Filters
#define MAX_FILTERS 32

// Size of transmit queue, must be 8, 16, 32 or 64
#define TXQUEUESIZE 16

// Timer Interrupt
void MCOHW_TimerISR (void) __attribute__ ((interrupt));  
// CAN Interrupt
void MCOHW_CANISR_Err (void) __attribute__ ((interrupt)); 
void MCOHW_CANISR_Rx1 (void) __attribute__ ((interrupt)); 
void MCOHW_CANISR_Tx1 (void) __attribute__ ((interrupt)); 
void MCOHW_DefaultISR (void) __attribute__ ((interrupt));  


/**************************************************************************
GLOBAL VARIABLES
***************************************************************************/ 

// Global timer/conter variable, incremented every millisecond
UNSIGNED16 volatile gTimCnt = 0;

#if (NROF_CANPORTS == 1)
// Only use this section for single CAN port implementations
// Timer is always handled by this module

#if (FIRST_CANPORT != 1)
  #error "FIRST_CANPORT must be 1 for this implementation!"
#endif

// Counts number of filters (CAN message objects) used
UNSIGNED16 volatile gCANFilter = 0;

// Type definition to hold a FullCAN message
typedef struct
{
  UNSIGNED32 Dat1;
  UNSIGNED32 DatA;
  UNSIGNED32 DatB;
} FULLCAN_MSGFIELD;

// FullCAN Message List
FULLCAN_MSGFIELD volatile gFullCANList[MAX_FILTERS];

// Lookup table for receive filters
UNSIGNED16 gFilterList[20];                           

// Transmit SW queue
CAN_MSG mTxQueue[TXQUEUESIZE];
UNSIGNED8 mTxIn;
UNSIGNED8 mTxOut;

// status
UNSIGNED8 mStatus = 0;

/**************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/ 

/**************************************************************************
DOES:    This function returns the global status variable.
CHANGES: The status can be changed anytime by this module, for example from 
         within an interrupt service routine or by any of the other 
         functions in this module.
BITS:    0: INIT - set to 1 after a completed initialization
                   left 0 if not yet inited or init failed
         1: CERR - set to 1 if a CAN bit or frame error occured
         2: ERPA - set to 1 if a CAN "error passive" occured
         3: RXOR - set to 1 if a receive queue overrun occured
         4: TXOR - set to 1 if a transmit queue overrun occured
         5: Reserved
         6: TXBSY - set to 1 if Transmit queue is not empty
         7: BOFF - set to 1 if a CAN "bus off" error occured
**************************************************************************/
UNSIGNED8 MCOHW_GetStatus (
  void
  )
{
UNSIGNED32 *pCSR;          // pointer into SFR space

  // Set SFR pointer
  pCSR = (UNSIGNED32 *) &C1SR + (FIRST_CANPORT-1)*0x1000;

  if ((mTxIn != mTxOut) && (!(*pCSR & 0x00000004L)))
  { // Busy transmitting
    mStatus |= HW_TXBSY;
  }
  else
  { // all Tx buffers empty
    mStatus &= ~HW_TXBSY;
  }

  return mStatus;
}


/**************************************************************************
DOES:    This function implements a CAN receive queue. With each
         function call a message is pulled from the queue.
RETURNS: 1 Message was pulled from receive queue
         0 Queue empty, no message received
**************************************************************************/
UNSIGNED8 MCOHW_PullMessage (CAN_MSG MEM_FAR *pReceiveBuf)
{
UNSIGNED16 obj;
UNSIGNED32 *pSrc; // Source Pointer
UNSIGNED32 *pDst; // Destination Pointer

  obj = 0;
  pDst = (UNSIGNED32 *) &(pReceiveBuf->BUF[0]);
  pSrc = (UNSIGNED32 *) &(gFullCANList[0].Dat1);
  
  while (obj < gCANFilter)
  {
    // if its currently updated, we come back next time and do not wait here
    // semaphore set to 11?
    if ((*pSrc & 0x03000000L) == 0x03000000L)
    { // Object Updated since last access
      *pSrc &= 0xFCFFFFFF; // clear Semaphore
      pSrc++; // Set to DatA
      *pDst = *pSrc; // Copy DatA
      pSrc++; // Set to DatB
      pDst++; // Set to DatB
      *pDst = *pSrc; // Copy DatB
      pSrc -= 2; // Back to Dat1

      pReceiveBuf->ID = (UNSIGNED16) *pSrc & 0x07FF;
      pReceiveBuf->LEN = (UNSIGNED8) (*pSrc >> 16) & 0x0F;

      // Re-read semaphore
      if ((*pSrc & 0x03000000L) == 0)
      { // Only return it, if not updated while reading
        return 1;
      }
    }
    obj ++; // Next message object buffer
    pSrc += 3; // Next record in gFullCANList array
  }
  return 0; // Return False, no msg rcvd 
}


/**************************************************************************
DOES: If there is something in the transmit queue, and if the transmit
      buffer is available, copy next message from queue to transmit buffer
***************************************************************************/ 
void MCOHW_CheckTxQueue (
  void
  )
{
UNSIGNED32 *pCSR;          // pointer into SFR space
CAN_MSG *pMsg;
UNSIGNED32 *pAddr;
UNSIGNED32 *pCandata;

  // Set SFR pointer
  pCSR = (UNSIGNED32 *) &C1SR + (FIRST_CANPORT-1)*0x1000;

  if ((*pCSR & 0x00000004L) && (mTxIn != mTxOut))
  { // Transmit Channel 1 is available and message is in queue
    
    pMsg = &(mTxQueue[(mTxOut)&(TXQUEUESIZE-1)]);

    pAddr = (UNSIGNED32 *) &C1TFI1 + (FIRST_CANPORT-1)*0x1000;

    // Write DLC
    *pAddr = ((UNSIGNED32) (pMsg->LEN)) << 16;  
  
    // Write RTR flag if needed
    /*
    if (pMsg->ID & CANID_RTR)
    {
      *pAddr |= (1 << 30);
    }
    */

    // Write CAN ID
    pAddr++;
    *pAddr = pMsg->ID & 0x000007FFL;
 
    // Write first 4 data bytes 
    pCandata = (UNSIGNED32 *) &(pMsg->BUF[0]);
    pAddr++;
    *pAddr = *pCandata;

    // Write second 4 data bytes 
    pCandata++;
    pAddr++;
    *pAddr = *pCandata;
  
    // Write transmission request
    pAddr = (UNSIGNED32 *) &C1CMR + (FIRST_CANPORT-1)*0x1000;
    *pAddr = 0x21; // Transmission Request Buf 1

    // Update Out pointer
    mTxOut++;
    mTxOut &= (TXQUEUESIZE-1);

  }
}


/**************************************************************************
DOES:    Adding a CAN message to the transmit queue
RETURNS: TRUE or FALSE if queue overrun
***************************************************************************/ 
UNSIGNED8 MCOHW_PushMessage (
  CAN_MSG *pTransmitBuf // Data structure with message to be send
  )
{
  // Copy message to transmit queue
  memcpy((UNSIGNED32 *) &(mTxQueue[mTxIn]),
          (UNSIGNED32 *) pTransmitBuf,
          sizeof(CAN_MSG));

  // Increment IN pointer (0-7)
  mTxIn++;
  mTxIn &= (TXQUEUESIZE-1);  

  // Check for overrun
  if (mTxIn == mTxOut)
  { // Overrun occured
    // Increment OUT pointer (one message lost)
    mTxOut++;
    mTxOut &= (TXQUEUESIZE-1);  

    // Signal overrun to status variable
    mStatus |= HW_TXOR;
    return FALSE;
  }

  VICSoftInt = 0x00100000;  // Trigger Tx complete interrupt

  return TRUE;
}


/**************************************************************************
DOES:    LPC2000 default interrupt handler
**************************************************************************/
void MCOHW_DefaultISR (
  void
  ) 
{
  VICVectAddr = 0xFFFFFFFF; // Acknowledge Interrupt
}
                                                        
/**************************************************************************
DOES:    CAN error interrupt handler
**************************************************************************/
void MCOHW_CANISR_Err (
  void
  )
{
  // INSERT APPLICATION SPECIFIC CODE

  mStatus |= HW_CERR;

  VICVectAddr = 0xFFFFFFFF; // Acknowledge Interrupt

⌨️ 快捷键说明

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