EtherCAT Code Assistent
|
|
|
| zurück |
Code-Assistent zur Generierung eines Framework-Codes
|
|
|
|
Um die Handhabung der EtherCAT-Masterbibliothek zu vereinfachen, hilft Ihnen der Code-Assistent bei der Generierung eines Framework-Codes
für die EtherCAT-Kommunikation auf Basis von C++. Mit dem Code-Assistenten wird ein Vorlagencode generiert, der
Header-Dateien und Codestrukturen enthält. Es sind zwei Schritte erforderlich: das Erstellen einer Header-Datei für jedes ausgewählte Gerät
und anschließend das Erstellen des Vorlagencodes. Der Code-Assistent bietet daher verschiedene Programmierstufen, vom Anfänger bis zum Experten. Die Struktur des Anwendungscodes ist somit vorgegeben und sofort einsatzbereit. Dadurch wird die Handhabung der EtherCAT-Masterbibliothek deutlich vereinfacht.
|
Erstellung der Header-Dateien
|
|
Zuerst müssen wir alle Header-Dateien aus der nativen Parameterdatei ECATDEVICExxx.par erstellen. Dazu müssen wir
jedes Gerät anhand von VendorID, ProductCode und Revision auswählen. Der Name der Header-Datei besteht aus einem erforderlichen
Präfix (DevConfig_...), dem Gerätenamen (z. B. LXM32M) und einem Zeitstempel (z. B. 2001091624).
|
|
|
Sample: DevConfig_EL7041_2001081526
|
-
//*****************************************************************
-
//*** Automated generated header ***
-
//*** Name:
[EL7041-1000] ***
-
//*** VendorID:
[0x00000002] ***
-
//*** ProductCode: [0x1b813052] ***
-
//*** Revision:
[0x001303e8] ***
-
//*****************************************************************
-
-
#pragma once
-
-
//*** Required header files ***
-
#include <windows.h>
-
#include "c:\sha\globdef64.h"
-
#include "c:\sha\Sha64Debug.h"
-
#include "c:\eth\Sha64EthCore.h"
-
#include "c:\eth\Eth64CoreDef.h"
-
#include "c:\eth\Eth64Macros.h"
-
#include "c:\ect\Sha64EcatCore.h"
-
#include "c:\ect\Ecat64CoreDef.h"
-
#include "c:\ect\Ecat64Macros.h"
-
#include "c:\ect\Ecat64Control.h"
-
#include "c:\ect\Ecat64SilentDef.h"
-
-
//*** Structures need to have 1 byte
alignment ***
-
#pragma pack(push, old_alignment)
-
#pragma pack(1)
-
-
//*** TX mapping structure [Device
Output] ***
-
typedef struct _TX_MAP_EL7041_2001081709
-
{
-
UCHAR
Data0[1];
//Item: Value
-
UCHAR
Data1[1];
//Item: Value
-
UCHAR
Data2[2];
//Item: Value, Type: Unsigned 16Bit
-
UCHAR
Data3[2];
//Item: Value, Type: Unsigned 16Bit
-
UCHAR
Data4[2];
//Item: Value
-
} TX_MAP_EL7041_2001081709,
*PTX_MAP_EL7041_2001081709;
-
-
//*** RX mapping
structure [Device Input]
***
-
typedef struct _RX_MAP_EL7041_2001081709
-
{
-
UCHAR
Data0[1];
//Item: Value
-
UCHAR
Data1[1];
//Item: Value
-
UCHAR
Data2[2];
//Item: Value, Type: Unsigned 16Bit
-
UCHAR
Data3[1];
//Item: Value
-
UCHAR
Data4[1];
//Item: Value
-
UCHAR
Data5[2];
//Item: Value, Type: Signed 16Bit
-
} RX_MAP_EL7041_2001081709,
*PRX_MAP_EL7041_2001081709;
-
-
//*** SDO download requests ***
-
__inline BOOLEAN
__SdoControl_EL7041_2001081709(PSTATION_INFO
pStation)
-
{
-
ULONG SdoData = 0;
-
-
SdoData = 0x00000000;
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadReq (pStation,
0x1c12, 0x00, 1, (PUCHAR)&SdoData))
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadResp(pStation)) {
-
-
SdoData = 0x00001600;
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadReq (pStation,
0x1c12, 0x01, 2, (PUCHAR)&SdoData))
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadResp(pStation)) {
-
-
SdoData = 0x00001602;
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadReq (pStation,
0x1c12, 0x02, 2, (PUCHAR)&SdoData))
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadResp(pStation)) {
-
-
SdoData = 0x00001604;
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadReq (pStation,
0x1c12, 0x03, 2, (PUCHAR)&SdoData))
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadResp(pStation)) {
-
-
SdoData = 0x00000003;
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadReq (pStation,
0x1c12, 0x00, 1, (PUCHAR)&SdoData))
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadResp(pStation)) {
-
-
SdoData = 0x00000000;
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadReq (pStation,
0x1c13, 0x00, 1, (PUCHAR)&SdoData))
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadResp(pStation)) {
-
-
SdoData = 0x00001a00;
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadReq (pStation,
0x1c13, 0x01, 2, (PUCHAR)&SdoData))
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadResp(pStation)) {
-
-
SdoData = 0x00001a03;
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadReq (pStation,
0x1c13, 0x02, 2, (PUCHAR)&SdoData))
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadResp(pStation)) {
-
-
SdoData = 0x00000002;
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadReq (pStation,
0x1c13, 0x00, 1, (PUCHAR)&SdoData))
-
if (ERROR_SUCCESS ==
Ecat64SdoInitDownloadResp(pStation)) {
-
-
//*** Disable SDO automation ***
-
pStation->SdoNum = 0;
-
return TRUE; }}}}}}}}}
-
-
//*** Something failed ***
-
return FALSE;
-
}
-
-
//Set back old alignment
-
#pragma pack(pop, old_alignment)
|
Build Template Code
|
-
Als Nächstes muss der Vorlagencode
erstellt werden. Der Code-Assistent
unterstützt Sie bei der Erstellung
verschiedener Codevorlagen:
Beginner: Kurzer Code mit High-Level-Schnittstelle. Keine
Unterstützung für verteilte Taktung.
Beginner DC: Kurzer Code mit
High-Level-Schnittstelle. Unterstützung
für verteilte Taktung. Expert: Standardcode mit
Low-Level-Schnittstelle. Keine
Unterstützung für verteilte Taktung.
Expert DC: Standardcode mit
Low-Level-Schnittstelle. Unterstützung
für verteilte Taktung. Expert Silent:
Standardcode mit
Low-Level-Schnittstelle. Unterstützung
für verteilte Taktung und Silent-Modus.
Die Codevorlage wird automatisch
mithilfe einer vordefinierten
Vorlagencodedatei (*.tpl) und den
generierten Headerdateien erstellt. Der
Vorlagencode enthält drei
gerätespezifische Einfügungen:
•
Header-Datei-Includes •
Mapping-Strukturen • SdoControls
Diese Informationen werden in den
Vorlagencode eingefügt und machen ihn
ausführbar.
|
|
Sample: Expert DC Code
|
- //***************************************
- // Automated generated code template ***
- // EtherCAT Code Type : [Expert DC] ***
- //***************************************
-
- #include <windows.h>
- #include <stdio.h>
- #include <conio.h>
- #include "c:\sha\globdef64.h"
- #include "c:\sha\sha64debug.h"
- #include "c:\eth\Sha64EthCore.h"
- #include "c:\eth\Eth64CoreDef.h"
- #include "c:\eth\Eth64Macros.h"
- #include "c:\ect\Sha64EcatCore.h"
- #include "c:\ect\Ecat64CoreDef.h"
- #include "c:\ect\Ecat64Macros.h"
- #include "c:\ect\Ecat64Control.h"
- #include "c:\ect\Ecat64SilentDef.h"
-
-
- //Configuration Header Includes
- #include "DevConfig_EK1100_2001091626.h"
- #include "DevConfig_EL1008_2001091626.h"
- #include "DevConfig_EL2004_2001091626.h"
- #include "DevConfig_EL7041_2001081526.h"
- #include "DevConfig_LXM32M_2001091624.h"
-
- #pragma comment( lib, "c:\\sha\\sha64dll.lib" )
- #pragma comment( lib, "c:\\eth\\sha64ethcore.lib" )
- #pragma comment( lib, "c:\\ect\\sha64ecatcore.lib" )
-
- #pragma warning(disable:4996)
- #pragma warning(disable:4748)
-
-
- #define REALTIME_PERIOD 2000 //Realtime sampling period [usec]
- #define SYNC_CYCLES 1
-
- //************************************
- //#define SEQ_DEBUG 1
- //************************************
-
-
- //Declare global elements
- PETH_STACK __pUserStack = NULL; //Ethernet Stack (outside Realtime Task)
- PETH_STACK __pSystemStack = NULL; //Ethernet Stack (inside Realtime Task)
- PSTATION_INFO __pUserList = NULL; //Station List (outside Realtime Task)
- PSTATION_INFO __pSystemList = NULL; //Station List (inside Realtime Task)
- USHORT __StationNum = 0; //Number of Stations
- FP_ECAT_ENTER __fpEcatEnter = NULL; //Function pointer to Wrapper EcatEnter
- FP_ECAT_EXIT __fpEcatExit = NULL; //Function pointer to Wrapper EcatExit
- ULONG __EcatState = 0; //Initial Wrapper State
- ULONG __UpdateCnt = 0; //Station Update Counter
- ULONG __LoopCnt = 0; //Realtime Cycle Counter
- ULONG __ReadyCnt = 0; //Ready state counter
- STATE_OBJECT __StateObject = { 0 }; //Cyclic state object
- BOOLEAN __bLogicReady = FALSE; //Logic Ready Flag
-
-
- //***************************
- #ifdef SEQ_DEBUG
- SEQ_INIT_ELEMENTS(); //Init sequencing elements
- #endif
- //***************************
-
-
- __inline PVOID __GetMapDataByName(char* szName, int Index, BOOLEAN bInput)
- {
- int cnt = 0;
-
- //Loop through station list
- for (USHORT i=0; i<__StationNum;i++)
- if (strstr(__pUserList[i].szName, szName))
- if (cnt++ == Index)
- {
- //Get station pointer and return index
- if (bInput) { return __pUserList[i].RxTel.s.data; }
- else { return __pUserList[i].TxTel.s.data; }
- }
-
- //Station not found
- return NULL;
- }
-
-
- void static DoLogic()
- {
- //Get mapped data pointers
- //... more devices
-
- PTX_MAP_EL1008_2001091626 pTxMap_EL1008_0 = (PTX_MAP_EL1008_2001091626)__GetMapDataByName("EL1008", 0, TRUE); //1. Device
- //PTX_MAP_EL1008_2001091626 pTxMap_EL1008_1 = (PTX_MAP_EL1008_2001091626)__GetMapDataByName("EL1008", 1, TRUE); //2. Device
- //PTX_MAP_EL1008_2001091626 pTxMap_EL1008_2 = (PTX_MAP_EL1008_2001091626)__GetMapDataByName("EL1008", 2, TRUE); //3. Device
- //... more devices
-
- PRX_MAP_EL2004_2001091626 pRxMap_EL2004_0 = (PRX_MAP_EL2004_2001091626)__GetMapDataByName("EL2004", 0, FALSE); //1. Device
- //PRX_MAP_EL2004_2001091626 pRxMap_EL2004_1 = (PRX_MAP_EL2004_2001091626)__GetMapDataByName("EL2004", 1, FALSE); //2. Device
- //PRX_MAP_EL2004_2001091626 pRxMap_EL2004_2 = (PRX_MAP_EL2004_2001091626)__GetMapDataByName("EL2004", 2, FALSE); //3. Device
- //... more devices
-
- PTX_MAP_EL7041_2001081709 pTxMap_EL7041_0 = (PTX_MAP_EL7041_2001081709)__GetMapDataByName("EL7041", 0, TRUE); //1. Device
- PRX_MAP_EL7041_2001081709 pRxMap_EL7041_0 = (PRX_MAP_EL7041_2001081709)__GetMapDataByName("EL7041", 0, FALSE); //1. Device
- //PTX_MAP_EL7041_2001081709 pTxMap_EL7041_1 = (PTX_MAP_EL7041_2001081709)__GetMapDataByName("EL7041", 1, TRUE); //2. Device
- //PRX_MAP_EL7041_2001081709 pRxMap_EL7041_1 = (PRX_MAP_EL7041_2001081709)__GetMapDataByName("EL7041", 1, FALSE); //2. Device
- //PTX_MAP_EL7041_2001081709 pTxMap_EL7041_2 = (PTX_MAP_EL7041_2001081709)__GetMapDataByName("EL7041", 2, TRUE); //3. Device
- //PRX_MAP_EL7041_2001081709 pRxMap_EL7041_2 = (PRX_MAP_EL7041_2001081709)__GetMapDataByName("EL7041", 2, FALSE); //3. Device
- //... more devices
-
- PTX_MAP_LXM32M_2001091624 pTxMap_LXM32M_0 = (PTX_MAP_LXM32M_2001091624)__GetMapDataByName("LXM32M", 0, TRUE); //1. Device
- PRX_MAP_LXM32M_2001091624 pRxMap_LXM32M_0 = (PRX_MAP_LXM32M_2001091624)__GetMapDataByName("LXM32M", 0, FALSE); //1. Device
- //PTX_MAP_LXM32M_2001091624 pTxMap_LXM32M_1 = (PTX_MAP_LXM32M_2001091624)__GetMapDataByName("LXM32M", 1, TRUE); //2. Device
- //PRX_MAP_LXM32M_2001091624 pRxMap_LXM32M_1 = (PRX_MAP_LXM32M_2001091624)__GetMapDataByName("LXM32M", 1, FALSE); //2. Device
- //PTX_MAP_LXM32M_2001091624 pTxMap_LXM32M_2 = (PTX_MAP_LXM32M_2001091624)__GetMapDataByName("LXM32M", 2, TRUE); //3. Device
- //PRX_MAP_LXM32M_2001091624 pRxMap_LXM32M_2 = (PRX_MAP_LXM32M_2001091624)__GetMapDataByName("LXM32M", 2, FALSE); //3. Device
- //... more devices
-
-
- //ToDo: Payload logic
- //...
-
- //****************************
- #ifdef SEQ_DEBUG
- SYSTEM_SEQ_CAPTURE("SEQ", __LINE__, 0, TRUE);
- #endif
- //****************************
- }
-
-
- void static AppTask(PVOID)
- {
- //Call enter wrapper function
- __EcatState = __fpEcatEnter(
- __pSystemStack,
- __pSystemList,
- (USHORT)__StationNum,
- &__StateObject);
-
-
- //Check operation state and increase ready count
- if (__EcatState == ECAT_STATE_READY) { __ReadyCnt--; }
- else { __ReadyCnt = SYNC_CYCLES; }
-
- //Check ready count
- if (__ReadyCnt == 1)
- {
- //**********************************
- if (__bLogicReady) { DoLogic(); }
- //**********************************
-
- //Update counter
- __UpdateCnt++;
- }
-
- //Call exit function
- __fpEcatExit();
-
- //Increase loop count
- __LoopCnt++;
- }
-
-
- __inline ULONG __SdoControl(void)
- {
- //Loop through station list
- for (USHORT i=0; i<__StationNum;i++)
- {
- PSTATION_INFO pStation = (PSTATION_INFO)&__pUserList[i];
- //Do Device SDO control
- if (strstr(pStation->szName, "EL7041"))
- if (__SdoControl_EL7041_2001081709(pStation) == FALSE)
- return (-1);
-
- if (strstr(pStation->szName, "LXM32M"))
- if (__SdoControl_LXM32M_2001091624(pStation) == FALSE)
- return (-1);
- }
-
- //Do default PDO assignment
- return Ecat64PdoAssignment();
- }
-
-
- void main(void)
- {
- //******************
- #ifdef SEQ_DEBUG
- SEQ_ATTACH(); //Attach to sequence memory
- SEQ_RESET(TRUE, FALSE, NULL, 0); //Reset/Init sequence memory
- #endif
- //******************
-
- printf("\n*** EtherCAT Code Type: [Expert DC] ***\n\n");
-
- //Set ethernet mode
- __EcatSetEthernetMode(0, REALTIME_PERIOD, SYNC_CYCLES, TRUE);
-
- //Required ECAT parameters
- ECAT_PARAMS EcatParams;
- memset(&EcatParams, 0, sizeof(ECAT_PARAMS));
- EcatParams.PhysAddr = DEFAULT_PHYSICAL_ADDRESS;
- EcatParams.LogicalAddr = DEFAULT_LOGICAL_ADDRESS;
- EcatParams.SyncCycles = SYNC_CYCLES; //Set cycles for synchronisation interval
- EcatParams.EthParams.dev_num = 0; //Set NIC index [0..7]
- EcatParams.EthParams.period = REALTIME_PERIOD; //Set realtime period [µsec]
- EcatParams.EthParams.fpAppTask = AppTask;
-
- //******************************
- //Create ECAT realtime core
- //******************************
- if (ERROR_SUCCESS == Sha64EcatCreate(&EcatParams))
- {
- Sleep(1000);
-
- //Init global elements
- __pUserStack = EcatParams.EthParams.pUserStack;
- __pSystemStack = EcatParams.EthParams.pSystemStack;
- __pUserList = EcatParams.pUserList;
- __pSystemList = EcatParams.pSystemList;
- __StationNum = EcatParams.StationNum;
- __fpEcatEnter = EcatParams.fpEcatEnter;
- __fpEcatExit = EcatParams.fpEcatExit;
-
- //Display station information
- for (int i=0; i<__StationNum; i++)
- printf("Station: %i, Name: %6s\n", i, __pUserList[i].szName);
-
- //******************************
- //Enable Stations
- //******************************
-
- //Change state to INIT
- if (ERROR_SUCCESS == Ecat64ChangeAllStates(AL_STATE_INIT))
- {
- UCHAR Data[0x100] = { 0 };
-
- //Reset devices
- Ecat64ResetDevices();
- Ecat64SendCommand(BWR_CMD, 0x0000, 0x300, 8, Data);
-
- //Set fixed station addresses and
- //Init FMMUs and SYNCMANs
- if (ERROR_SUCCESS ==
- Ecat64InitStationAddresses(EcatParams.PhysAddr))
- if (ERROR_SUCCESS == Ecat64InitFmmus(EcatParams.LogicalAddr))
- if (ERROR_SUCCESS == Ecat64InitSyncManagers())
- {
- //Change state to PRE OPERATIONAL
- //Init PDO assignment
- if (ERROR_SUCCESS == Ecat64ChangeAllStates(AL_STATE_PRE_OP))
- if (ERROR_SUCCESS == __SdoControl())
- {
- //Drift compensation delay [msec]
- ULONG CompLoops = 1000;
-
- //Init DC immediately after cyclic operation started
- //and get static master drift per msec (nsec unit)
- if (ERROR_SUCCESS == Ecat64ReadDcLocalTime())
- if (ERROR_SUCCESS == Ecat64CompDcOffset())
- if (ERROR_SUCCESS == Ecat64CompDcPropDelay())
- if (ERROR_SUCCESS == Ecat64CompDcDrift(&CompLoops))
- if (ERROR_SUCCESS == Ecat64DcControl())
- {
- //Init process telegrams (required for
- //AL_STATE_SAFE_OP)
- Ecat64InitProcessTelegrams();
-
- //********************************************************
- //Start cyclic operation
- //********************************************************
- if (ERROR_SUCCESS ==
- Ecat64CyclicStateControl(&__StateObject, AL_STATE_SAFE_OP)) { Sleep(500);
- if (ERROR_SUCCESS ==
- Ecat64CyclicStateControl(&__StateObject, AL_STATE_OP)) { Sleep(100);
-
- //Set Logic Ready Flag
- __bLogicReady = TRUE;
-
- //Do a check loop
- printf("\nPress any key ...\n");
- while (!kbhit())
- {
- //Display TX and RX information
- printf("Update Count: %i\r",
- __UpdateCnt);
-
- //Do some delay
- Sleep(100);
- }
-
- //Reset Logic Ready Flag
- __bLogicReady = FALSE;
- Sleep(100);
-
- //********************************************************
- //Stop cyclic operation
- //********************************************************
- Ecat64CyclicStateControl(&__StateObject, AL_STATE_INIT);
- }
- }
- }
- }
- }
- }
- //Destroy ECAT core
- Sha64EcatDestroy(&EcatParams);
- }
-
- //Check Status
- If (EcatParams.EthParams.pUserStack == NULL)
- { printf("\n*** Ethernet Stack Failed ***\n"); }
- else if (EcatParams.EthParams.err_cnts.Phy != 0)
- { printf("\n*** No Link ***\n"); }
- else if (EcatParams.pUserList == NULL)
- { printf("\n*** No Station List ***\n"); }
- else if (EcatParams.StationNum == 0)
- { printf("\n*** No Station Found ***\n"); }
- else { printf("\n*** OK ***\n"); }
-
- //Wait for key press
- printf("\nPress any key ...\n");
- while (!kbhit()) { Sleep(100); }
-
- //******************
- #ifdef SEQ_DEBUG
- SEQ_DETACH(); //Detach from sequence memory
- #endif
- //******************
- }
|
|