This function will read a package that has been received from a MODBUS ASCII connection.
While it is possible to use modbusReceive to continuously poll for received packages, it is recommended to only poll after modasciiWaitData has detected that a package has been received. This function is non-blocking and will therefore return immediately with the result of the operation.
Note: if the received package is too large for the receive buffer, only the part of the message that can fit the buffer is actually returned.
Input:
net_id : INT
The ID of the MODBUS connection.
frame : PTR
Address of the buffer where the received package is stored.
maxsize : INT
Maximum size of the receive buffer.
Output:
unit_id : INT
The ID of the device on the MODBUS network who sent the package.
Note: if the MODBUS connection is opened in slave mode, this will be the address of the RTCU device.
size : INT
Number of bytes received.
status : INT
0
|
- Success.
|
-1
|
- Not a valid MODBUS connection ID.
|
-3
|
- No data received.
|
Declaration:
FUNCTION_BLOCK modasciiReceive;
VAR_INPUT
net_id : INT;
frame:PTR;
maxsize:INT;
END_VAR;
VAR_OUTPUT
unit_id:INT;
size:INT;
status:INT;
END_VAR;
Example:
INCLUDE rtcu.inc
VAR
mbNet : INT;
mbRcv : modasciiReceive;
END_VAR;
FUNCTION setINT;
VAR_INPUT
adr : PTR;
v : INT;
END_VAR;
memcpy(dst := adr + 1, src := ADDR(v) , len := 1);
memcpy(dst := adr , src := ADDR(v) + 1, len := 1);
END_FUNCTION;
FUNCTION_BLOCK modbusReadDiscreteInputs;
VAR_INPUT
net_id : INT;
unit_id : INT;
index : INT;
length : INT;
END_VAR;
VAR_OUTPUT
status : INT;
size : INT;
input : ARRAY[1..32] OF BOOL;
END_VAR;
VAR
rc, i : INT;
buf : ARRAY[1..253] OF SINT;
mask : SINT;
END_VAR;
IF length < 1 OR length > 32 THEN
status := 1;
RETURN;
END_IF;
IF index < 1 THEN
status := 2;
RETURN;
END_IF;
buf[1] := 16#02;
setINT(adr := ADDR(buf[2]), v := index - 1);
setINT(adr := ADDR(buf[4]), v := length);
rc := modasciiSend(net_id := net_id, unit_id := unit_id, frame := ADDR(buf), size := 5);
IF rc <> 0 THEN
status := 3;
RETURN;
END_IF;
IF NOT modasciiWaitData(net_id := net_id, timeout := 5000) THEN
status := 4;
RETURN;
END_IF;
mbRcv(net_id := net_id, frame := ADDR(buf), maxsize := SIZEOF(buf));
IF mbRcv.status <> 0 THEN
status := 5;
RETURN;
END_IF;
IF mbRcv.unit_id <> unit_id THEN
status := 6;
RETURN;
END_IF;
IF buf[1] <> 16#02 THEN
status := 7;
RETURN;
END_IF;
mask := 1;
FOR i := 1 TO length DO
input[i] := BOOL(buf[3 + ((i - 1) / 8)] AND mask);
mask := shl8(in := mask, n := 1);
IF mask = 0 THEN mask := 1; END_IF;
END_FOR;
size := length;
status := 0;
END_FUNCTION_BLOCK;
PROGRAM ModbusExample;
VAR
dinRead : modbusReadDiscreteInputs;
linsec : DINT;
i : INT;
END_VAR;
DebugMsg(message := "Initializing...");
mbNet := modasciiOpen(port := 2, baud := 19200, parity := 0, mode := 0);
DebugFmt(message := "modbus...\1", v1 := mbNet);
BEGIN
IF clockNow() > linsec THEN
DebugMsg(message := "------------------------------");
DebugMsg(message := "Reading inputs:");
dinRead(net_id := mbNet, unit_id := 9, index := 1, length := 4);
DebugFmt(message := "-status=\1", v1 := dinRead.status);
IF dinRead.status = 0 THEN
FOR i := 1 TO dinRead.size DO
DebugFmt(message := "-input[\1]=\2", v1 := i, v2 := INT(dinRead.input[i]));
END_FOR;
END_IF;
linsec := clockNow() + 5;
END_IF;
END;
END_PROGRAM;
|