| S7plc EPICS driver S7plc EPICS driver documentationContents
IntroductionTheory of OperationDriver ConfigurationDevice Support
 
 Connection StatusAnalog InputAnalog OutputBinary InputBinary OutputMultibit Binary InputMultibit Binary OutputMultibit Binary Input DirectMultibit Binary Output DirectLong InputLong OutputString InputString OutputWaveform InputCalculation OutputDriver Functions 1 Introduction
This driver is intended to connect a Siemens S7 PLC (programmable
logic controller) via TCP/IP to an EPICS IOC, using the so called
"send/receive" protocol.
However, it can be used for any device sending and receiving blocks of
process variables (PVs) in the same way.
I highly recommend to connect to the PLC on a separate physical
network using a second network interface to avoid connection problems.
 
The driver was originally developped for SLS (Swiss Light Source) in 2000.
Later is has been modified by DESY (Deutsches Elektronen Synchrotron). The
current version has been completely rewritten for PPT (Puls-Plasmatechnik GmbH)
to run on a R3.14.6 PC based system, but it can also run on R3.13 vxWorks
system. Author of the current version is
Dirk
Zimoch <dirk.zimoch@psi.ch>.
 
In this document, it is assumed that the reader is familiar with EPICS, the
record concept and meanings of the fields of the standard records.
Recommended documentation: EPICS Record Refecrence Manual.
 2 Theory of Operation
The driver and the PLC periodically exchange data (process variables)
over the network.
For each direction (IOC to PLC and PLC to IOC), there is one fixed size
data block that bundles all process variables for this direction.
The process variables are identified by their bytes offset in the data
block.
 
Process variables can be 8, 16, or 32 bit wide signed or unsigned integers
or bit fields, single or double precision floating point values,
or arrays of these, as well as strings of single byte characters.
Both byte orders, big endian and little endian, are supported.
 
The IOC programmer typically connects one input record to each process
variable sent from the PLC to the IOC and one output record for each
process variable sent from the IOC to the PLC.
This requires that the programmer of the PLC and the programmer of the IOC
agree on the data block sizes and layouts.
The layout is not negotiated between IOC and PLC in any automated way.
 
When the IOC starts, the driver tries to connect to the PLC
which must run a TCP server.
If connection cannot be established (e.g. because the PLC is off)
the driver periodically retries to set up the connection.
Once connected, the driver waits for data blocks sent by the PLC.
The PLC must be set up to send its data periodically.
If the driver does not receive any data within a configurable timeout
(which should be 2 to 10 times the send period of the PLC) or the
data block does not have the correct size, the driver considers the
communication broken and closes the connection.
After a short time it tries to reconnect.
 
Upon reciving the data block, the driver copies the process variables
from this block into input records and then triggers processing of the
records.
To allow this triggering, the input records should use "I/O Intr" scanning
(or alternatively be processed by another record that uses "I/O Intr"
and is conencted to the same PLC).
All input records connected to the same PLC are triggered at the same time
after all input values have been updated.
The order of processing is undefined.
 
On the other hand, the driver periodically checks if any of the output
records connected to this PLC has processed since the last cycle.
If and only if this is the case, a data block containing all output
variables is sent to the PLC.
Sending output only starts after the "PINI" run at IOC startup.
This allows to initialize all output records before any data is sent
to the IOC.
Thus all output records should have the "PINI" field set to "YES" (or
alternatively be processed by another record that uses "PINI").
Any output that has not been processed before the data block is sent
to the PLC transfers only 0 bytes (usually meaning integer 0, floating
point 0.0, or empty string, depending on the data type).
 
Data blocks are always transfered completely.
That means all process variables in that block are transfered, even
if they have not changed since the last cycle.
There is no way to write or read only a sub-set of process variables.
In between two cycles, any number of process variables may have changed.
These changes are only transfered to the other communication partner
in the next cycle.
Thus, there is always a delay until the values update on the other side
of the connection.
Also if values change too quickly, faster than the transfer cycle,
intermediate values are lost.
 3 Driver Configuration
In the IOC startup script, the s7plc driver needs to be configured:
 
s7plcConfigure (PLCname, IPaddr, port, inSize,
outSize, bigEndian, recvTimeout, sendIntervall)
 
