I2CBusManager, Gestione periferiche su bus I2C

List

Questa pagina fa parte del Manuale Programmazione IEC 61131-3. Vai all indice.

Questo blocco funzione gestisce periferiche con interfaccia su bus I2C, in base alla definizione di I2CMode è possibile selezionare il bus da utilizzare. Attivando Check viene verificata la presenza dispositivo I2C indirizzato in I2CAddress sul bus. Se presente sul Done sarà attivo anche Ok.

Attivando RRCmd se WrBytes e WrBuffer sono definiti, viene eseguita la scrittura di WrBytes bytes dal buffer indirizzato da WrBuffer sul dispositivo I2C indirizzato in I2CAddress. Terminata la scrittura se RdBytes e RdBuffer sono definiti viene eseguita la lettura di RdBytes bytes dal dispositivo I2C indirizzato in I2CAddress nel buffer indirizzato da RdBuffer.

Se I2CMode=1 sugli ingressi IClock ed IData vanno connessi i relativi segnali di ingresso, e sulle uscite OClock ed OData i relativi segnali di uscita del bus I2C.

Information Circle

Blocco funzione

CODESYS: Non disponibile

LogicLab: eLLabI2CDevsLib

Descrizione

SpyOn (BOOL) Se attivo permette di spiare il funzionamento della FB.
IClock (BOOL) Collegare il segnale hardware di lettura Clock da bus I2C. Se non è necessario gestire lo stretching si può lasciare scollegato. Si utilizza solo se I2CMode<>0.
IData (BOOL) Collegare il segnale hardware di lettura Data da bus I2C. Si utilizza solo se I2CMode<>0.
I2CMode (DINT) Definisce il modo di gestione del bus I2C.
0:Viene utilizzato il bus di espansione del sistema gestito in hardware.
1:Si utilizza un bus simulato su I/O discreti. La gestione dei segnali Clock e Data del bus è eseguita interamente da software permettendo di utilizzare qualsiasi I/O discreto, occorre appoggiare i segnali sui rispettivi I/O.
BFrequency (REAL) Frequenza di Clock bus I2C (Hz). Se I2CMode:=0 il parametro non è utilizzato la frequenza è definita dal sistema.
I2CAddress (USINT) Indirizzo dispositivo I2C range da 16#00 a 16#7F.
WrBytes (UDINT) Numero di bytes dati da scrivere. 0 se solo lettura.
WrBuffer (PVOID) Indirizzo buffer memoria che contiene i dati da scrivere, NULL se solo lettura.
RdBytes (UDINT) Numero di bytes dati da leggere. 0 se solo scrittura.
RdBuffer (PVOID) Indirizzo buffer memorizzazione dati letti, NULL se solo scrittura.
Done (BOOL) Si attiva per un loop al termine dell’esecuzione comando.
Ok (BOOL) Si attiva per un loop contemporaneamente al Done se il comando terminato correttamente.

I segnali seguenti sono gestiti solo se I2CMode<>0.

OClock (BOOL) Occorre collegare il segnale hardware di gestione Clock su bus I2C.
OData (BOOL) Occorre collegare il segnale hardware di gestione Data su bus I2C.
AckTrigger (BOOL) Attivata su acquisizione acknowledge dal dispositivo I2C.
BLockup (UDINT) Contatore errori di bus lockup. Si incrementa ad ogni invio di clock per liberare il bus.
Errors (UDINT) Contatore errori, si incrementa ad ogni errore riscontrato nella gestione.

Immagine FB I2CBusManager

Trigger di spy

Se SpyOn attivo è possibile utilizzare utilizzare la console di spionaggio per verificare il funzionamento della FB. Sono previsti vari livelli di triggers.

Livelli di trigger
TriggerDescrizione
16#40000000Er: Errore acquisizione.
Bus simulato su I/O discreti senza feedback

Quando si utilizza il blocco per la gestione di un bus I2C simulato su I/O discreti per facilitare il cablaggio è possibile evitare la lettura sia del segnale di clock che di dato.

Non acquisendo il clock non potrà essere gestito lo stretching (Ma essendo il bus simulato già molto lento non è necessario).

