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

📄 mco.c

📁 Philips LPC2000 CAN驱动程序(包括3个示例)
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************
MODULE:    MCO
CONTAINS:  Minimal MicroCANopen implementation
COPYRIGHT: Embedded Systems Academy, Inc. 2002-2004.
           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 VERSION CREATED FOR FREE DISTRIBUTION
           FOR KEIL SOFTWARE www.keil.com
		       FOR PHILIPS SEMICONDUCTORS www.philipsmcu.com
VERSION:   1.21, Pf 02-FEB-04
---------------------------------------------------------------------------
HISTORY:   1.21, Pf 02-FEB-04, Release for Philips LPC2129
           1.20, Pf 19-AUG-03, Code changed to use process image
                 Bug fix for incorrect inhibit time handling
           1.10, Pf 27-MAY-03, Bug fixes in OD (hi byte was corrupted)
                 OD changed to indefinite length
				 Support of define controled MEMORY types
           1.01, Pf 17-DEC-02, Made Object Dictionary more readable
           1.00, Pf 07-OCT-02, First Published Version
***************************************************************************/ 

#include "mco.h"
#include "mcohw.h"
#include <string.h>


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

// This structure holds all node specific configuration
MCO_CONFIG MEM_FAR gMCOConfig;

#if NR_OF_TPDOS > 0
// This structure holds all the TPDO configuration data for up to 4 TPDOs
TPDO_CONFIG MEM_FAR gTPDOConfig[NR_OF_TPDOS];

// This is the next TPDO to be checked in MCO_ProcessStack
BYTE MEM_FAR gTPDONr = NR_OF_TPDOS;
#endif

#if NR_OF_RPDOS > 0
// This structure holds all the RPDO configuration data for up to 4 RPDOs
RPDO_CONFIG MEM_FAR gRPDOConfig[NR_OF_RPDOS];
#endif

// This structure holds the current receive message
CAN_MSG MEM_FAR gRxCAN;

// This structure holds the CAN message for SDO responses or aborts
CAN_MSG MEM_FAR gTxSDO;

// Process image from user_xxxx.c
extern BYTE MEM_NEAR gProcImg[];

// Table with SDO Responses for read requests to OD - defined in user_xxx.c
extern BYTE MEM_CONST SDOResponseTable[];

// 1ms timer
extern WORD gTimCnt;

/**************************************************************************
LOCAL FUNCTIONS
***************************************************************************/ 

// SDO Abort Messages
#define SDO_ABORT_UNSUPPORTED  0x06010000UL
#define SDO_ABORT_NOT_EXISTS   0x06020000UL
#define SDO_ABORT_READONLY     0x06010002UL
#define SDO_ABORT_TYPEMISMATCH 0x06070010UL


/**************************************************************************
DOES:    Search the SDO Response table for a specifc index and subindex.
RETURNS: 255 if not found, otherwise the number of the record found
         (staring at zero)
**************************************************************************/
BYTE MCO_Search_OD (
  WORD index,   // Index of OD entry searched
  BYTE subindex // Subindex of OD entry searched 
  )
{
BYTE i;
BYTE i_hi, hi;
BYTE i_lo, lo;
BYTE *p;
BYTE *r;

  i = 0;
  i_hi = (BYTE) (index >> 8);
  i_lo = (BYTE) index;
  r = (BYTE *) &(SDOResponseTable[0]);
  while (i < 255)
  {
    p = r;
    r += 8; // Set r to next record in table
    p++; // Skip command byte
	lo = *p;
	p++;
	hi = *p;
    if ((lo == 0xFF) && (hi == 0xFF))
    { // if index in table is 0xFFFF, this is end of table
	  return 255;
	}
    if (lo == i_lo)
    { 
      if (hi == i_hi)
      { 
        p++;
        if (*p == subindex)
        { // Entry found
          return i;
        }
      }
    }
    i++;
  } // while search loop
  return 255;
}


/**************************************************************************
DOES: Generates an SDO Abort Response
**************************************************************************/
void MCO_Send_SDO_Abort
  (
  DWORD ErrorCode   // 4 byte SDO abort error code
  )
{
BYTE i;

  gTxSDO.BUF[0] = 0x80;
  for (i=0;i<4;i++)
  {
    gTxSDO.BUF[4+i] = ErrorCode;
    ErrorCode >>= 8;
  }
  
  if (!MCOHW_PushMessage(&gTxSDO))
  {
    MCOUSER_FatalError(0x8801);
  }
}