PLCnameis an arbitrary symbolic name for the PLC running
a server TCP socket onIPaddr:port. 
The records reference the PLC with this name in theirINPorOUTlink.PLCnamemust not contain the
slash character (/). 
inSizeandoutSizeare the data block
sizes in bytes read from and sent to the PLC, respectively. Any of them can
be0. Byte order is defined bybigEndian. If
this is1, the IOC expects the PLC to send and receive any
multibyte PV (word, float, etc) most significant byte first. If it is0, the data is least significant byte first. This is independent
of the byte order of the IOC. 
If the IOC does not receive new data from the PLC for
recvTimeoutmilliseconds, it closes the connection and
tries to reopen it after a few seconds.recvTimeoutshould be 2 to 10 times the send intervall of the PLC. 
The IOC checks for data to send every sendIntervallmilliseconds. If any output record has been processed in this time, the
complete buffer is sent to the PLC. If no new output is available, nothing
is sent. Example:
s7plcConfigure ("vak-4", "192.168.0.10", 2000, 1024, 32, 1, 500, 100)
 
In the vxWorks target shell, PLCname, andIPaddrmust be quoted. In the iocsh, quotes are
optional. 
The variable s7plcDebugcan be set in the statup script or
at any time on the command line to change the amount or debug output.
The following levels are supported: 
-1:  fatal errors only0:  errors only
 1:  startup messages
 2:+ output record processing
 3:+ inputput record processing
 4:+ driver calls
 5:+ io printout
 
 
Be careful using level>1 since many messages can introduce considerable
delays which may result in connection losses. Default level is 0.
 
On vxWorks, s7plcDebugcan be set withs7plcDebug=level 
In the iocsh use
var s7plcDebug level 4 Device Support
The driver supports the standard record types ai,
ao, bi, bo,
mbbi, mbbo,
mbbiDirect, mbboDirect,
longin, longout,
stringin, stringout,
and waveform. With EPICS R3.14,
calcout is supported, too.
The DTYPis"S7plc". If the record processes when
the PLC is not connected (off, down, unreachable), the record raises an
alarm withSEVR="INVALID"andSTAT="CONN". 
There is also a connection status support for bi. The
DTYPis"S7plc stat". This record does not
raise an alarm when the PLC is disconnected. It just changes to0state in that case. 
SCAN="I/O Intr"is supported. Whenever input data is received
from a PLC, all"I/O Intr"input records connected to this PLC
are processed. In each output cyle, all"I/O Intr"output
records are processed. 
The general form of the INPorOUTlink is 
  "@PLCname/offset T=type L=low H=high B=bit"
 
Not all parameters T,L,H, andBare required for each record type and parameters equal to the
default value may be omitted. The default values depend on the record type. 
PLCnameis the PLC name as defined bys7plcConfigurein the startup script. 
offsetis the byte offset of the PV relative to the
beginning of the input or output data block for this PLC. It must be an
integer number or a sum of integer numbers like20+3+2. 
T=typedefines the data type for transmitting the PV
from or to the PLC. It is not case sensitive and has several aliases (see
table below).
The default isT=INT16for most record types.L=lowandH=highare used in analog
input and output records ifLINRis set to"LINEAR"to convert analog values to integer values and back. They define the raw
values which correspond toEGULandEGUF,
respectively.
Analog output records will never write integer values lower thanLor higher thanH. If necessary, the raw output
value is truncated to the nearest limit. The default values forLandHdepend onT. 
| T= | Data Type | Default L= | Default H= |  
 | INT8 | 8 bit (1 byte) signed integer number | -0x7F -127
 | 0x7F 127
 |  
 | UINT8 UNSIGN8
 BYTE
 CHAR
 | 8 bit (1 byte) unsigned integer number | 0x00 0
 | 0xFF 255
 |  
 | INT16 SHORT
 | 16 bit (2 bytes) signed integer number | -0x7FFF -32767
 | 0x7FFF 32767
 |  
 | UINT16 UNSIGN16
 WORD
 | 16 bit (2 bytes) unsigned integer number | 0x0000 0
 | 0xFFFF 65535
 |  
 | INT32 LONG
 | 32 bit (4 bytes) signed integer number | -0x7FFFFFFF -2147483647
 | 0x7FFFFFFF 2147483647
 |  
 | UINT32 UNSIGN32
 DWORD
 | 32 bit (4 bytes) unsigned integer number | 0x00000000 0
 | 0xFFFFFFFF 4294967295
 |  
 | REAL32 FLOAT32
 FLOAT
 | 32 bit (4 bytes) floating point number | N/A | N/A |  
 | REAL64 FLOAT64
 DOUBLE
 | 64 bit (8 bytes) floating point number | N/A | N/A |  
 | STRING | character array | 40 | N/A |  
