SysI2CWrRd, writes / reads on I2C extension bus

List

This page is part of the IEC 61131-3 Programming Manual. Go to the index.

This function manages the write / read on the extension I2C bus. Using this function allows you to manage any I2C component connected to the extension bus. Calling the function with WrBytes and RdBytes set to zero, it performs a node check returning TRUE if the I2c node exists.

Attention, the I2C bus is used to access the extension modules in order not to slow down access, it is recommended to execute I2C commands no longer than 4 bytes in writing and reading. If you need to manage more bytes, it is advisable to split the command into several consecutive commands.

information circle

Function

CODESYS: Not available

LogicLab: eLLabXUnified12Lib

Description

Address (BYTE) I2C device address range from 16 # 00 to 16 # 7F.
WrBytes (USINT) Number of data bytes to write. 0 if read only.
WrBuffer (PVOID) Memory buffer address that contains the data to be written, eNULL if only read.
RdBytes (USINT) Number of data bytes to read. 0 if writing only.
RdBuffer (PVOID) Buffer address for storing read data, eNULL if only writing.

The function returns a BOOL, FALSE: Execution error, TRUE: Function performed correctly.

Image F SysI2CWrRd
Check I2C device

To check if a device with a certain I2C address is connected to the system expansion bus, you can use the function SysI2CWrRd passing the I2C address to be checked with the other unassigned parameters.

    IF (SysI2CWrRd(16#30, 0, eNULL, 0, eNULL)) THEN
        // Device with 16#30 I2C address is connected.
    ELSE
        // Device with 16#30 I2C address is not connected.
    END_IF;

Examples

How to use the examples.

ST_SysI2CWrRd: The acquisition of the temperature and humidity value is performed from a Sensirion SHT30-DIS sensor as this connected to the I2C bus of a system SlimLine. The control on the CRC of the acquired values ​​is not performed. In this article the same management is carried out with the I2C bus management FB.

ST_ScanI2CDevices: By telnet connection to the indicated port, all possible I2C addresses are scanned and the list of devices connected to the expansion I2C bus is returned.

LogicLab (Ptp116, ST_SysI2CWrRd)
PROGRAM ST_SysI2CWrRd
VAR
    CaseNr : USINT; (* Program case *)
    TimeBf : UDINT; (* Time buffer (mS) *)
    Errors : UDINT; (* Error counter *)
    Temperature : REAL; (* Temperature value (°C) *)
    Humidity : REAL; (* Humidity value (%) *)
    I2CWrite : ARRAY[0..1] OF BYTE; (* I2C write buffer *)
    I2CRead : ARRAY[0..7] OF BYTE; (* I2C read buffer *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_SysI2CWrRd"
// *****************************************************************************
// Temperature and humidity acquisistion from a Sensirion SHT30-DIS.
// -----------------------------------------------------------------------------

    // -------------------------------------------------------------------------
    // PROGRAM CASES
    // -------------------------------------------------------------------------
    // Program cases management.

    CASE (CaseNr) OF

        // ---------------------------------------------------------------------
        // Conversion command "Single Shot Mode high repeatability" clock
        // streching disabled.

        0:
        I2CWrite[0]:=16#24; //MSB
        I2CWrite[1]:=16#00; //LSB
        IF NOT(SysI2CWrRd(16#44, 2, ADR(I2CWrite), 0, eNULL)) THEN
            Errors:=Errors+1; //Error counter
            CaseNr:=0; //Program case
            RETURN;
        END_IF;

        // Save time to wait

        TimeBf:=SysTimeGetMs(); //Time buffer (mS)
        CaseNr:=CaseNr+1; //Program case

        // ---------------------------------------------------------------------
        // Wait conversion complete (Max time oh high repeatability 15 mS).

         1:
         IF ((SysTimeGetMs()-TimeBf) < T#15ms) THEN RETURN; END_IF;

        // Read the conversion results.

        IF NOT(SysI2CWrRd(16#44, 0, eNULL, 6, ADR(I2CRead))) THEN
            Errors:=Errors+1; //Error counter
            CaseNr:=0; //Program case
            RETURN;
        END_IF;

        // Convert the acquired values.

        Temperature:=-45.0+(175.0*(TO_REAL((I2CRead[0]*256)+I2CRead[1])/65535.0));
        Humidity:=100.0*(TO_REAL((I2CRead[3]*256)+I2CRead[4])/65535.0);
        CaseNr:=0; //Program case
    END_CASE;

// [End of file]
LogicLab (Ptp116, ST_ScanI2CDevices)
PROGRAM ST_ScanI2CDevices
VAR
    i : UDINT; (* Auxiliary variable *)
    Fp : eFILEP; (* File pointer array *)
    SOut : STRING[ 128 ]; (* String output *)
    TCPServer : SysTCPServer; (* TCP server *)
    CaseNr : USINT; (* Program case *)
    I2CAddress : BYTE; (* I2C address *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_ScanI2CDevices"
// *****************************************************************************
// Opens a TCP server and when a client connect to it the extension I2C is
// scanned.
// -----------------------------------------------------------------------------

    // -------------------------------------------------------------------------
    // INITIALIZATION
    // -------------------------------------------------------------------------
    // TCPServer initialization.

    IF (SysFirstLoop) THEN
        TCPServer.FilesArr:=ADR(Fp); //Files array
        TCPServer.LocalAdd:=ADR('0.0.0.0'); //Local address
        TCPServer.LocalPort:=1120; //Local port 
        TCPServer.MaxConn:=1; //Accepted connections
        TCPServer.FlushTm:=50; //Flush time (mS)
        TCPServer.LifeTm:=15; //Life time (S)
        TCPServer.RxSize:=128; //Rx buffer size
        TCPServer.TxSize:=128; //Tx buffer size
    END_IF;

    // -------------------------------------------------------------------------
    // OBJECT EXECUTION
    // -------------------------------------------------------------------------
    // Manage the TCP server and check if a client has been connected.

    TCPServer(); //TCPServer management
    TCPServer.Enable:=TRUE; //TCPServer enable
    IF NOT(SysFIsOpen(Fp)) THEN CaseNr:=0; RETURN; END_IF;

    // -------------------------------------------------------------------------
    // PROGRAM CASES
    // -------------------------------------------------------------------------
    // Program cases management.

    CASE (CaseNr) OF

        // ---------------------------------------------------------------------
        // Init check.

        0:
        i:=SysVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('Scan I2C Bus devices%s'), STRING_TYPE, ADR('$r$n'));
        I2CAddress:=16#00; //I2C address
        CaseNr:=CaseNr+1; //Program case

        // ---------------------------------------------------------------------
        // Check if the I2C device is present.

        1:
        IF NOT(SysI2CWrRd(Address:=I2CAddress, WrBytes:=0, WrBuffer:=eNULL, RdBytes:=0, RdBuffer:=eNULL)) THEN
            i:=SysCVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%s '), STRING_TYPE, ADR('--'));
        ELSE
            i:=SysCVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%02X '), USINT_TYPE, ADR(I2CAddress));
        END_IF;

        // Increase the I2C address to check.
        
        I2CAddress:=I2CAddress+1; //I2C address

        // Every 16 addresses return the result.

        IF (MOD(I2CAddress, 16) = 0) THEN    
            i:=SysCVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%s'), STRING_TYPE, ADR('$r$n'));
            i:=Sysfwrite(ADR(SOut), TO_INT(LEN(SOut)), 1, Fp);
            i:=SysFOBfFlush(Fp); //Flush the socket data
            CaseNr:=CaseNr+1; //Program case
            RETURN;
        END_IF;

        // ---------------------------------------------------------------------
        // Waits the output buffer empty.

        2:
        IF (SysFGetOSpace(Fp) <> TO_INT(SysFGetOBfSize(Fp))) THEN RETURN; END_IF;
        i:=Sysmemset(ADR(SOut), 0, SIZEOF(SOut));

        // Check if all possible addresses has been tested.

        IF (I2CAddress < 16#80) THEN CaseNr:=CaseNr-1; RETURN; END_IF;
        i:=SysFOBfFlush(Fp); //Flush the socket data
        i:=Sysfclose(Fp); //Close socket
        CaseNr:=0; //Program case
    END_CASE;

// [End of file]
Was this article helpful?