Reading a variable declaration
The following information is transferred when accessing the variable declaration:
- Variable name
- Data type
- Length
- Address (IndexGroup / IndexOffset)
- Comment
The AdsSyncReadWriteReq() call is used to read the variable information. The variable name is transferred to the function via parameter pWriteData. After the call the requested information is contained in variable pAdsSymbolEntry. The individual information items in the PLC variables are stored in this structure. The macros PADSSYMBOLNAME, PADSSYMBOLTYPE and PADSSYMBOLCOMMENT simplify the evaluation of this data. Next the data type of the variable is evaluated using pAdsSymbolEntry->dataType.
If the data type is UDINT or ARRAY OF UDINT, the value of this variable is also read out.
Download: sample14-c-ads-dll-readsinglevariabledeclaration.zip
#include <windows.h>
#include <conio.h>
#include <assert.h>
#include <string.h>
#include <iostream.h>
// ADS headers
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h"
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsApi.h"
typedef enum AdsDataTypeId
{
ADST_VOID = VT_EMPTY,
ADST_INT8 = VT_I1,
ADST_UINT8 = VT_UI1,
ADST_INT16 = VT_I2,
ADST_UINT16 = VT_UI2,
ADST_INT32 = VT_I4,
ADST_UINT32 = VT_UI4,
ADST_INT64 = VT_I8,
ADST_UINT64 = VT_UI8,
ADST_REAL32 = VT_R4,
ADST_REAL64 = VT_R8,
ADST_STRING = VT_LPSTR,
ADST_WSTRING = VT_LPWSTR,
ADST_REAL80 = VT_LPWSTR+1,
ADST_BIT = VT_LPWSTR+2,
ADST_BIGTYPE = VT_BLOB,
ADST_MAXTYPES = VT_STORAGE,
} ADS_DATATYPE;
typedef struct _ValueString
{
DWORD dwValue;
char* szLabel;
} ValueString;
ValueString AdsDatatypeString[] =
{
{ VT_EMPTY, "ADST_VOID", },
{ VT_I1, "ADST_INT8", },
{ VT_UI1, "ADST_UINT8", },
{ VT_I2, "ADST_INT16", },
{ VT_UI2, "ADST_UINT16", },
{ VT_I4, "ADST_INT32", },
{ VT_UI4, "ADST_UINT32", },
{ VT_I8, "ADST_INT64", },
{ VT_UI8, "ADST_UINT64", },
{ VT_R4, "ADST_REAL32", },
{ VT_R8, "ADST_REAL64", },
{ VT_LPSTR, "ADST_STRING", },
{ VT_LPWSTR, "ADST_WSTRING", },
{ VT_LPWSTR+2, "ADST_BIT", },
{ VT_BLOB, "ADST_BIGTYPE", },
{ VT_STORAGE, "ADST_MAXTYPES", },
};
void main()
{
long nErr, nPort;
AmsAddr Addr;
PAmsAddr pAddr = &Addr;
char szVariable[255];
BYTE buffer[0xFFFF];
PAdsSymbolEntry pAdsSymbolEntry;
// Open communication port on the ADS router
nPort = AdsPortOpen();
nErr = AdsGetLocalAddress(pAddr);
if (nErr) cerr << "Error: AdsGetLocalAddress: " << nErr << '\n';
// Select Port: TwinCAT2 PLC1
pAddr->port = 801;
for(;;)
{
cout << "Enter variable Name: ";
cin >> szVariable;
nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_INFOBYNAMEEX, 0, sizeof(buffer), buffer, strlen(szVariable)+1, szVariable);
if (nErr)
{
cerr << "Error: AdsSyncReadReq: " << nErr << '\n';
}
else
{
pAdsSymbolEntry = (PAdsSymbolEntry)buffer;
cout << "Name: " << PADSSYMBOLNAME(pAdsSymbolEntry) << "\n"
<<"Index Group: "<< pAdsSymbolEntry->iGroup << '\n'
<<"Index Offset: "<< pAdsSymbolEntry->iOffs << '\n'
<<"Size: "<< pAdsSymbolEntry->size << '\n'
<<"Type: "<< (char*)PADSSYMBOLTYPE(pAdsSymbolEntry) << '\n'
<<"Comment: "<< (char*)PADSSYMBOLCOMMENT(pAdsSymbolEntry) << '\n';
switch(pAdsSymbolEntry->dataType)
{
case ADST_UINT32:
{
int nElements = pAdsSymbolEntry->size/sizeof(unsigned long);
unsigned long *pVal = new unsigned long[nElements];
cout << "Datatype: ADST_UINT32" <<'\n';
AdsSyncReadReq(pAddr, pAdsSymbolEntry->iGroup, pAdsSymbolEntry->iOffs, pAdsSymbolEntry->size, pVal);
if( nErr )
{
cerr << "Error: AdsSyncReadReq: Unable to read Value" << nErr << '\n';
}
else
{
cout << "Value: ";
for( int i=0; i<nElements; i++ )
{
cout << pVal[i] << '\t';
}
cout << '\n';
}
}
break;
default:
{
int nType = sizeof(AdsDatatypeString)/sizeof(ValueString);
for(int i=0; i< nType; i++)
{
if( AdsDatatypeString[i].dwValue == pAdsSymbolEntry->dataType )
{
cout << "Datatype:" << AdsDatatypeString[i].szLabel <<'\n';
break;
}
}
if( i == nType )
cout << "Datatype:" << "Unknown datatype:" << pAdsSymbolEntry->dataType <<'\n';
}
break;
}
}
cout << "Exit(y/n)" << '\n';
cout.flush();
if(_getch() == 'y')
break;
}
// Close communication port
nErr = AdsPortClose();
if (nErr) cerr << "Fehler: AdsPortClose: " << nErr << '\n';
}
VAR_GLOBAL
PLCVarBYTE AT %MB0: BYTE; (* PLCVarBYTE *)
PLCVarWORD AT %MB4: WORD; (* PLCVarWORD *)
PLCVarDWORD AT %MB8: DWORD; (* PLCVarDWORD *)
PLCVarBOOL AT %MB12: BOOL; (* PLCVarBOOL *)
PLCVarINT AT %MB16: INT; (* PLCVarINT *)
PLCVarSINT AT %MB20: SINT; (* PLCVarSINT *)
PLCVarUSINT AT %MB24: USINT; (* PLCVarUSINT *)
PLCVarUINT AT %MB28: UINT; (* PLCVarUINT *)
PLCVarDINT AT %MB32: DINT; (* PLCVarDINT *)
PLCVarUDINT AT %MB34: UDINT := 1234; (* PLCVarUDINT *)
PLCVarREAL AT %MB38: REAL; (* PLCVarREAL *)
PLCVarLREAL AT %MB42: LREAL; (* PLCVarLREAL *)
PLCVarUDINTArray :ARRAY[0..5] OF UDINT; (* PLCVarINTArray*)
END_VAR