If T=STRING,Lmeans length, not low.
The default value is the length of theVALfield.
In the case of the stringin and stringout records, this is 40 (including
the terminating null byte). 
B=bitis only used for bi and bo records to define the
bit number within the data byte, word, or doubleword (depending onT). Bit number 0 is the least significant bit.
Note that in big endian byte order (also known as motorola format) bit 0 is
in the last byte, while in little endian byte order (intel format) bit 0 is
in the first byte. If in doubt, useT=BYTEto avoid all
byte order problems when handling single bits. 
Note that the output buffer is initialised with null bytes at startup and
any output record that has not been processed after reboot will send null
values to the PLC. The driver does not send anything before the global
variable interruptAccepthas been setTRUEat the
end ofiocInit. All records withPINIset to"YES"have already been processed by that time. The driver
does not change theVALfield of any output record at
initialisation. Thus, auto save and restore can be used in combination withPINI="YES". 4.1 Connection Status
 record (bi, "$(RECORDNAME)") {
  field (DTYP, "S7plc stat")
  field (INP,  "@$(PLCNAME)")
  field (SCAN, "I/O Intr")
 }
The record value is 1 if a connection to the PLC is established and 0 if not.
Disconnect does not raise an alarm.
 4.2 Analog InputWith conversion from integer data type:
 record (ai, "$(RECORDNAME)") {
  field (DTYP, "S7plc")
  field (INP,  "@$(PLCNAME)/$(OFFSET) T=$(T) L=$(L) H=$(H)")
  field (SCAN, "I/O Intr")
  field (LINR, "Linear")
  field (EGUL, "$(MINVAL)")
  field (EGUF, "$(MAXVAL)")
 }
Using floating point data type:
 record (ai, "$(RECORDNAME)") {
  field (DTYP, "S7plc")
  field (INP,  "@$(PLCNAME)/$(OFFSET) T=$(T)")
  field (SCAN, "I/O Intr")
 }
Default type is T=INT16.
Defaults forLandHdepend
onT(see table above). 
If Tis an integer type, the PV is read intoRVAL. IfLINRis set to"LINEAR",
then the record support convertsRVALtoVALso thatRVAL=Lconverts toVAL=EGULandRVAL=Hconverts toVAL=EGUF. 
VALtemp=(RVAL-L)*(EGUF-EGUL)/(H-L)+EGUL 
After this conversion, VALtempis still
subject to scaling and smoothing. 
VAL=(VALtemp*ASLO+AOFF)*(1-SMOO)+VALold*SMOO. 
If T=FLOATorT=DOUBLE,
the PV is read directly intoVALandL,H,EGULandEGUFare ignored.
The device support emulates scaling and smoothing which is otherwise done
by the record support during conversion. 
VAL=(PV*ASLO+AOFF)*(1-SMOO)+VALold*SMOO 
T=STRINGis not valid for ai records. 4.3 Analog OutputWith conversion to integer data type:
 record (ao, "$(RECORDNAME)") {
  field (DTYP, "S7plc")
  field (OUT,  "@$(PLCNAME)/$(OFFSET) T=$(T) L=$(L) H=$(H)")
  field (LINR, "Linear")
  field (PINI, "YES")
  field (EGUL, "$(MINVAL)")
  field (EGUF, "$(MAXVAL)")
 }
Using floating point data type:
 record (ao, "$(RECORDNAME)") {
  field (DTYP, "S7plc")
  field (OUT,  "@$(PLCNAME)/$(OFFSET) T=$(T)")
  field (PINI, "YES")
 }
