From 236a4ad497cff07b208d4c36d8e35909b73fc3d5 Mon Sep 17 00:00:00 2001
From: anicic
+This is a documentation for
+s7plcFW EPICS driver documentation
+Contents
+
+s7plcFW Intro
+s7plcFW
driver, which is a copy of s7plc
driver
+adjusted to use FETCH/WRITE communication with PLC, instead of SEND/RECEIVE.
+
+Besides the
+
+
+there should be no other differences.
+s7plcFWConfigure
function"s7plcFW stat2"
)
+The following description is a copy of s7plc
documentation.
+Only change is regarding the three above mentioned differences.
+
+
+
+NOTE:
+ FETCH/WRITE mechanism can do transfers only with even number of bytes.
+ Any record writting even number of bytes, will force the other byte of the same 16bit WORD to be written, too,
+ at the beginning and at the end of the block beeing written.
+
+
+This driver is intended to connect a Siemens S7 PLC (programmable +logic controller) via TCP/IP to an EPICS IOC. 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 +Damir +Anicic (SLS) <damir.anicic@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. +
+ + ++In the IOC startup script, the s7plcFW driver needs to be configured: +
+
+
+s7plcFWConfigure (PLCname, IPaddr, fetchInfo, writeInfo,
+bigEndian, recvTimeout, recvDelay, outIOintDelay)
+
+
+PLCname
is an arbitrary symbolic name for the PLC running
+a pair of server TCP sockets on IPaddr:fetchPort
and IPaddr:writePort
.
+The records reference the PLC with this name in their INP
or
+OUT
link. PLCname
must not contain the
+slash character (/
).
+
+IPaddr
is TCP/IP address of the PLC (in dotted notation, like: 192.168.1.10)
+
+fetchInfo
and writeInfo
are the string parameters,
+containing the
+"fetchPort,fetchOrg,fetchDb,fetchOffsetInDb,fetchSizeOfDb"
+and
+"writePort,writeOrg,writeDb,writeOffsetInDb,writeSizeOfDb"
.
+
+fetchPort and writePort come in pairs. Usualy starting at 2000,2001.
+
+Offsets and Sizes are in bytes and must be even numbers
. Offset will usualy be zero, but one does not neccessarilly have to start at the beginning of Db. The size is number of bytes to fetch or write starting from given offset - it does not have to go to the end of Db and it should never exceed the size of Db.
+
+
+If any of Port, Org, Db or Size are zero or if Offset or Size are not even numbers, the info is declared invalid.
+fetchInfo should not be invalid, but invalid writeInfo is allowed, but the writting will be disabled.
+
+bigEndian
defines the Byte order of the PLC. If
+this is 1
, the IOC expects the PLC to send and receive any
+multibyte PV (word, float, etc) most significant byte first. If it is
+0
, the data is least significant byte first. This is independent
+of the byte order of the IOC.
+
+recvTimeout
is the time in milliseconds, that IOC will wait for data. If exceeded the IOC will close the connection and
+try to reopen it after a few seconds. recvTimeout
should be big enough, not to get frequent disconnects.
+
+One, two, or even more seconds is OK. It is anyhow important only in cases when something goes wrong.
+
+recvDelay
is the IOC polling delay for getting new data (fetch), in milliseconds.
+The frequency of getting the data will be smaller than 1 / recvDelay
,
+because data receiving time is not 0. So, the real data reading frequency would be 1 / (recvDelay + dataTransferTime)
+
+The outIOintDelay
is replacement for sendInterval
of the s7plc
driver.
+s7plcFW
driver sends written data immediately. The outIOintDelay
is added to provide
+interrupt based processing of output records (SCAN="I/O intr"
) as used in s7plc
driver.
+
+
+
+s7plcFWConfigure("VakuumPLC-10", "192.168.1.10", "2000,1,50,0,1000", "2001,1,40,0,50", 0, 1000, 200, 1000)
+
+
+In the vxWorks target shell, PLCname
,
+IPaddr
, fetchInfo
and writeInfo
must be quoted. In the iocsh, quotes are
+optional.
+
+The variable s7plcFWDebug
can 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 only
+ 0: 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, s7plcFWDebug
can be set with
+s7plcFWDebug=level
+
+In the iocsh use
+var s7plcFWDebug level
+
+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 DTYP
is "s7plcFW"
. If the record processes when
+the PLC is not connected (off, down, unreachable), the record raises an
+alarm with SEVR="INVALID"
and STAT="CONN"
.
+
+There are also two connection statuses supported for bi. The
+DTYP
are "s7plcFW stat"
for fetch and "s7plcFW stat2"
for write. This records do not
+raise an alarm when the PLC is disconnected. It just changes to
+0
state 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 INP
or OUT
link is
+
+
+ "@PLCname/offset T=type L=low H=high B=bit"
+
+
+Not all parameters T
, L
, H
, and
+B
are required for each record type and parameters equal to the
+default value may be omitted. The default values depend on the record type.
+
+PLCname
is the PLC name as defined by
+s7plcFWConfigure
in the startup script.
+
+offset
is 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 like 20+3+2
.
+
+T=type
defines 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 is T=INT16
for most record types.
+L=low
and H=high
are used in analog
+input and output records if LINR
is set to "LINEAR"
+to convert analog values to integer values and back. They define the raw
+values which correspond to EGUL
and EGUF
,
+respectively.
+Analog output records will never write integer values lower than
+L
or higher than H
. If necessary, the raw output
+value is truncated to the nearest limit. The default values for
+L
and H
depend on T
.
+
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
, L
means length, not low.
+The default value is the length of the VAL
field.
+In the case of the stringin and stringout records, this is 40 (including
+the terminating null byte).
+
+B=bit
is only used for bi and bo records to define the
+bit number within the data byte, word, or doubleword (depending on
+T
). 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, use T=BYTE
to 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 interruptAccept
has been set TRUE
at the
+end of iocInit
. All records with PINI
set to
+"YES"
have already been processed by that time. The driver
+does not change the VAL
field of any output record at
+initialisation. Thus, auto save and restore can be used in combination with
+PINI="YES"
.
+
+record (bi, "$(RECORDNAME):ConnStatusFetch") { + field (DTYP, "S7plcFW stat") + field (INP, "@$(PLCNAME)") + field (ZNAM, "Disconnected") + field (ONAM, "Connected") + field (SCAN, "I/O Intr") +} +record (bi, "$(RECORDNAME):ConnStatusWrite") { + field (DTYP, "S7plcFW stat2") + field (INP, "@$(PLCNAME)") + field (ZNAM, "Disconnected") + field (ONAM, "Connected") + 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. +
+ + ++ record (ai, "$(RECORDNAME)") { + field (DTYP, "s7plcFW") + field (INP, "@$(PLCNAME)/$(OFFSET) T=$(T) L=$(L) H=$(H)") + field (SCAN, "I/O Intr") + field (LINR, "Linear") + field (EGUL, "$(MINVAL)") + field (EGUF, "$(MAXVAL)") + } + + record (ai, "$(RECORDNAME)") { + field (DTYP, "s7plcFW") + field (INP, "@$(PLCNAME)/$(OFFSET) T=$(T)") + field (SCAN, "I/O Intr") + } ++
+Default type is T=INT16
.
+Defaults for L
and H
depend
+on T
(see table above).
+
+If T
is an integer type, the PV is read into
+RVAL
. If LINR
is set to "LINEAR"
,
+then the record support converts RVAL
to VAL
+so that RVAL=L
converts to VAL=EGUL
and
+RVAL=H
converts to VAL=EGUF
.
+
+VALtemp=(RVAL-L)*(EGUF-EGUL)/(H-L)+EGUL
+
+After this conversion, VALtemp
is still
+subject to scaling and smoothing.
+
+VAL=(VALtemp*ASLO+AOFF)*(1-SMOO)+VALold*SMOO
.
+
+If T=FLOAT
or T=DOUBLE
,
+the PV is read directly into VAL
and L
,
+H
, EGUL
and EGUF
are 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=STRING
is not valid for ai records.
+
+ record (ao, "$(RECORDNAME)") { + field (DTYP, "s7plcFW") + field (OUT, "@$(PLCNAME)/$(OFFSET) T=$(T) L=$(L) H=$(H)") + field (LINR, "Linear") + field (PINI, "YES") + field (EGUL, "$(MINVAL)") + field (EGUF, "$(MAXVAL)") + } + + record (ao, "$(RECORDNAME)") { + field (DTYP, "s7plcFW") + field (OUT, "@$(PLCNAME)/$(OFFSET) T=$(T)") + field (PINI, "YES") + } ++
+Default type is T=INT16
.
+Defaults for L
and H
depend
+on T
(see table above).
+
+If T
is an integer type, RVAL
is
+written to the PV. If LINR
is set to "LINEAR"
,
+then the record support first scales OVAL
.
+
+OVALtemp=(OVAL-AOFF)/ASLO
+
+After that, the value is converted to RVAL
so that
+OVALtemp=EGUL
converts to RVAL=L
and
+OVALtemp=EGUF
converts to RVAL=H
.
+
+RVAL=(OVALtemp-EGUL)*(H-L)/(EGUF-EGUL)+L
+
+If RVAL
is higher than H
or lower than
+L
, the value is truncated to the nearest limit.
+
+If T=FLOAT
or T=DOUBLE
,
+OVAL
is written directly to the PV. L
,
+H
, EGUL
and EGUF
are ignored.
+The device support emulates scaling which is otherwise done by the
+record support during conversion.
+
+PV=(OVAL-AOFF)/ASLO
+
+T=STRING
is not valid for ao records.
+
+ record(bi, "$(NAME)") { + field (DTYP, "s7plcFW") + field (INP, "@$(PLCNAME)/$(OFFSET) T=$(T) B=$(B)") + field (SCAN, "I/O Intr") + } ++
+Default type is T=INT16
. Default bit is B=0
.
+
+Depending on T
, B
can 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, use T=BYTE
to avoid all byte order problems when
+handling single bits.
+
+The PV is read to RVAL
and masked with
+2B
.
+VAL
is 1 if RVAL
is not 0.
+
+RVAL=PV&(1<<B); VAL=(RVAL!=0)?1:0
+
+T=STRING
, T=FLOAT
or T=DOUBLE
are not
+valid for bo records. Signed and unsigned types are equivalent.
+
+ record(bo, "$(NAME)") { + field (DTYP, "s7plcFW") + field (OUT, "@$(PLCNAME)/$(OFFSET) T=$(T) B=bit") + field (PINI, "YES") + } ++
+Default type is T=INT16
. Default bit is B=0
.
+
+Depending on T
, B
can 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, use T=BYTE
to avoid all byte order problems when
+handling single bits.
+
+If VAL
is not 0, then RVAL
is set to
+2B
, else RVAL
is 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=FLOAT
or T=DOUBLE
are not
+valid for bo records. Signed and unsigned types are equivalent.
+
+ record(mbbi, "$(NAME)") { + field (DTYP, "s7plcFW") + 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 by SHFT
bits
+and masked with NOBT
bits. Valid values for NOBT
+and SHFT
depend on T
:
+NOBT
+SHFT
must 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=FLOAT
or T=DOUBLE
are not
+valid for mbbi records. Signed and unsigned types are equivalent.
+
+ record(mbbo, "$(NAME)") { + field (DTYP, "s7plcFW") + 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 NOBT
bits, shifted left by
+SHFT
bits and written to the PV. Valid values for
+NOBT
and SHFT
depend on T
:
+NOBT
+SHFT
must 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 NOBT
bits 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=FLOAT
or T=DOUBLE
are not
+valid for mbbo records. Signed and unsigned types are equivalent.
+
+ record(mbbiDirect, "$(NAME)") { + field (DTYP, "s7plcFW") + 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 by SHFT
+bits and masked with NOBT
bits (see mbbi).
+Valid values for NOBT
and SHFT
depend
+on T
: NOBT
+SHFT
must
+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=FLOAT
or T=DOUBLE
are not
+valid for mbbiDirect records. Signed and unsigned types are equivalent.
+
+ record(mbboDirect, "$(NAME)") { + field (DTYP, "s7plcFW") + 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 NOBT
bits, shifted left by SHFT
+bits and written to the PV (see mbbo). Valid values for
+NOBT
and SHFT
depend on T
:
+NOBT
+SHFT
must 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 NOBT
bits 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=FLOAT
or T=DOUBLE
are not
+valid for mbboDirect records. Signed and unsigned types are equivalent.
+
+ record(longin, "$(NAME)") { + field (DTYP, "s7plcFW") + 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=FLOAT
or T=DOUBLE
are not
+valid for longin records.
+
+ record(longout, "$(NAME)") { + field (DTYP, "s7plcFW") + 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
+of VAL
are written to the PV.
+
+T=STRING
, T=FLOAT
or T=DOUBLE
are not
+valid for longout records.
+
+ record(stringin, "$(NAME)") { + field (DTYP, "s7plcFW") + field (INP, "@$(PLCNAME)/$(OFFSET) L=$(LENGTH)") + field (SCAN, "I/O Intr") + } ++
+Default and only valid type is T=STRING
.
+Default length is L=40
.
+
+L
bytes are read from the PV to VAL
and null
+terminated. Thus, the effective string length is maximal
+L
-1 bytes.
+
+ record(stringout, "$(NAME)") { + field (DTYP, "s7plcFW") + field (OUT, "@$(PLCNAME)/$(OFFSET) L=$(LENGTH)") + field (PINI, "YES") + } ++
+Default and only valid type is T=STRING
.
+Default length is L=40
.
+
+L
bytes are written from VAL
to the PV.
+If the actual string length of VAL
is shorter than
+L
, the remaining space is filled with null bytes. If
+it is longer than L
, the string is truncated and not
+null terminated
+
+ record(waveform, "$(NAME)") { + field (DTYP, "s7plcFW") + field (INP, "@$(PLCNAME)/$(OFFSET)") + field (SCAN, "I/O Intr") + field (NELM, "$(NUMBER_OF_ELEMENTS)") + field (FTVL, "$(DATATYPE)") + } ++
+NELM
elements are read from the PV to VAL
.
+
+The default type depends on FTVL
. For example
+FTVL=LONG
results in T=INT32
.
+T
and FTVL
must match but can differ
+in signedness. In most cases, better just specify FTVL
and
+leave T
to the default.
+
+If T=STRING
, FTVL
must be "CHAR"
or
+"UCHAR"
. L=length
can be specified but
+defaults to and must not exceed NELM
.
+If L
is less than NELM
, the
+remaining elements are left untouched.
+
+FTVL="STRING"
is not supported.
+
+The special type T=TIME
is supported for
+waveforms records only. FTVL
must be
+"CHAR"
or "UCHAR"
and NELM
should 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
.
+
+ record(calcout, "$(NAME)") { + field (DTYP, "s7plcFW") + field (OUT, "@$(PLCNAME)/$(OFFSET) T=$(T) L=$(L) H=$(H)") + field (PINI, "YES") + } ++
+Default type is T=INT16
.
+Defaults for L
and H
depend
+on T
(see table above).
+
+OVAL
(the result of CALC
or OCAL
,
+depending on DOPT
) is written to the PV. If
+T
is an integer type, the value is truncated to an
+integer and compared to L
and H
.
+If OVAL
is lower than L
or higher than
+H
, it is truncated to the nearest limit.
+
+If T=FLOAT
or T=DOUBLE
,
+OVAL
is written to the PV directly without any conversion.
+
+T=STRING
is not valid for calcout records.
+
+To use this device support with calcout records, you need EPICS R3.14. +
+ + ++Device support for other record types can be written with calls to the +following driver functions: +
+
+
+s7plcFWStation* s7plcFWOpen (char* PLCname);
+
+
+
+int s7plcFWRead (s7plcFWStation* station,
+unsigned int offset, unsigned int dlen,
+void* pdata);
+
+
+
+int s7plcFWReadArray (s7plcFWStation* station,
+unsigned int offset, unsigned int dlen,
+unsigned int nelem, void* pdata);
+
+
+
+int s7plcFWWrite (s7plcFWStation* station,
+unsigned int offset, unsigned int dlen,
+void* pdata);
+
+
+
+int s7plcFWWriteMasked (s7plcFWStation* station,
+unsigned int offset, unsigned int dlen,
+void* pdata, void* pmask);
+
+
+
+int s7plcFWWriteArray (s7plcFWStation* station,
+unsigned int offset, unsigned int dlen,
+unsigned int nelem, void* pdata);
+
+
+
+int s7plcFWWriteMaskedArray (s7plcFWStation* station,
+unsigned int offset, unsigned int dlen,
+unsigned int nelem, void* pdata, void* pmask);
+
+
+The functions s7plcFWRead()
, s7plcFWWrite()
,
+s7plcFWWriteMasked()
, and s7plcFWWriteArray()
+are actually macros for
+s7plcFWReadArray()
and s7plcFWWriteMaskedArray()
with
+nelem=1
and/or mask=NULL
.
+
+station
is a handle previously obtained by a call to
+s7plcFWOpen()
.
+
+offset
is the byte offset of the PV relative
+to the beginning to the data block.
+
+dlen
is 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
+the dlen
bytes is swapped by the driver.
+
+nelem
is the number of elements in an array.
+
+pdata
is a pointer to a buffer of
+nelem
*dlen
bytes.
+PVs are read to or written from this buffer.
+
+mask
is a pointer to a bitmask of dlen
bytes.
+Only those bits are changed where the mask contains 1 bits. All other bits
+remain untouched.
+
+For strings, use array functions with dlen=1
and
+nelem=buffersize
.
+