ADS-sum command: Get and release several handles

Download: VC++ Sample

This sample shows how to get and release several handles with the ADS-sum command. It's constructed like the AdsSyncReadWriteRequest and is used as container to transport the sub commands.

1. Get handles

First, all necessary headers have to be included.

#include <iostream.h> 
#include <windows.h>
#include <conio.h>

// ADS headers for TwinCAT 3
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h"
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h"

Next step is to define a structure, declare variables and allocate memory.

// Structure declaration for valuestypedef struct dataReq 
{
unsigned long indexGroup; // index group in ADS server interfaceunsigned long indexOffset; // index offset in ADS server interfaceunsigned long rlength; // count of bytes to readunsigned long wlength; // count of bytes to write
}TDataReq, *PTDataReq;


// Variables declaration
AmsAddr Addr;
LONG nErr, nPort;
PAmsAddr pAddr = &Addr;

char szVar1[] = {".bVar01"};
char szVar2[] = {".bVar02"};

// Allocate memory
ULONG cbReq = ( sizeof(TDataReq)*2 ) + sizeof(szVar1) + sizeof(szVar2);
BYTE* pBuffReq = new BYTE[cbReq];

BYTE* pBuffRes = new BYTE[24];

// Put structure over memory
PTDataReq pDataReq = (PTDataReq)pBuffReq;
ULONG* pDataRes = (ULONG*)pBuffRes;

The values which can be transferred are written behind the last structure.

ADS-sum command: Get and release several handles 1:

// pDataReq-> structure 1 
pDataReq->indexGroup = ADSIGRP_SYM_HNDBYNAME;
pDataReq->indexOffset = 0x0;
pDataReq->rlength = sizeof(ULONG);
pDataReq->wlength = sizeof(szVar1);

// Skip to next structure
pDataReq = pDataReq+1;

// pDataReq-> structure 2
pDataReq->indexGroup = ADSIGRP_SYM_HNDBYNAME;
pDataReq->indexOffset = 0x0;
pDataReq->rlength = sizeof(ULONG);
pDataReq->wlength = sizeof(szVar2);

// Skip to write data 1char* szVarName = ( (char*)pDataReq ) + sizeof(TDataReq);
strncpy( szVarName, szVar1, sizeof(szVar1) );

// Skip to write data 2
szVarName = szVarName + sizeof(szVar1);
strncpy( szVarName, szVar2, sizeof(szVar2) );

For the communication a open port is necessary. After that the local address is handed over. If it comes to transmission the port is assigned to the address of the run time system 1 first.The parameters for the sum command consist of IndexGroup (0xf082) - call the sum command, IndexOffset (0x2)- count of sub commands, ReadLength (0x18)- size of the data which can be read, ReadData (pBuffRes)- memory which read data assumes, WriteLength (cbReq)- size of the data which can be send and WriteLength (pBuffReq)- memory which contains data that can be sent.

// Open communication port on the ADS router 
nPort = AdsPortOpen();
nErr = AdsGetLocalAddress(pAddr);

cout << "open port: ";
if (nErr == 0)
{
cout << "OK" << '\n';

// Get handles
pAddr->port = AMSPORT_R0_PLC_RTS1;
nErr = AdsSyncReadWriteReq(
pAddr,
0xf082, // ADS list-read-write command
0x2, // number of ADS-sub commands
0x18, // we expect an ADS-error-return-code for each ADS-sub command
pBuffRes, // provide space for the response containing the return codes
cbReq, // cbReq : send 48 bytes (IG1, IO1, RLen1, WLen1,// IG2, IO2, RLen2, WLen2, Data1, Data2)
pBuffReq ); // buffer with data
}
else {cout << "ERROR [" << nErr << "]" << '\n';};