Default type is T=INT16.
Defaults forLandHdepend
onT(see table above). 
If Tis an integer type,RVALis
written to the PV. IfLINRis set to"LINEAR",
then the record support first scalesOVAL. 
OVALtemp=(OVAL-AOFF)/ASLO 
After that, the value is converted to RVALso thatOVALtemp=EGULconverts toRVAL=LandOVALtemp=EGUFconverts toRVAL=H. 
RVAL=(OVALtemp-EGUL)*(H-L)/(EGUF-EGUL)+L 
If RVALis higher thanHor lower thanL, the value is truncated to the nearest limit. 
If T=FLOATorT=DOUBLE,OVALis written directly to the PV.L,H,EGULandEGUFare ignored.
The device support emulates scaling which is otherwise done by the
record support during conversion. 
PV=(OVAL-AOFF)/ASLO 
T=STRINGis not valid for ao records. 4.4 Binary Input
 record(bi, "$(NAME)") {
  field (DTYP, "S7plc")
  field (INP,  "@$(PLCNAME)/$(OFFSET) T=$(T) B=$(B)")
  field (SCAN, "I/O Intr")
 }
Default type is T=INT16. Default bit isB=0. 
Depending on T,Bcan vary from 0 to 7, 15, or 31.
Bit 0 is the least significant bit. In little endian byte order, bit 0 is in
the first byte, in big endian byte order it is in the last byte of the PV.
If in doubt, useT=BYTEto avoid all byte order problems when
handling single bits. 
The PV is read to RVALand masked with
2B.VALis 1 ifRVALis not 0. 
RVAL=PV&(1<<B); VAL=(RVAL!=0)?1:0 
T=STRING,T=FLOATorT=DOUBLEare not
valid for bo records. Signed and unsigned types are equivalent. 4.5 Binary Output
 record(bo, "$(NAME)") {
  field (DTYP, "S7plc")
  field (OUT,  "@$(PLCNAME)/$(OFFSET) T=$(T) B=bit")
  field (PINI, "YES")
 }
Default type is T=INT16. Default bit isB=0. 
Depending on T,Bcan vary from 0 to 7, 15, or 31.
Bit 0 is the least significant bit. In little endian byte order, bit 0 is in
the first byte, in big endian byte order it is in the last byte of the PV.
If in doubt, useT=BYTEto avoid all byte order problems when
handling single bits. 
If VALis not 0, thenRVALis set to
2B, elseRVALis set to 0.
Only the referenced bit of the PV is changed while all other bits remain
untouched. Thus, other output records can write to different bits of the
same PV. 
RVAL=(VAL!=0)?(1<<bit):0;
PV=(PVold&~(1<<bit))|RVAL 
T=STRING,T=FLOATorT=DOUBLEare not
valid for bo records. Signed and unsigned types are equivalent. 4.6 Multibit Binary Input
 record(mbbi, "$(NAME)") {
  field (DTYP, "S7plc")
  field (INP,  "@$(PLCNAME)/$(OFFSET) T=$(T)")
  field (SCAN, "I/O Intr")
  field (NOBT, "$(NUMBER_OF_BITS)")
  field (SHFT, "$(RIGHT_SHIFT)")
 }
Default type is T=INT16. 
The PV is read to RVAL, shifted right bySHFTbits
and masked withNOBTbits. Valid values forNOBTandSHFTdepend onT:NOBT+SHFTmust not exceed the number of bits of
the type. 
Bit 0 is the least significant bit. In little endian byte order, bit 0 is in
the first byte, in big endian byte order it is in the last byte of the PV.
 
Example: Use bits 4 to 9 out of 16.
T=INT16,NOBT=6,SHFT=4 
 
  | PV | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |  
  | RVAL |  |  |  |  |  |  |  |  |  |  | 9 | 8 | 7 | 6 | 5 | 4 |  
T=STRING,T=FLOATorT=DOUBLEare not
valid for mbbi records. Signed and unsigned types are equivalent. 4.7 Multibit Binary Output
 record(mbbo, "$(NAME)") {
  field (DTYP, "S7plc")
  field (OUT,  "@$(PLCNAME)/$(OFFSET) T=$(T)")
  field (PINI, "YES")
  field (NOBT, "$(NUMBER_OF_BITS)")
  field (SHFT, "$(LEFT_SHIFT)")
 }
Default type is T=INT16. 
RVAL is masked with NOBTbits, shifted left bySHFTbits and written to the PV. Valid values forNOBTandSHFTdepend onT:NOBT+SHFTmust not exceed the number of bits of
the type. 
Bit 0 is the least significant bit. In little endian byte order, bit 0 is in
the first byte, in big endian byte order it is in the last byte of the PV.
 