/**************************************************************************
DOES: Handle an incoimg SDO request.
**************************************************************************/
BYTE MCO_Handle_SDO_Request 
  (               // Returns 1 if SDO Access success
                  // Returns 0 if SDO Abort generated
  BYTE *pData     // Pointer to 8 data bytes with SDO data
  )
{
BYTE cmd;         // Command byte of SDO request
WORD index;       // Index of SDO request
BYTE subindex;    // Subindex of SDO request
BYTE found;       // Search result of Search_OD
unsigned int *src, *dst; // Source and destination pointer for copying
#ifdef PROCIMG_IN_OD
BYTE len;
OD_PROCESS_DATA_ENTRY MEM_CONST *pOD; // Pointer to an entry in gODProcTable
#endif 

  // Init variables
  cmd = *pData & 0xE0; // Upper 3-bits are the command
  index = pData[2]; // Get hi byte of index
  index = (index << 8) + pData[1]; // Add lo byte of index
  subindex = pData[3];

  // Copy Multiplexor into response
  gTxSDO.BUF[1] = pData[1]; // index lo
  gTxSDO.BUF[2] = pData[2]; // index hi
  gTxSDO.BUF[3] = pData[3]; // subindex

  if ((cmd == 0x40) || (cmd == 0x20)) 
  { // It is a read or write command

    // Search const table 
    found = MCO_Search_OD(index,subindex);
    if (found < 255)
    { // OD entry found
      if (cmd == 0x40)
      { // Read command
        // Copy from response table to TxSDO buffer
        dst = (unsigned int *) &(gTxSDO.BUF[0]);
        src = (unsigned int *) &(SDOResponseTable[(found*8)]);
        *dst = *src;
        dst++;
        src++;
        *dst = *src;

        if (!MCOHW_PushMessage(&gTxSDO))
        {
          MCOUSER_FatalError(0x8802);
        }
        return 1;
      }
      // Write command
      MCO_Send_SDO_Abort(SDO_ABORT_READONLY);
      return 0;
    }
    if ((index == 0x1001) && (subindex == 0x00))
    {
      if (cmd == 0x40)
      { // Read command
        gTxSDO.BUF[0] = 0x4F; // Expedited, 1-byte of data
        gTxSDO.BUF[4] = gMCOConfig.error_register;
        if (!MCOHW_PushMessage(&gTxSDO))
        {
          MCOUSER_FatalError(0x8802);
        }
        return 1;
      }
      // Write command
      MCO_Send_SDO_Abort(SDO_ABORT_READONLY);
      return 0;
    }
    MCO_Send_SDO_Abort(SDO_ABORT_NOT_EXISTS);
    return 0;
  }
  if (cmd != 0x80)
  { // Ignore "abort received" - all others produce error
    MCO_Send_SDO_Abort(SDO_ABORT_UNSUPPORTED);
    return 0;
  }
  return 1;
}


#if NR_OF_TPDOS > 0
/**************************************************************************
DOES: Called when going into the operational mode.
      Prepares all TPDOs for operational.
**************************************************************************/
void MCO_Prepare_TPDOs 
  (
    void
  )
{
BYTE i;
BYTE x;

  i = 0;
  while (i < NR_OF_TPDOS)
  { // Prepare all TPDOs for transmission
    if (gTPDOConfig[i].CAN.ID != 0)
    { // This TPDO is used
      // Copy current process data
      for (x=0;x<gTPDOConfig[i].CAN.LEN;x++) 
      {
        gTPDOConfig[i].CAN.BUF[x] = gProcImg[gTPDOConfig[i].offset+x];
      }
      // Reset event timer for immediate transmission
      gTPDOConfig[i].event_timestamp = MCOHW_GetTime() - 2;
    }
  i++;
  }
  gTPDONr = NR_OF_TPDOS; // Ensure that MCO_ProcessStack starts with TPDO1
}


/**************************************************************************
DOES: Called when a TPDO needs to be transmitted
**************************************************************************/
void MCO_TransmitPDO 
  (
  BYTE PDONr
  )
{
  gTPDOConfig[PDONr].event_timestamp = MCOHW_GetTime() + gTPDOConfig[PDONr].event_time; 
  if (!MCOHW_PushMessage(&gTPDOConfig[PDONr].CAN))
  {
    MCOUSER_FatalError(0x8801);
  }
}
#endif // NR_OF_TPDOS > 0


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

void MCO_Init 
  (
  WORD Baudrate,
  BYTE Node_ID,
  WORD Heartbeat
  )
{
BYTE i;

  // Init the global variables

⌨️ 快捷键说明

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