Non acquisendo il dato sarà possibile gestire solo dispositivi di output non potendo gestirne le lettura e non sarà possibile controllare il segnale di acnowledge del dato scritto.

Ecco nell’esempio come gestire i due segnali.

    // -------------------------------------------------------------------------
    // OBJECT EXECUTION
    // -------------------------------------------------------------------------
    // Manage the I2C bus on CPU module logic I/Os.
    // The Di00 is used as Clock, Di01 is used as Data.

    DInp(); //Dgital inputs acquisition
    I2CBus.IClock:=TRUE; //Clock in signal
    I2CBus.IData:=NOT(I2CBus.AckTrigger); //Data in signal

    // The Do00 is used as Clock, Do01 is used as Data.

    DOut.Value.0:=NOT(I2CBus.OClock); //Clock out signal
    DOut.Value.1:=NOT(I2CBus.OData); //Data out signal
    DOut(); //Digital output management

Esempi

Come utilizzare gli esempi.
Negli esempi vengono utilizzati gli I/O digitali del modulo CPU per gestire un bus I2C software, in questo modo il bus è completamente isolato dal sistema. Di fianco lo schema di cablaggio utilizzato, la tensione di alimentazione del bus +5Vcc deve essere fornita da un alimentatore esterno.

ST_I2CBusManager: Viene acquisito un sensore di temperatura ed umidità (Come questo) collegato al bus I2C simulato con gli I/O logici.

ST_ScanI2CDevicesOnIOs: 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 emulato con gli I/O del modulo.

