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

📄 mco.c

📁 The following Philips LPC2k CAN examples in this directory were provided by ESAcademy. LPC2_CANA
💻 C
📖 第 1 页 / 共 2 页
字号:
  gMCOConfig.Node_ID = Node_ID;
  gMCOConfig.error_code = 0;
  gMCOConfig.Baudrate = Baudrate;
  gMCOConfig.heartbeat_time = Heartbeat;
  gMCOConfig.heartbeat_msg.ID = 0x700+Node_ID;
  gMCOConfig.heartbeat_msg.LEN = 1;
  gMCOConfig.heartbeat_msg.BUF[0] = 0; // Current NMT state of this node = bootup
  gMCOConfig.error_register = 0;
 
  // Init SDO Response/Abort message
  gTxSDO.ID = 0x580+gMCOConfig.Node_ID;
  gTxSDO.LEN = 8;
   
#if NR_OF_TPDOS > 0
  i = 0;
  while (i < NR_OF_TPDOS)
  { // Init TPDOs
     gTPDOConfig[i].CAN.ID = 0;
     i++;
  }
#endif
#if NR_OF_RPDOS > 0
  i = 0;
  while (i < NR_OF_RPDOS)
  { // Init RPDOs
     gRPDOConfig[i].CANID = 0;
     i++;
  }
#endif

  // Init the CAN interface
  if (!MCOHW_Init(Baudrate))
  {
    MCOUSER_FatalError(0x8802);
  }
  if (!MCOHW_SetCANFilter(0)) // For NMT master message 
  {
    MCOUSER_FatalError(0x8803);
  }
  if (!MCOHW_SetCANFilter(0x600+Node_ID)) // For SDO Requests
  {
    MCOUSER_FatalError(0x8803);
  }

  // Signal to MCO_ProcessStack: we just initialized
  gTPDONr = 0xFF;
}  

#if NR_OF_RPDOS > 0
/**************************************************************************
DOES: This function initializes a receive PDO. Once initialized, the 
      MicroCANopen stack automatically updates the data at offset.
NOTE: For data consistency, the application should not read the data
      while function MCO_ProcessStack executes.
**************************************************************************/
void MCO_InitRPDO
  (
  BYTE PDO_NR,       // RPDO number (1-4)
  WORD CAN_ID,       // CAN identifier to be used (set to 0 to use default)
  BYTE len,          // Number of data bytes in RPDO
  BYTE offset        // Offset to data location in process image
  )
{

#ifdef CHECK_PARAMETERS
  if ( ((PDO_NR < 1) || (PDO_NR > NR_OF_RPDOS)) ||  // Check PDO range 
       ((gMCOConfig.Node_ID < 1) || (gMCOConfig.Node_ID > 127)) )   
                                                    // Check Node ID range 1-127
  {
    MCOUSER_FatalError(0x8804);
  }
  if (offset >= PROCIMG_SIZE)   
  { // Size of process image exceeded 
    MCOUSER_FatalError(0x8904);
  }
#endif
  PDO_NR--;
  gRPDOConfig[PDO_NR].len = len;
  gRPDOConfig[PDO_NR].offset = offset;
  if (CAN_ID == 0)
  {
    gRPDOConfig[PDO_NR].CANID = 0x200 + (0x100 * ((WORD)(PDO_NR))) + gMCOConfig.Node_ID;
  }
  else
  {
    gRPDOConfig[PDO_NR].CANID = CAN_ID;
  }
  if (!MCOHW_SetCANFilter(gRPDOConfig[PDO_NR].CANID))
  {
    MCOUSER_FatalError(0x8805);
  }
}
#endif // NR_OF_RPDOS > 0


#if NR_OF_TPDOS > 0
/**************************************************************************
DOES: This function initializes a transmit PDO. Once initialized, the 
      MicroCANopen stack automatically handles transmitting the PDO.
      The application can directly change the data at any time.
NOTE: For data consistency, the application should not write to the data
      while function MCO_ProcessStack executes.
**************************************************************************/
void MCO_InitTPDO
  (
  BYTE PDO_NR,        // TPDO number (1-4)
  WORD CAN_ID,        // CAN identifier to be used (set to 0 to use default)
  WORD event_time,    // Transmitted every event_tim ms 
  WORD inhibit_time,  // Inhibit time in ms for change-of-state transmit
                      // (set to 0 if ONLY event_tim should be used)
  BYTE len,           // Number of data bytes in TPDO
  BYTE offset         // Offset to data location in process image
  )
{

#ifdef CHECK_PARAMETERS
  if ( ((PDO_NR < 1) || (PDO_NR > NR_OF_TPDOS)) ||   // Check PDO range
       ((gMCOConfig.Node_ID < 1) || (gMCOConfig.Node_ID > 127)) || // Check Node ID
       ((len < 1) || (len > 8)) ||                   // Check len range 1-8
       ((event_time == 0) && (inhibit_time == 0)) )  // One of these needs to be set
  {
    MCOUSER_FatalError(0x8806);
  }
  if (offset >= PROCIMG_SIZE)   
  { // Size of process image exceeded 
    MCOUSER_FatalError(0x8906);
  }
#endif
  PDO_NR--;
  if (CAN_ID == 0)
  {
    gTPDOConfig[PDO_NR].CAN.ID = 0x180 + (0x100 * ((WORD)(PDO_NR))) + gMCOConfig.Node_ID;
  }
  else
  {
    gTPDOConfig[PDO_NR].CAN.ID = CAN_ID;
  }
  gTPDOConfig[PDO_NR].CAN.LEN = len;
  gTPDOConfig[PDO_NR].offset = offset;
  gTPDOConfig[PDO_NR].event_time = event_time;
}
#endif // NR_OF_TPDOS > 0