Only the referenced NOBTbits of the PV are changed. All other
bits remain untouched. Thus, other output records can write to different bits
of the same PV. 
Example: Use bits 5 to 8 out of 16.
T=INT16,NOBT=4,SHFT=5 
 
  | RVAL |  |  |  |  |  |  |  |  |  |  |  |  | 8 | 7 | 6 | 5 |  
  | PV | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |  
T=STRING,T=FLOATorT=DOUBLEare not
valid for mbbo records. Signed and unsigned types are equivalent. 4.8 Multibit Binary Input Direct
 record(mbbiDirect, "$(NAME)") {
  field (DTYP, "S7plc")
  field (INP,  "@$(PLCNAME)/$(OFFSET) T=$(T)")
  field (SCAN, "I/O Intr")
  field (NOBT, "$(NUMBER_OF_BITS)")
  field (SHFT, "$(RIGHT_SHIFT)")
 }
Default type is T=INT16. 
The PV is read to VAL, shifted right bySHFTbits and masked withNOBTbits (see mbbi).
Valid values forNOBTandSHFTdepend
onT:NOBT+SHFTmust
not exceed the number of bits of the type. 
Bit 0 is the least significant bit. In little endian byte order, bit 0 is in
the first byte, in big endian byte order it is in the last byte of the PV.
 
T=STRING,T=FLOATorT=DOUBLEare not
valid for mbbiDirect records. Signed and unsigned types are equivalent. 4.9 Multibit Binary Output Direct
 record(mbboDirect, "$(NAME)") {
  field (DTYP, "S7plc")
  field (OUT,  "@$(PLCNAME)/$(OFFSET) T=$(T)")
  field (PINI, "YES")
  field (NOBT, "$(NUMBER_OF_BITS)")
  field (SHFT, "$(LEFT_SHIFT)")
 }
Default type is T=INT16. 
VAL is masked with NOBTbits, shifted left bySHFTbits and written to the PV (see mbbo). Valid values forNOBTandSHFTdepend onT:NOBT+SHFTmust not exceed the number of bits of
the type. 
Bit 0 is the least significant bit. In little endian byte order, bit 0 is in
the first byte, in big endian byte order it is in the last byte of the PV.
 
Only the referenced NOBTbits of the PV are changed. All other
bits remain untouched. Thus, other output records can write to different bits
of the same PV. 
T=STRING,T=FLOATorT=DOUBLEare not
valid for mbboDirect records. Signed and unsigned types are equivalent. 4.10 Long Input
 record(longin, "$(NAME)") {
  field (DTYP, "S7plc")
  field (INP,  "@$(PLCNAME)/$(OFFSET) T=$(T)")
  field (SCAN, "I/O Intr")
 }
Default type is T=INT16. 
The PV is read to VAL. If the type has less than 32 bits, the
value is zero extended or sign extended depending on the signedness of
the type. 
T=STRING,T=FLOATorT=DOUBLEare not
valid for longin records. 4.11 Long Output
 record(longout, "$(NAME)") {
  field (DTYP, "S7plc")
  field (OUT,  "@$(PLCNAME)/$(OFFSET) T=$(T)")
  field (PINI, "YES")
 }
Default type is T=INT16. 
Depending on T, the least significant 8, 16, or 32 bytes
ofVALare written to the PV. 
T=STRING,T=FLOATorT=DOUBLEare not
valid for longout records. 4.12 String Input
 record(stringin, "$(NAME)") {
  field (DTYP, "S7plc")
  field (INP,  "@$(PLCNAME)/$(OFFSET) L=$(LENGTH)")
  field (SCAN, "I/O Intr")
 }
Default and only valid type is T=STRING.
Default length isL=40. 
Lbytes are read from the PV toVALand null
terminated. Thus, the effective string length is maximalL-1 bytes. 4.13 String Output
 record(stringout, "$(NAME)") {
  field (DTYP, "S7plc")
  field (OUT,  "@$(PLCNAME)/$(OFFSET) L=$(LENGTH)")
  field (PINI, "YES")
 }
Default and only valid type is T=STRING.
Default length isL=40. 
Lbytes are written fromVALto the PV.
If the actual string length ofVALis shorter thanL, the remaining space is filled with null bytes. If
it is longer thanL, the string is truncated and not
null terminated 4.14 Waveform Input
 record(waveform, "$(NAME)") {
  field (DTYP, "S7plc")
  field (INP,  "@$(PLCNAME)/$(OFFSET)")
  field (SCAN, "I/O Intr")
  field (NELM, "$(NUMBER_OF_ELEMENTS)")
  field (FTVL, "$(DATATYPE)")
 }
