class I2CTarget – un dispositivo target I2C

Un target I2C è un dispositivo che si collega a un bus I2C ed è controllato da un controller I2C. I target I2C possono assumere molte forme. La classe machine.I2CTarget implementa un target I2C che può essere configurato come dispositivo di memoria/registro, oppure come dispositivo I2C arbitrario utilizzando callback (se supportate dalla porta).

Disponibile su OpenMV Cam M4 / M7 / H7 / H7 Plus / Pure Thermal / RT1062 / AE3.

Esempio di utilizzo per il caso di un dispositivo di memoria:

from machine import I2CTarget

# Create the backing memory for the I2C target.
mem = bytearray(8)

# Create an I2C target.  Depending on the port, extra parameters
# may be required to select the peripheral and/or pins to use.
i2c = I2CTarget(addr=67, mem=mem)

# At this point an I2C controller can read and write `mem`.
...

# Deinitialise the I2C target.
i2c.deinit()

Nota che alcune porte richiedono che vengano passati al costruttore I2CTarget un id, ed eventualmente i pin scl e sda, per selezionare l’istanza I2C hardware e i pin a cui essa si collega.

Quando è configurato come dispositivo di memoria, è anche possibile registrarsi per ricevere eventi. Ad esempio per essere notificati quando la memoria viene letta/scritta:

from machine import I2CTarget

# Define an IRQ handler, for I2C events.
def irq_handler(i2c_target):
    flags = i2c_target.irq().flags()
    if flags & I2CTarget.IRQ_END_READ:
        print("controller read target at addr", i2c_target.memaddr)
    if flags & I2CTarget.IRQ_END_WRITE:
        print("controller wrote target at addr", i2c_target.memaddr)

# Create the I2C target and register to receive default events.
mem = bytearray(8)
i2c = I2CTarget(addr=67, mem=mem)
i2c.irq(irq_handler)

Dispositivi I2C più complessi possono essere implementati utilizzando l’intero insieme di eventi. Ad esempio, per vedere gli eventi grezzi nel momento in cui vengono attivati:

from machine import I2CTarget

# Define an IRQ handler that prints the event id and responds to reads/writes.
def irq_handler(i2c_target, buf=bytearray(1)):
    flags = i2c_target.irq().flags()
    print(flags)
    if flags & I2CTarget.IRQ_READ_REQ:
        i2c_target.write(buf)
    if flags & I2CTarget.IRQ_WRITE_REQ:
        i2c_target.readinto(buf)

# Create the I2C target and register to receive all events.
i2c = I2CTarget(addr=67)
all_triggers = (
    I2CTarget.IRQ_ADDR_MATCH_READ
    | I2CTarget.IRQ_ADDR_MATCH_WRITE
    | I2CTarget.IRQ_READ_REQ
    | I2CTarget.IRQ_WRITE_REQ
    | I2CTarget.IRQ_END_READ
    | I2CTarget.IRQ_END_WRITE
)
i2c.irq(irq_handler, trigger=all_triggers, hard=True)

Costruttori

class machine.I2CTarget(id: int, addr: int, *, addrsize: int = 7, mem: bytearray | None = None, mem_addrsize: int = 8, scl: Pin | None = None, sda: Pin | None = None)

Costruisce e restituisce un nuovo oggetto I2CTarget utilizzando i seguenti parametri:

  • id identifica una particolare periferica I2C. I valori consentiti dipendono dalla particolare porta/scheda. Alcune porte hanno un valore predefinito, nel qual caso questo parametro può essere omesso.

  • addr è l’indirizzo I2C del target.

  • addrsize è il numero di bit nell’indirizzo del target I2C. I valori validi sono 7 e 10.

  • mem è un oggetto scrivibile che supporta il buffer protocol. Se non specificato, non c’è memoria di supporto e i dati devono essere letti/scritti utilizzando i metodi I2CTarget.readinto() e I2CTarget.write().

  • mem_addrsize è il numero di bit nell’indirizzo di memoria. I valori validi sono 0, 8, 16, 24 e 32.

  • scl è un oggetto pin che specifica il pin da utilizzare per SCL.

  • sda è un oggetto pin che specifica il pin da utilizzare per SDA.

