dm_modbus Module

Abstraction layer over libmodbus, for Modbus RTU/TCP communication.

The following types and ranges are used by the Modbus protocol:

Code Range Type Function
0x 00001 – 09999 coil dm_modbus_read_bits()
1x 10001 – 19999 discrete input dm_modbus_read_input_bits()
3x 30001 – 39999 input register dm_modbus_read_input_registers()
4x 40001 – 49999 holding register dm_modbus_read_registers()

You may want to use the functions dm_to_signed() and dm_to_unsigned() available in module dm_c to convert unsigned to signed integers and vice versa.

Use Modbus function code 0x03 to read holding registers from a Modbus RTU connection:

integer               :: i, rc, s
integer(kind=u2)      :: data(2)
type(modbus_rtu_type) :: modbus

! Create Modbus RTU context and connect to device 10.
rc = dm_modbus_create(modbus    = modbus, &
                      path      = '/dev/ttyUSB0', &
                      baud_rate = TTY_B19200, &
                      byte_size = TTY_BYTE_SIZE8, &
                      parity    = TTY_PARITY_EVEN, &
                      stop_bits = TTY_STOP_BITS1)
rc = dm_modbus_connect(modbus)
rc = dm_modbus_set_slave(modbus, slave=10)

! Read and output two registers.
rc = dm_modbus_read_registers(modbus, address=50, data=data)

do i = 1, size(data)
    s = dm_to_signed(data(i))
    print '("data(", i0, ") = ", i0, " (0x", z0, ")")', i, s, s
end do

! Print the two registers as real in ABCD byte order.
print '(f12.8)', dm_modbus_get_float_abcd(data)

! Disconnect and clean-up.
call dm_modbus_close(modbus)
call dm_modbus_destroy(modbus)

In production, add additional error handling of the return codes.

References


Uses

  • module~~dm_modbus~~UsesGraph module~dm_modbus dm_modbus iso_c_binding iso_c_binding module~dm_modbus->iso_c_binding modbus modbus module~dm_modbus->modbus modbus_rtu modbus_rtu module~dm_modbus->modbus_rtu modbus_tcp modbus_tcp module~dm_modbus->modbus_tcp module~dm_c dm_c module~dm_modbus->module~dm_c module~dm_error dm_error module~dm_modbus->module~dm_error module~dm_kind dm_kind module~dm_modbus->module~dm_kind module~dm_modbus_type dm_modbus_type module~dm_modbus->module~dm_modbus_type module~dm_c->iso_c_binding module~dm_c->module~dm_kind module~dm_error->module~dm_kind module~dm_ascii dm_ascii module~dm_error->module~dm_ascii iso_fortran_env iso_fortran_env module~dm_kind->iso_fortran_env module~dm_modbus_type->module~dm_error module~dm_modbus_type->module~dm_kind module~dm_response dm_response module~dm_modbus_type->module~dm_response module~dm_string dm_string module~dm_modbus_type->module~dm_string module~dm_response->module~dm_error module~dm_response->module~dm_kind module~dm_id dm_id module~dm_response->module~dm_id module~dm_util dm_util module~dm_response->module~dm_util module~dm_string->module~dm_error module~dm_string->module~dm_kind module~dm_util->module~dm_error module~dm_util->module~dm_kind

Used by

  • module~~dm_modbus~~UsedByGraph module~dm_modbus dm_modbus module~dmpack dmpack module~dmpack->module~dm_modbus

Interfaces

public interface dm_modbus_create

Generic function to create Modbus RTU or TCP context.

  • public function dm_modbus_create_rtu(modbus, path, baud_rate, byte_size, parity, stop_bits) result(rc)

    Creates a new Modbus RTU context.

    The function returns the following error codes:

    • E_INVALID if a given argument is invalid.
    • E_MODBUS if no Modbus context could be created.

    Arguments

    Type IntentOptional Attributes Name
    type(modbus_rtu_type), intent(out) :: modbus

    Modbus RTU type.

    character(len=*), intent(in) :: path

    Device path.

    integer, intent(in) :: baud_rate

    Baud rate enumerator (TTY_B*).

    integer, intent(in) :: byte_size

    Byte size enumerator (TTY_BYTE_SIZE*).

    integer, intent(in) :: parity

    Parity enumerator (TTY_PARITY_*).

    integer, intent(in) :: stop_bits

    Stop bits enumerator (TTY_STOP_BITS*).

    Return Value integer

  • public function dm_modbus_create_tcp(modbus, address, port) result(rc)

    Creates a new Modbus TCP context.

    The function returns the following error codes:

    • E_INVALID if the given arguments are invalid.
    • E_MODBUS if no Modbus context could be created.

    Arguments

    Type IntentOptional Attributes Name
    type(modbus_tcp_type), intent(out) :: modbus

    Modbus TCP type.

    character(len=*), intent(in) :: address

    IPv4 address.

    integer, intent(in) :: port

    Port number.

    Return Value integer


