modasciiReceive (Functionblock)

Top  Previous  Next

Architecture:

X32 / NX32 / NX32L

Device support:

All devices with RS485

Firmware version:

4.00 / 1.00.00


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;
 
  // 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 := modasciiSend(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 modasciiWaitData(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 := 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;
    // Set next reading
     linsec := clockNow() + 5;
  END_IF;
END;
END_PROGRAM;