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.
// 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.
// 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();
}