Derived Types

type, public ::  modbus_type

Opaque Modbus RTU/TCP context type.

type, public, extends(modbus_type) ::  modbus_rtu_type

Opaque Modbus RTU context type.

type, public, extends(modbus_type) ::  modbus_tcp_type

Opaque Modbus TCP context type.


Functions

public function dm_modbus_connect(modbus) result(rc)

Connects to Modbus RTU/TCP device.

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

Return Value integer

public function dm_modbus_create_rtu(modbus, path, baud_rate, byte_size, parity, stop_bits) result(rc)

Creates a new Modbus RTU context.

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_rtu_type), intent(out) :: modbus

Modbus RTU type.

character(len=*), intent(in) :: path

Device path.

integer, intent(in) :: baud_rate

Baud rate enumerator (TTY_B*).

integer, intent(in) :: byte_size

Byte size enumerator (TTY_BYTE_SIZE*).

integer, intent(in) :: parity

Parity enumerator (TTY_PARITY_*).

integer, intent(in) :: stop_bits

Stop bits enumerator (TTY_STOP_BITS*).

Return Value integer

public function dm_modbus_create_tcp(modbus, address, port) result(rc)

Creates a new Modbus TCP context.

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_tcp_type), intent(out) :: modbus

Modbus TCP type.

character(len=*), intent(in) :: address

IPv4 address.

integer, intent(in) :: port

Port number.

Return Value integer

public function dm_modbus_error_message() result(message)

Returns error message from libmodbus.

Arguments

None

Return Value character(len=:), allocatable

public function dm_modbus_flush(modbus) result(rc)

Flushes non-transmitted data.

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

Return Value integer

public function dm_modbus_get_float(data, order, error) result(value)

Returns real value from two registers of given byte order in argument value. The argument byte order must be one of the following:

Read more…

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(inout) :: data(2)

Registers to convert.

integer, intent(in) :: order

Byte order.

integer, intent(out), optional :: error

Error code.

Return Value real

public function dm_modbus_get_float_abcd(data) result(value)

Returns real value from two registers in ABCD byte order.

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(inout) :: data(2)

Registers to convert.

Return Value real

public function dm_modbus_get_float_badc(data) result(value)

Returns real value from two registers in BADC byte order.

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(inout) :: data(2)

Registers to convert.

Return Value real

public function dm_modbus_get_float_cdab(data) result(value)

Returns real value from two registers in CDAB byte order.

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(inout) :: data(2)

Registers to convert.

Return Value real

public function dm_modbus_get_float_dcba(data) result(value)

Returns real value from two registers in DCBA byte order.

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(inout) :: data(2)

Registers to convert.

Return Value real

public pure elemental function dm_modbus_get_high_byte(data) result(value)

Returns high byte from 2-byte integer.

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(in) :: data

Register data.

Return Value character(len=1)

public pure function dm_modbus_get_int32_from_int16(data) result(value)

Returns 4-byte integer from two 2-byte registers.

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(in) :: data(2)

Register data.

Return Value integer(kind=i4)

public pure function dm_modbus_get_int64_from_int16(data) result(value)

Returns 8-byte integer from four 2-byte registers.

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(in) :: data(4)

Register data.

Return Value integer(kind=i8)

public pure elemental function dm_modbus_get_low_byte(data) result(value)

Returns low byte from 2-byte integer.

Arguments

Type IntentOptional Attributes Name
integer(kind=u2), intent(in) :: data

Register data.

Return Value character(len=1)

public function dm_modbus_get_serial_mode(modbus, mode) result(rc)

Gets the current Modbus RTU serial mode (RS-232 or RS-485).

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_rtu_type), intent(inout) :: modbus

Modbus RTU type.

