modbusReceive (Functionblock)

Top  Previous  Next

Architecture:

X32 / NX32 / NX32L

Firmware version:

1.50 / 1.00.00


This function will read a package that has been received from a MODBUS connection.

While it is possible to use modbusReceive to continuously poll for received packages, it is recommended to only poll after modbusWaitData 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.

 

tid : DINT

The transaction ID of the package. This parameter is only used by MODBUS TCP connections.

 

status : INT

0

- Success.

-1

- Not a valid MODBUS connection ID.

-3

- No data received.

-7

- Data received is not a valid MODBUS message.

 

Declaration:

FUNCTION_BLOCK modbusReceive;
VAR_INPUT
   net_id  : INT;
   frame   : PTR;
   maxsize : INT;
END_VAR;
VAR_OUTPUT
   unit_id : INT;
   size    : INT;
   status  : INT;
   tid     : DINT;
END_VAR;

 

 

Example:

INCLUDE rtcu.inc
 
VAR
   mbNet : INT;
   mbRcv : modbusReceive;
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;
 
   // Check length
   IF length < 1 OR length > 32 THEN
      status := 1;
      RETURN;
   END_IF;
   IF index < 1 THEN
      status := 2;
      RETURN;
   END_IF;
 
   // Build command
   buf[1] := 16#02;
   setINT(adr := ADDR(buf[2]), v := index - 1);
   setINT(adr := ADDR(buf[4]), v := length);
 
   // Send command
   rc := modbusSend(net_id := net_id, unit_id := unit_id, frame := ADDR(buf), size := 5);
   IF rc <> 0 THEN
      status := 3;
      RETURN;
   END_IF;
 
   // Wait for reply
   IF NOT modbusWaitData(net_id := net_id, timeout := 5000) THEN
      status := 4;
      RETURN;
   END_IF;
 
   // Read reply
   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;
 
   // Parse reply
   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 := modbusOpen(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;
      // Set next reading
      linsec := clockNow() + 5;
   END_IF;
END;
END_PROGRAM;