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.
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.
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
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]