/**************************************************************************
DOES: This function implements the main MicroCANopen protocol stack. 
      It must be called frequently to ensure proper operation of the
      communication stack. 
      Typically it is called from the while(1) loop in main.
**************************************************************************/
BYTE MCO_ProcessStack
  ( // Returns 0 if nothing was done
    // Returns 1 if a CAN message was received or sent
  void
  )
{
BYTE i;
BYTE x;
BYTE ret_val = 0;

  // Check if this is right after boot-up
  if (gTPDONr == 0xFF) // Was set by MCO_Init
  {
    // Init heartbeat time
    gMCOConfig.heartbeat_timestamp = MCOHW_GetTime() + gMCOConfig.heartbeat_time;
    // Send Boot-up message  
    if (!MCOHW_PushMessage(&gMCOConfig.heartbeat_msg))
    {
      MCOUSER_FatalError(0x8801);
    }
    gMCOConfig.heartbeat_msg.BUF[0] = 0x05; // going into operational state
#if NR_OF_TPDOS > 0
    MCO_Prepare_TPDOs();
#endif
    gTPDONr = NR_OF_TPDOS; // Retun value to default
    return 1;
  }
 
  // Work on next incoming messages
  if (MCOHW_PullMessage(&gRxCAN))
  { // Message received

gRxCAN.ID++;
MCOHW_PushMessage(&gRxCAN);
gRxCAN.ID--;
  
    // Check if it is NMT master message
    if (gRxCAN.ID == 0)
    { // NMT Master Message
      if ((gRxCAN.BUF[1] == gMCOConfig.Node_ID) || (gRxCAN.BUF[1] == 0))
      { // NMT message is for this node or all nodes
        switch (gRxCAN.BUF[0])
        {
        case 1: // Start node
          gMCOConfig.heartbeat_msg.BUF[0] = 5;
#if NR_OF_TPDOS > 0          
          MCO_Prepare_TPDOs();
#endif
          break;
        case 2: // Stop node
          gMCOConfig.heartbeat_msg.BUF[0] = 4;
          break;
        case 128:
          gMCOConfig.heartbeat_msg.BUF[0] = 127;
          break;
        case 129:
          // Node Reset
          MCOUSER_ResetApplication();
          break;
        case 130:
          // Reset Communication
          MCOUSER_ResetCommunication();
          break;
        default:
          break;
        } // switch
        return 1;
      } // NMT message addressed to this node
    } // NMT master message received
    
    // Check if it is SDO request message
    if (gMCOConfig.heartbeat_msg.BUF[0] != 4)
    { // Node is NOT stopped
      if (gRxCAN.ID == gMCOConfig.Node_ID+0x600)
      { // SDO Request
        i = MCO_Handle_SDO_Request(&gRxCAN.BUF[0]); // Return value not used in this version
        return 1;
      }
    }

#if NR_OF_RPDOS > 0
    // Check if it is RPDO message
    if (gMCOConfig.heartbeat_msg.BUF[0] == 5)
    { // Node is in operational
      i = 0;
      while (i < NR_OF_RPDOS)
      {
        if (gRxCAN.ID == gRPDOConfig[i].CANID)
        { // RPDO match
          for (x=0;x<gRPDOConfig[i].len;x++) 
          {
            gProcImg[gRPDOConfig[i].offset+x] = gRxCAN.BUF[x];
          }
          i = NR_OF_RPDOS;
          ret_val = 1;
        }
        i++;
      } // for all RPDOs
    } // Node is operational
#endif // NR_OF_RPDOS > 0
  } // Message received

#if NR_OF_TPDOS > 0
  // Check Next TPDO for transmit
  if (gMCOConfig.heartbeat_msg.BUF[0] == 0x05)
  { // Node is in operational
    gTPDONr++;
    if (gTPDONr >= NR_OF_TPDOS)
    {
      gTPDONr = 0;
    }
    if (gTPDOConfig[gTPDONr].CAN.ID != 0)
    { // TPDO 'gTPDONr' is used
      if ((gTPDOConfig[gTPDONr].event_time != 0) && 
          (MCOHW_IsTimeExpired(gTPDOConfig[gTPDONr].event_timestamp)) )
      { // TPDO 'i' uses event timer and event timer is expired
        // Get application data
        for (x=0;x<gTPDOConfig[gTPDONr].CAN.LEN;x++) 
        {
          gTPDOConfig[gTPDONr].CAN.BUF[x] = gProcImg[gTPDOConfig[gTPDONr].offset+x];
        }
        MCO_TransmitPDO(gTPDONr);
        return 1;
      }
    } // PDO active (CAN_ID != 0)  
  } // if node is operational
#endif // NR_OF_TPDOS > 0
  
  // Produce Heartbeat
  if (gMCOConfig.heartbeat_time != 0)
  {
    if (MCOHW_IsTimeExpired(gMCOConfig.heartbeat_timestamp))
    {
      if (!MCOHW_PushMessage(&gMCOConfig.heartbeat_msg))
      {
        MCOUSER_FatalError(0x8801);
      }
      gMCOConfig.heartbeat_timestamp = MCOHW_GetTime() + gMCOConfig.heartbeat_time;
      ret_val = 1;
    }
  }
  return ret_val;
}

⌨️ 快捷键说明

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