integer, intent(out) :: mode

Modbus RTU mode (MODBUS_RTU_RS232, MODBUS_RTU_RS485).

Return Value integer

public function dm_modbus_get_slave(modbus, slave) result(rc)

Gets current slave number in the Modbus context.

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(out) :: slave

Device id.

Return Value integer

public function dm_modbus_read_bits(modbus, address, data, n) result(rc)

Reads many input bits from address. The size of argument data determines the number of bits to read, unless optional argument n is passed. The function uses the Modbus function code 0x01 (read coil status).

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to read from.

integer(kind=u1), intent(inout) :: data(:)

Bits.

integer, intent(inout), optional :: n

Number of registers to read on input, number of registers read on output.

Return Value integer

public function dm_modbus_read_float(modbus, address, value, order) result(rc)

Reads 4-byte real from input or holding register, depending on the address, and returns result in value.

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to read from.

real(kind=4), intent(out) :: value

Value read from register.

integer, intent(in) :: order

Byte order.

Return Value integer

public function dm_modbus_read_input_bits(modbus, address, data, n) result(rc)

Reads many input bits from address. The size of argument data determines the number of bits to read, unless optional argument n is passed. The function uses the Modbus function code 0x02 (read input status).

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to read from.

integer(kind=u1), intent(inout) :: data(:)

Bits.

integer, intent(inout), optional :: n

Number of registers to read on input, number of registers read on output.

Return Value integer

public function dm_modbus_read_input_registers(modbus, address, data, n) result(rc)

Reads many registers from address. The size of argument data determines the number of registers to read, unless optional argument n is passed. The function uses the Modbus function code 0x04 (read input registers).

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to read from.

integer(kind=u2), intent(inout) :: data(:)

Register values (unsigned).

integer, intent(inout), optional :: n

Number of registers to read on input, number of registers read on output.

Return Value integer

public function dm_modbus_read_int16(modbus, address, value) result(rc)

Reads 2-byte signed integer from input or holding register, depending on the address, and returns result in value.

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to read from.

integer(kind=i2), intent(out) :: value

Value read from register.

Return Value integer

public function dm_modbus_read_int32(modbus, address, value) result(rc)

Reads 4-byte signed integer from input or holding register, depending on the address, and returns result in value.

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to read from.

integer(kind=i4), intent(out) :: value

Value read from register.

Return Value integer

public function dm_modbus_read_registers(modbus, address, data, n) result(rc)

Reads many registers from address. The size of argument data determines the number of registers to read, unless optional argument n is passed. The function uses the Modbus function code 0x03 (read holding registers).

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to read from.

integer(kind=u2), intent(inout) :: data(:)

Register values (unsigned).

integer, intent(inout), optional :: n

Number of registers to read on input, number of registers read on output.

Return Value integer

public function dm_modbus_read_uint16(modbus, address, value) result(rc)

Reads 2-byte unsigned integer from input or holding register, depending on the address, and returns result in value. Stores the 2-byte unsigned value in a 4-byte signed integer.

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to read from.

integer(kind=i4), intent(out) :: value

Value read from register.

Return Value integer

public function dm_modbus_read_uint32(modbus, address, value) result(rc)

Reads 4-byte unsigned integer from input or holding register, depending on the address, and returns result in value. Stores the 4-byte unsigned value in a 8-byte signed integer.

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to read from.

integer(kind=i8), intent(out) :: value

Value read from register.

Return Value integer

public function dm_modbus_set_debug(modbus, debug) result(rc)

Sets debug flag of the Modbus context. Returns E_MODBUS on error.

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

logical, intent(in) :: debug

Enable debug mode.

Return Value integer

public function dm_modbus_set_serial_mode(modbus, mode) result(rc)

Sets the Modbus RTU serial mode to RS-232 or RS-485. This API function is only supported on Linux kernels 2.6.28 onwards.

Read more…

Arguments

Type IntentOptional Attributes Name
type(modbus_rtu_type), intent(inout) :: modbus

Modbus RTU type.

integer, intent(in) :: mode

Modbus RTU mode (MODBUS_RTU_RS232, MODBUS_RTU_RS485).

Return Value integer

public function dm_modbus_set_slave(modbus, slave) result(rc)

Sets slave number in the Modbus context.

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: slave

Device id.

Return Value integer