cout << "connect: ";
if (nErr == 0)
{
cout << "OK" << '\n';

// Skip to handle 1 and examine the value
ULONG nVarHandle = *( (ULONG*)pBuffRes );
if (nVarHandle != 0)
{
cout << " > handle1: ";
cout << "ERROR [" << nVarHandle << "]" << '\n';
}

// Skip to handle 2 and examine the value
nVarHandle = *( (ULONG*)pBuffRes + 2 );
if (nVarHandle != 0)
{
cout << " > handle2: ";
cout << "ERROR [" << nVarHandle << "]" << '\n';
}
}
else {cout << "ERROR [" << nErr << "]" << '\n';};

2. Release handlesDefine a structure, declare variables and allocate memory again.

// Structure declaration for valuestypedef struct dataRel 
{
unsigned long indexGroup; // index group in ADS server interfaceunsigned long indexOffset; // index offset in ADS server interfaceunsigned long length; // count of bytes to write
}TDataRel, *PTDataRel;


// Variables declaration
ULONG* nVar1 = (ULONG*)pBuffRes+4;
ULONG* nVar2 = (ULONG*)pBuffRes+5;

// Allocate memory
ULONG cbRel = sizeof(TDataRel)*2 + sizeof(ULONG)*2;
BYTE* pBuffRel = new BYTE[cbRel];

ULONG cbRelRes = sizeof(ULONG)*2;
BYTE* pBuffRelRes = new BYTE[cbRelRes];

// Put structure over memory
PTDataRel pDataRel = (PTDataRel)pBuffRel;
ULONG* pDataRelRes = (ULONG*)pBuffRelRes;

The values which can be transferred are written behind the last structure again.

ADS-sum command: Get and release several handles 2:

// pDataRel-> structure 1 
pDataRel->indexGroup = ADSIGRP_IOIMAGE_RWIB;
pDataRel->indexOffset = 0x0;
pDataRel->length = sizeof(ULONG);

// Skip to next structure
pDataRel++;

// pDataReq-> structure 2
pDataRel->indexGroup = ADSIGRP_IOIMAGE_RWIB;
pDataRel->indexOffset = 0x0;
pDataRel->length = sizeof(ULONG);

// Skip to next structure
pDataRel++;

// Write handles into structure
memcpy( pDataRel, nVar1, sizeof(ULONG) );
memcpy( (ULONG*)pDataRel+1, nVar2, sizeof(ULONG) );

The existing connection is used to release the handles.The parameters for the sum command consist of IndexGroup (0xf081) - call the sum command, IndexOffset (0x2)- count of sub commands, ReadLength (cbRelRes)- size of the data which can be read, ReadData (pBuffRelRes)- memory which read data assumes, WriteLength (cbRel)- size of the data which can be send and WriteLength (pBuffRel)- memory which contains data that can be sent.Last thing left is releasing the handles and closing the port.

// Release handles 
nErr = AdsSyncReadWriteReq(
pAddr,
0xf081, // ADS list-write command
0x2, // number of ADS-sub commands
cbRelRes, // we expect an ADS-error-return-code for each ADS-sub command
pBuffRelRes, // provide space for the response containing the return codes
cbRel, // cbReq : send 40 bytes (IG1, IO1, Len1, IG2, IO2, Len2, Data1, Data2)
pBuffRel ); // buffer with data

cout << "disconnect: ";
if (nErr == 0)
{
cout << "OK" << '\n';

// Skip to handle 1 and examine the value
ULONG nVarHandle = *( (ULONG*)pBuffRes );
if (nVarHandle != 0)
{
cout << " > handle1: ";
cout << "ERROR [" << nVarHandle << "]" << '\n';
}

// Skip to handle 2 and examine the value
nVarHandle = *( (ULONG*)pBuffRes + 2 );
if (nVarHandle != 0)
{
cout << " > handle2: ";
cout << "ERROR [" << nVarHandle << "]" << '\n';
}
}
else {cout << "ERROR [" << nErr << "]" << '\n';};

// Close the communication port
nErr = AdsPortClose();
cout << "close port: ";
if (nErr == 0) {cout << "OK" << '\n' << "-------------------" << '\n';}
else {cout << "ERROR [" << nErr << "]" << '\n' << "-------------------" << '\n';}

cout.flush();

// Wait for key press
getch();
}