Questa funzione gestisce la scrittura/lettura sul bus I2C di estensione. L’utilizzo di questa funzione permette di gestire qualsiasi componente I2C connesso al bus di estensione. Chiamando la funzione con WrBytes e RdBytes a zero, esegue un node check tornando TRUE se il nodo I2c esiste.
Attenzione, il bus I2C è utilizzato per l’accesso ai moduli di estensione per non rallentarne l’accesso si consiglia di eseguire comandi I2C non più lunghi di 4 bytes in scrittura e lettura. Nel caso serva gestire più bytes si consiglia di spezzare il comando in più comandi consecutivi.
Approfondimenti
- In questo topic un semplice programma di gestione I/O expander in linguaggio FBD.
- In questo topic un semplice programma di gestione PIO I2C.
- In questo topic un programma di gestione display alfanumerico.
- In questo topic indicazioni su come gestire un display I2C SainSmart.
- In questo topic acquisizione di sensore pirometrico MEMS Thermal Sensors D6T della Omron.
Descrizione
Address (BYTE) Indirizzo dispositivo I2C range da 16#00 a 16#7F.
WrBytes (USINT) Numero di bytes dati da scrivere. 0 se solo lettura.
WrBuffer (PVOID) Indirizzo buffer memoria che contiene i dati da scrivere, eNULL se solo lettura.
RdBytes (USINT) Numero di bytes dati da leggere. 0 se solo scrittura.
RdBuffer (PVOID) Indirizzo buffer memorizzazione dati letti, eNULL se solo scrittura.
La funziona ritorna un BOOL, FALSE: Errore esecuzione, TRUE: Funzione eseguita correttamente.

Verifica dispositivo I2C
Per verificare se un dispositivo con un certo indirizzo I2C è connesso al bus di espansione del sistema è possibile utilizzare la funzione SysI2CWrRd passando l’indirizzo I2C da verificare con gli altri parametri non assegnati.
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;
Esempi
ST_SysI2CWrRd: Viene eseguita l’acquisizione del valore di temperatura e di umidità da un sensore SHT30-DIS della Sensirion come questo connesso al bus I2C di un sistema SlimLine. Non viene eseguito il controllo sul CRC dei valori acquisisti. In questo articolo si trova la stessa gestione realizzata con il FB di gestione bus I2C.
ST_ScanI2CDevices: Collegandosi in telnet alla porta indicata viene eseguito la scansione di tutti i possibili indirizzi I2C e ritornato l’elenco dei dispositivi connessi al bus I2C di espansione.
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) < TO_UDINT(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(BytesToWord(I2CRead[0], I2CRead[1]))/65535.0));
Humidity:=100.0*(TO_REAL(BytesToWord(I2CRead[3], I2CRead[4]))/65535.0);
CaseNr:=0; //Program case
END_CASE;
// [End of file]
LogicLab (Ptp116, ST_ScanI2CDevices)
PROGRAM ST_ScanI2CDevices
VAR
CaseNr : USINT; (* Program case *)
I2CAddress : BYTE; (* I2C address *)
Fp : eFILEP; (* File pointer *)
SOut : STRING[ 128 ]; (* String output *)
TCPServer : SysTCPServer; (* TCP server *)
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:
eTO_JUNK(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(I2CAddress, 0, eNULL, 0, eNULL)) THEN
eTO_JUNK(SysCVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%s '), STRING_TYPE, ADR('--')));
ELSE
eTO_JUNK(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
eTO_JUNK(SysCVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%s'), STRING_TYPE, ADR('$r$n')));
eTO_JUNK(Sysfwrite(ADR(SOut), TO_INT(LEN(SOut)), 1, Fp));
eTO_JUNK(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;
eTO_JUNK(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;
eTO_JUNK(SysFOBfFlush(Fp)); //Flush the socket data
Fp:=FClose(Fp); //File pointer
CaseNr:=0; //Program case
END_CASE;
// [End of file]