public function dm_modbus_version(name) result(version)

Returns libmodbus version as allocatable string.

Arguments

Type IntentOptional Attributes Name
logical, intent(in), optional :: name

Add prefix libmodbus/.

Return Value character(len=:), allocatable

Version string.

public function dm_modbus_write_int16(modbus, address, value) result(rc)

Writes 2-byte signed integer to address.

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to write to.

integer(kind=i2), intent(in) :: value

Value to write.

Return Value integer

public function dm_modbus_write_int32(modbus, address, value) result(rc)

Writes 4-byte signed integer to address.

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to write to.

integer(kind=i4), intent(in) :: value

Value to write.

Return Value integer

public function dm_modbus_write_register(modbus, address, data) result(rc)

Writes register to address. The function uses the Modbus function code 0x06 (preset single register).

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to write to.

integer(kind=u2), intent(in) :: data

Register value (unsigned).

Return Value integer

public function dm_modbus_write_registers(modbus, address, data, n) result(rc)

Writes many registers to address. The size of argument data determines the number of registers to write, unless optional argument n is passed. The function uses the Modbus function code 0x10 (preset multiple registers).

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to write to.

integer(kind=u2), intent(inout) :: data(:)

Register values (unsigned).

integer, intent(inout), optional :: n

Number of registers to write on input, number of registers written on output.

Return Value integer

public function dm_modbus_write_uint16(modbus, address, value) result(rc)

Writes 2-byte unsigned integer to address. The unsigned value must be passed in a 4-byte signed integer.

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to write to.

integer(kind=i4), intent(in) :: value

Value to write.

Return Value integer

public function dm_modbus_write_uint32(modbus, address, value) result(rc)

Writes 4-byte unsigned integer to address. The unsigned value must be passed in a 8-byte signed integer.

Read more…

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

integer, intent(in) :: address

Address to write to.

integer(kind=i8), intent(in) :: value

Value to write.

Return Value integer


Subroutines

public subroutine dm_modbus_close(modbus)

Closes the Modbus RTU/TCP connection.

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCPtype.

public subroutine dm_modbus_destroy(modbus)

Destroys the Modbus RTU/TCP context.

Arguments

Type IntentOptional Attributes Name
class(modbus_type), intent(inout) :: modbus

Modbus RTU/TCP type.

public pure subroutine dm_modbus_set_int32_to_int16(value, data)

Sets 4-byte integer to two 2-byte registers.

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: value

Value to convert.

integer(kind=u2), intent(out) :: data(2)

Returned register data.

public pure subroutine dm_modbus_set_int64_to_int16(value, data)

Sets 8-byte integer to four 2-byte registers.

Arguments

Type IntentOptional Attributes Name
integer(kind=i8), intent(in) :: value

Value to convert.

integer(kind=u2), intent(out) :: data(4)

Returned register data.

public subroutine dm_modbus_set_float(value, data, order, error)

Sets real value to registers of given byte order. The argument order must be one of the following:

Read more…

Arguments

Type IntentOptional Attributes Name
real, intent(in) :: value

Real value to set.

integer(kind=u2), intent(out) :: data(2)

Registers to write to.

integer, intent(in) :: order

Byte order.

integer, intent(out), optional :: error

Error code.

public subroutine dm_modbus_set_float_abcd(value, data)

Returns real value to registers in ABCD byte order.

Arguments

Type IntentOptional Attributes Name
real, intent(in) :: value

Real value to set.

integer(kind=u2), intent(out) :: data(2)

Registers to write to.

public subroutine dm_modbus_set_float_badc(value, data)

Returns real value to registers in BADC byte order.

Arguments

Type IntentOptional Attributes Name
real, intent(in) :: value

Real value to set.

integer(kind=u2), intent(out) :: data(2)

Registers to write to.

public subroutine dm_modbus_set_float_cdab(value, data)

Sets real value to registers in CDAB byte order.

Arguments

Type IntentOptional Attributes Name
real, intent(in) :: value

Real value to set.

integer(kind=u2), intent(out) :: data(2)

Registers to write to.

public subroutine dm_modbus_set_float_dcba(value, data)

Sets real value to registers in DCBA byte order.

Arguments

Type IntentOptional Attributes Name
real, intent(in) :: value

Real value to set.

integer(kind=u2), intent(out) :: data(2)

Registers to write to.