Nota che alcune porte/schede avranno valori predefiniti di scl e sda che possono essere modificati in questo costruttore. Altre avranno valori fissi di scl e sda che non possono essere modificati.

Metodi generali

deinit() None

Deinizializza il target I2C. Dopo che questo metodo è stato chiamato, l’hardware non risponderà più alle richieste sul bus I2C e non sarà possibile chiamare altri metodi.

readinto(buf: bytearray) int

Legge nel buffer specificato eventuali byte in sospeso scritti dal controller I2C. Restituisce il numero di byte letti.

write(buf: bytes) int

Scrive i byte dal buffer specificato, da passare al controller I2C dopo che esso invia una richiesta di lettura. Restituisce il numero di byte scritti. La maggior parte delle porte accetta un solo byte alla volta per questo metodo.

irq(handler: Callable[[I2CTarget], None] | None = None, trigger: int = IRQ_END_READ | IRQ_END_WRITE, hard: bool = False) None

Installa un gestore IRQ handler che viene invocato quando si verifica uno degli eventi selezionati da trigger. trigger è una maschera di bit di costanti IRQ_* combinate con OR; il valore predefinito si attiva al termine di ogni lettura o scrittura lato controller.

hard=True registra un gestore di interrupt hardware (nessuna allocazione di heap nella callback). Il valore predefinito è una callback schedulata. Passa handler=None per disabilitare l’interrupt.

Nota

IRQ_ADDR_MATCH_READ, IRQ_ADDR_MATCH_WRITE, IRQ_READ_REQ e IRQ_WRITE_REQ devono essere gestiti da una callback hard IRQ (hard=True) perché gli eventi devono essere riconosciuti in modo sincrono con l’hardware. IRQ_END_READ e IRQ_END_WRITE possono essere gestiti da callback soft o hard; tutti gli eventi condividono un unico gestore, quindi se un evento qualsiasi richiede una callback hard, allora la richiedono tutti.

Quando viene fornito un buffer di memoria al costruttore, il driver sopprime IRQ_END_WRITE per la transazione che si limita a scrivere l’indirizzo di memoria. Ciò mantiene significativi gli eventi di fine transazione anche quando lo scheduler soft-IRQ rinvia la callback.

memaddr

Il valore intero dell’indirizzo di memoria più recente che è stato selezionato dal controller I2C (valido solo se mem è stato specificato nel costruttore).

Costanti

Ogni costante IRQ_* è un bit di flag. Combinale con OR per costruire una maschera trigger per irq(). All’interno del gestore l’insieme degli eventi attivati può essere recuperato tramite self.irq().flags() combinato con AND con ciascuna costante.

IRQ_ADDR_MATCH_READ: int

Si attiva quando un controller indirizza questo target per una transazione di lettura (il byte di indirizzo è stato ricevuto con il bit di lettura/scrittura impostato a 1). Solo hard IRQ.

IRQ_ADDR_MATCH_WRITE: int

Si attiva quando un controller indirizza questo target per una transazione di scrittura (il byte di indirizzo è stato ricevuto con il bit di lettura/scrittura impostato a 0). Solo hard IRQ.

IRQ_READ_REQ: int

Si attiva quando il controller richiede un byte al target. Il gestore deve chiamare write() per fornire il byte prima che si concluda il ciclo di clock del controller. Solo hard IRQ.

IRQ_WRITE_REQ: int

Si attiva quando il controller ha inviato (clocked in) un byte al target. Il gestore deve chiamare readinto() per recuperare il byte prima che il controller invii il successivo. Solo hard IRQ.

IRQ_END_READ: int

Si attiva quando il controller ha terminato una transazione di lettura (ricevuto STOP / START ripetuto). Può essere gestito da una callback hard o soft IRQ.

IRQ_END_WRITE: int

Si attiva quando il controller ha terminato una transazione di scrittura (ricevuto STOP / START ripetuto). Può essere gestito da una callback hard o soft IRQ. Soppresso per la transazione che scrive l’indirizzo di memoria quando un buffer mem è stato fornito al costruttore.