Schema connessioni bus I2C su I/O
LogicLab (Ptp176, ST_I2CBusManager)
PROGRAM ST_I2CBusManager
VAR
    CaseNr : USINT; (* Program case *)
    Errors : UDINT; (* Error counter *)
    TimeBf : UDINT; (* Time buffer (mS) *)
    Temperature : REAL; (* Temperature value (°C) *)
    Humidity : REAL; (* Humidity value (%) *)
    I2CWrite : ARRAY[0..1] OF BYTE; (* I2C write buffer *)
    I2CRead : ARRAY[0..5] OF BYTE; (* I2C read buffer *)
    I2CBus : I2CBusManager; (* I2C bus management *)
    DInp : SysGetPhrDI; (* Digital input acquisistion *)
    DOut : SysSetPhrDO; (* Digital output management *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_I2CBusManager"
// *****************************************************************************
// Temperature and humidity acquisition from a Sensirion SHT30-DIS connected
// to a I2C bus emulated by logic I/Os
// -----------------------------------------------------------------------------

    // -------------------------------------------------------------------------
    // INITIALIZATION
    // -------------------------------------------------------------------------
    // First program loop initialization.

    IF (SysFirstLoop) THEN

        // Initialize the logic I/O management.

        DInp.Address:=255; //Module address
        DInp.Mode:=DI_I_8_LL; //Input mode

        DOut.Address:=255; //Module address
        DOut.Mode:=DO_8_LL; //Output mode
        DOut.Mask:=16#00000003; //Output mask

        // Initialize the software I2C management.

        I2CBus.I2CMode:=1; //I2C mode selection
        I2CBus.I2CAddress:=16#44; //I2C Address
        I2CBus.BFrequency:=1000.0; //Bus frequency (Hz)
    END_IF;

    // -------------------------------------------------------------------------
    // OBJECT EXECUTION
    // -------------------------------------------------------------------------
    // Manage the I2C bus on CPU module logic I/Os.
    // The Di00 is used as Clock, Di01 is used as Data.

    DInp(); //Dgital inputs acquisition
    I2CBus.IClock:=NOT(DInp.Value.0); //Clock in signal
    I2CBus.IData:=NOT(DInp.Value.1); //Data in signal

    // The Do00 is used as Clock, Do01 is used as Data.

    DOut.Value.0:=NOT(I2CBus.OClock); //Clock out signal
    DOut.Value.1:=NOT(I2CBus.OData); //Data out signal
    DOut(); //Digital output management

    // -------------------------------------------------------------------------
    // 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
        I2CBus(WrBuffer:=ADR(I2CWrite), WrBytes:=2, RdBuffer:=eNULL, RdBytes:=0);
        IF NOT(I2CBus.Done) THEN RETURN; END_IF;
        IF NOT(I2CBus.Ok) THEN Errors:=Errors+1; CaseNr:=0; 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.

        I2CBus(WrBuffer:=eNULL, WrBytes:=0, RdBuffer:=ADR(I2CRead), RdBytes:=6);
        IF NOT(I2CBus.Done) THEN RETURN; END_IF;
        IF NOT(I2CBus.Ok) THEN Errors:=Errors+1; CaseNr:=0; 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 (Ptp176, ST_ScanI2CDevicesOnIOs)
PROGRAM ST_ScanI2CDevicesOnIOs
VAR
    i : UDINT; (* Auxiliary variable *)
    CaseNr : USINT; (* Program case *)
    Fp : eFILEP; (* File pointer array *)
    SOut : STRING[ 128 ]; (* String output *)
    DInp : SysGetPhrDI; (* Digital input acquisistion *)
    DOut : SysSetPhrDO; (* Digital output management *)
    I2CBus : I2CBusManager; (* I2C bus management *)
    TCPServer : SysTCPServer; (* TCP server *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_ScanI2CDevicesOnIOs"
// *****************************************************************************
// Opens a TCP server and when a client connects to it a I2C Bus emulated by
// logic I/Os is scanned.
// -----------------------------------------------------------------------------

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

    IF (SysFirstLoop) THEN

        // Initialize the logic I/O management.

        DInp.Address:=255; //Module address
        DInp.Mode:=DI_I_8_LL; //Input mode

        DOut.Address:=255; //Module address
        DOut.Mode:=DO_8_LL; //Output mode
        DOut.Mask:=16#00000003; //Output mask

        // Initialize the software I2C management.

        I2CBus.I2CMode:=1; //I2C mode selection
        I2CBus.WrBytes:=0; //Data to write
        I2CBus.WrBuffer:=eNULL; //Data to write buffer
        I2CBus.RdBytes:=0; //Data to read
        I2CBus.RdBuffer:=eNULL; //Data readed buffer
        I2CBus.BFrequency:=1000.0; //Bus frequency (Hz)

        // Initialize TCP server.
    
        TCPServer.FilesArr:=ADR(Fp); //Files array
        TCPServer.LocalAdd:=ADR('0.0.0.0'); //Local address
        TCPServer.LocalPort:=1110; //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 I2C bus on CPU module logic I/Os.
    // The Di00 is used as Clock, Di01 is used as Data.

    DInp(); //Dgital inputs acquisition
    I2CBus.IClock:=NOT(DInp.Value.0); //Clock in signal
    I2CBus.IData:=NOT(DInp.Value.1); //Data in signal

    // The Do00 is used as Clock, Do01 is used as Data.

    DOut.Value.0:=NOT(I2CBus.OClock); //Clock out signal
    DOut.Value.1:=NOT(I2CBus.OData); //Data out signal
    DOut(); //Digital output management

    // 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'));
        I2CBus.I2CAddress:=16#00; //I2C address
        CaseNr:=CaseNr+1; //Program case

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

        1:
        I2CBus();
        IF NOT(I2CBus.Done) THEN RETURN; END_IF;

        IF NOT(I2CBus.Ok) THEN
            i:=SysCVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%s '), STRING_TYPE, ADR('--'));
        ELSE
            i:=SysCVsnprintf(ADR(SOut), SIZEOF(SOut), ADR('%02X '), USINT_TYPE, ADR(I2CBus.I2CAddress));
        END_IF;

        // Increase the I2C address to check.

        I2CBus.I2CAddress:=I2CBus.I2CAddress+1; //I2C address

        // Every 16 addresses return the result.

        IF (MOD(I2CBus.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:=Sysmemset(ADR(SOut), 0, SIZEOF(SOut));
            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 (I2CBus.I2CAddress < 16#80) THEN CaseNr:=CaseNr-1; RETURN; END_IF;
        i:=SysFOBfFlush(Fp); //Flush the socket data
        TCPServer.Enable:=FALSE; //TCPServer enable
        CaseNr:=0; //Program case
    END_CASE;

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