classe I2C – un protocollo seriale a due fili

I2C è un protocollo a due fili per la comunicazione tra dispositivi. A livello fisico è costituito da due linee, SCL (clock) e SDA (dati). L’OpenMV Cam non fornisce pull-up integrati su nessuna delle due linee – sono necessari pull-up esterni sia su SCL che su SDA affinché il bus funzioni.

Gli oggetti I2C sono associati a un bus specifico e possono essere inizializzati al momento della costruzione oppure più tardi tramite init().

Esempio:

from pyb import I2C

i2c = I2C(2)                              # create on bus 2 (uninitialised)
i2c = I2C(2, I2C.CONTROLLER)              # create and init as a controller
i2c.init(I2C.CONTROLLER, baudrate=20000)  # init as a controller
i2c.init(I2C.PERIPHERAL, addr=0x42)       # init as a peripheral with the given address
i2c.deinit()                              # turn off the peripheral

Stampando l’oggetto I2C se ne visualizza la configurazione.

I metodi di base sono send() e recv()

i2c.send("abc")      # send 3 bytes
i2c.send(0x42)       # send a single byte, given by the number
data = i2c.recv(3)   # receive 3 bytes

Per ricevere sul posto, creare prima un bytearray

data = bytearray(3)  # create a buffer
i2c.recv(data)       # receive 3 bytes, writing them into data

È possibile specificare un timeout (in ms):

i2c.send(b"123", timeout=2000)   # timeout after 2 seconds

Un controller deve specificare l’indirizzo del destinatario:

i2c.init(I2C.CONTROLLER)
i2c.send("123", 0x42)        # send 3 bytes to peripheral with address 0x42
i2c.send(b"456", addr=0x42)  # keyword for address

Un controller dispone anche di questi metodi:

# Check if peripheral 0x42 is ready.
i2c.is_ready(0x42)

# Scan the bus and return a list of responding addresses.
i2c.scan()

# Read 3 bytes from peripheral 0x42 starting at memaddr 2.
i2c.mem_read(3, 0x42, 2)

# Write 3 bytes to peripheral 0x42 at memaddr 2.
i2c.mem_write("abc", 0x42, 2, timeout=1000)

Costruttori

class pyb.I2C(bus: int | str, *args, **kwargs)

Costruisce un oggetto I2C sul bus indicato (un indice intero della periferica, ad es. 2 per I2C2). Senza parametri aggiuntivi l’oggetto viene creato ma non inizializzato (mantiene le impostazioni del bus precedenti, se presenti); se vengono forniti argomenti extra, il bus viene inizializzato. Vedere init() per i parametri disponibili.

I2C(2) è cablato sugli stessi pin dell’header su ogni OpenMV Cam che espone pyb.I2C (M4 / M7 / H7 / H7 Plus / Pure Thermal):

Segnale

Pin header

Note

SCL

P4

SDA

P5

I2C(4) è inoltre disponibile sulle OpenMV Cam M7, H7, H7 Plus e Pure Thermal con SCL sul pin header P7 e SDA sul pin header P8.

L’OpenMV Cam N6 non espone pyb.I2C; usare invece machine.I2C.

Metodi

deinit() None

Disattiva il bus I2C.

init(mode: int, *, addr: int = 0x12, baudrate: int = 400000, gencall: bool = False, dma: bool = False) None

Inizializza il bus I2C con i parametri indicati:

  • mode deve essere I2C.CONTROLLER o I2C.PERIPHERAL.

  • addr è l’indirizzo a 7 bit (sensato solo per una periferica).

  • baudrate è la frequenza di clock SCL (sensata solo per un controller).

  • gencall indica se supportare la modalità general-call.

  • dma indica se consentire l’uso del DMA per i trasferimenti I2C (si noti che i trasferimenti DMA hanno una temporizzazione più precisa ma attualmente non gestiscono correttamente gli errori di bus).

La frequenza di clock effettiva può essere inferiore a quella richiesta. Ciò dipende dall’hardware della piattaforma. La frequenza effettiva può essere determinata stampando l’oggetto I2C.

is_ready(addr: int) bool

Verifica se un dispositivo I2C risponde all’indirizzo indicato. Valido solo in modalità controller.

mem_read(data: int | bytearray, addr: int, memaddr: int, *, timeout: int = 5000, addr_size: int = 8) bytes

Legge dalla memoria di un dispositivo I2C:

  • data può essere un intero (numero di byte da leggere) o un buffer in cui leggere

  • addr è l’indirizzo del dispositivo I2C

  • memaddr è la posizione di memoria all’interno del dispositivo I2C

  • timeout è il timeout in millisecondi entro cui attendere la lettura

  • addr_size seleziona l’ampiezza di memaddr: 8 o 16 bit

Restituisce i dati letti. Valido solo in modalità controller.

mem_write(data: int | bytes | bytearray, addr: int, memaddr: int, *, timeout: int = 5000, addr_size: int = 8) None

Scrive nella memoria di un dispositivo I2C:

  • data può essere un intero o un buffer da cui scrivere.

  • addr è l’indirizzo del dispositivo I2C.

  • memaddr è la posizione di memoria all’interno del dispositivo I2C.

  • timeout è il timeout in millisecondi entro cui attendere la scrittura.

  • addr_size seleziona l’ampiezza di memaddr: 8 o 16 bit.

Valido solo in modalità controller.

recv(recv: int | bytearray, addr: int = 0x00, *, timeout: int = 5000) bytes

Riceve dati sul bus:

  • recv può essere un intero, che è il numero di byte da ricevere, oppure un buffer mutabile, che verrà riempito con i byte ricevuti

  • addr è l’indirizzo da cui ricevere (necessario solo in modalità controller)

  • timeout è il timeout in millisecondi entro cui attendere la ricezione

Valore restituito: se recv è un intero allora un nuovo buffer con i byte ricevuti, altrimenti lo stesso buffer passato a recv.

send(send: int | bytes | bytearray, addr: int = 0x00, *, timeout: int = 5000) None

Invia dati sul bus:

  • send sono i dati da inviare (un intero da inviare, o un oggetto buffer).

  • addr è l’indirizzo a cui inviare (necessario solo in modalità controller).

  • timeout è il timeout in millisecondi entro cui attendere l’invio.

scan() List[int]

Esegue la scansione di tutti gli indirizzi I2C da 0x01 a 0x7f e restituisce un elenco di quelli che rispondono. Valido solo in modalità controller.

Costanti

CONTROLLER: int

Inizializza il bus come master (controller) – pilota SCL e avvia le transazioni.

PERIPHERAL: int

Inizializza il bus come slave (periferica) che ascolta sull”addr impostato in init() e risponde alle transazioni avviate da un controller sullo stesso bus.