NELMelements are read from the PV toVAL. 
The default type depends on FTVL. For exampleFTVL=LONGresults inT=INT32.TandFTVLmust match but can differ
in signedness. In most cases, better just specifyFTVLand
leaveTto the default. 
If T=STRING,FTVLmust be"CHAR"or"UCHAR".L=lengthcan be specified but
defaults to and must not exceedNELM.
IfLis less thanNELM, the
remaining elements are left untouched. 
FTVL="STRING"is not supported. 
The special type T=TIMEis supported for
waveforms records only.FTVLmust be"CHAR"or"UCHAR"andNELMshould be"8". The input bytes are converted from BCD (binary coded decimal)
to integer values in the range from 0 to 99 each. This type is intended
to transfer BCD coded real time clock timestamps. 
The Siemens "STEP 7" manual defines the 8 byte PLC timetamp as follows:
 
 
  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |  
  | year | month | day | hour | minute | second | msec(hi) | msec(lo)*10+day of week |  
Years 90 to 99 mean 1990 to 1999, years 0 to 89 mean 2000 to 2089. Months
and days start with 1. Hour is 0 to 23, minute and second 0 to 59. Msec are
milliseconds in the range 0 to 999. The first two digits (0-99 hundredth of
a second) are in msec(hi). The last digit (0-9 thousandth of a second)
is multiplyed by 10 and added to the day of week (Sunday=1 to Saturday=7).
If you want to have the unconverted BCD bytes, do not use
T=TIME. 4.15 Calculation Output
 record(calcout, "$(NAME)") {
  field (DTYP, "S7plc")
  field (OUT,  "@$(PLCNAME)/$(OFFSET) T=$(T) L=$(L) H=$(H)")
  field (PINI, "YES")
 }
Default type is T=INT16.
Defaults forLandHdepend
onT(see table above). 
OVAL(the result ofCALCorOCAL,
depending onDOPT) is written to the PV. IfTis an integer type, the value is truncated to an
integer and compared toLandH.
IfOVALis lower thanLor higher thanH, it is truncated to the nearest limit. 
If T=FLOATorT=DOUBLE,OVALis written to the PV directly without any conversion. 
T=STRINGis not valid for calcout records. 
To use this device support with calcout records, you need EPICS R3.14.
 5 Driver Functions
Device support for other record types can be written with calls to the
following driver functions:
 
s7plcStation* s7plcOpen (char* PLCname);
 
int s7plcRead (s7plcStation* station,
unsigned int offset, unsigned int dlen,
void* pdata);
 
int s7plcReadArray (s7plcStation* station,
unsigned int offset, unsigned int dlen,
unsigned int nelem, void* pdata);
 
int s7plcWrite (s7plcStation* station,
unsigned int offset, unsigned int dlen,
void* pdata);
 
int s7plcWriteMasked (s7plcStation* station,
unsigned int offset, unsigned int dlen,
void* pdata, void* pmask);
 
int s7plcWriteArray (s7plcStation* station,
unsigned int offset, unsigned int dlen,
unsigned int nelem, void* pdata);
 
int s7plcWriteMaskedArray (s7plcStation* station,
unsigned int offset, unsigned int dlen,
unsigned int nelem, void* pdata, void* pmask);
 
The functions s7plcRead(),s7plcWrite(),s7plcWriteMasked(), ands7plcWriteArray()are actually macros fors7plcReadArray()ands7plcWriteMaskedArray()withnelem=1and/ormask=NULL. 
stationis a handle previously obtained by a call tos7plcOpen(). 
offsetis the byte offset of the PV relative
to the beginning to the data block. 
dlenis the length of the PV in bytes (one element in case of
arrays). If the endianess of the PLC differs from the IOC, the byte order of
thedlenbytes is swapped by the driver. 
nelemis the number of elements in an array. 
pdatais a pointer to a buffer ofnelem*dlenbytes.
PVs are read to or written from this buffer. 
maskis a pointer to a bitmask ofdlenbytes.
Only those bits are changed where the mask contains 1 bits. All other bits
remain untouched. 
For strings, use array functions with dlen=1andnelem=buffersize. Dirk Zimoch, March 2005 - February 2012
 Updated: 09.07.2025
 |