class SPI – protocollo bus Serial Peripheral Interface (lato controller)

SPI è un protocollo seriale sincrono pilotato da un controller. A livello fisico, un bus è costituito da 3 linee: SCK, MOSI, MISO. Più dispositivi possono condividere lo stesso bus. Ogni dispositivo dovrebbe avere un quarto segnale separato, CS (Chip Select), per selezionare un particolare dispositivo sul bus con cui avviene la comunicazione. La gestione del segnale CS dovrebbe avvenire nel codice utente (tramite la classe machine.Pin).

Esistono implementazioni SPI sia hardware sia software, tramite le classi SPI e SoftSPI. L’SPI hardware utilizza il supporto hardware sottostante del sistema per eseguire le letture/scritture ed è solitamente efficiente e veloce, ma può avere restrizioni su quali pin possono essere usati. L’SPI software è implementato tramite bit-banging e può essere usato su qualsiasi pin, ma non è altrettanto efficiente. Queste classi dispongono degli stessi metodi e differiscono principalmente nel modo in cui vengono costruite.

Esempio di utilizzo:

from machine import SPI, Pin

spi = SPI(0, baudrate=400000)           # Create SPI peripheral 0 at frequency of 400kHz.
                                        # Depending on the use case, extra parameters may be required
                                        # to select the bus characteristics and/or pins to use.
cs = Pin(4, mode=Pin.OUT, value=1)      # Create chip-select on pin 4.

try:
    cs(0)                               # Select peripheral.
    spi.write(b"12345678")              # Write 8 bytes, and don't care about received data.
finally:
    cs(1)                               # Deselect peripheral.

try:
    cs(0)                               # Select peripheral.
    rxdata = spi.read(8, 0x42)          # Read 8 bytes while writing 0x42 for each byte.
finally:
    cs(1)                               # Deselect peripheral.

rxdata = bytearray(8)
try:
    cs(0)                               # Select peripheral.
    spi.readinto(rxdata, 0x42)          # Read 8 bytes inplace while writing 0x42 for each byte.
finally:
    cs(1)                               # Deselect peripheral.

txdata = b"12345678"
rxdata = bytearray(len(txdata))
try:
    cs(0)                               # Select peripheral.
    spi.write_readinto(txdata, rxdata)  # Simultaneously write and read bytes.
finally:
    cs(1)                               # Deselect peripheral.

Costruttori

class machine.SPI(id: int, baudrate: int = 1000000, *, polarity: int = 0, phase: int = 0, bits: int = 8, firstbit: int = MSB, sck: Pin | None = None, mosi: Pin | None = None, miso: Pin | None = None)

Costruisce un oggetto SPI sul bus indicato, id. I valori di id dipendono dalla particolare porta e dal suo hardware. I valori 0, 1, ecc. sono comunemente usati per selezionare il blocco SPI hardware #0, #1, ecc.

Senza parametri aggiuntivi, l’oggetto SPI viene creato ma non inizializzato (mantiene le impostazioni dell’ultima inizializzazione del bus, se presente). Se vengono forniti argomenti aggiuntivi, il bus viene inizializzato. Vedi init per i parametri di inizializzazione.

Metodi

init(baudrate: int = 1000000, *, polarity: int = 0, phase: int = 0, bits: int = 8, firstbit: int = SPI.MSB, sck: Pin | None = None, mosi: Pin | None = None, miso: Pin | None = None) None

Inizializza il bus SPI con i parametri indicati:

  • baudrate è la frequenza di clock di SCK.

  • polarity può essere 0 o 1 ed è il livello a cui si trova la linea di clock a riposo.

  • phase può essere 0 o 1 per campionare i dati rispettivamente sul primo o sul secondo fronte di clock.

  • bits è la larghezza in bit di ogni trasferimento. Solo 8 è garantito essere supportato da tutto l’hardware.

  • firstbit può essere SPI.MSB o SPI.LSB.

  • sck, mosi, miso sono oggetti pin (machine.Pin) da usare per i segnali del bus. Per la maggior parte dei blocchi SPI hardware (selezionati dal parametro id passato al costruttore), i pin sono fissi e non possono essere modificati. In alcuni casi, i blocchi hardware consentono 2-3 set di pin alternativi per un blocco SPI hardware. Assegnazioni arbitrarie di pin sono possibili solo per un driver SPI in bitbanging (id = -1).

Nel caso dell’SPI hardware la frequenza di clock effettiva può essere inferiore al baudrate richiesto. Ciò dipende dall’hardware della piattaforma. La frequenza effettiva può essere determinata stampando l’oggetto SPI.

deinit() None

Spegne il bus SPI.

read(nbytes: int, write: int = 0x00) bytes

Legge un numero di byte specificato da nbytes scrivendo continuamente il singolo byte indicato da write. Restituisce un oggetto bytes con i dati letti.

readinto(buf: bytearray, write: int = 0x00) None

Legge nel buffer specificato da buf scrivendo continuamente il singolo byte indicato da write. Restituisce None.

write(buf: bytes) None

Scrive i byte contenuti in buf. Restituisce None.

write_readinto(write_buf: bytes, read_buf: bytearray) None

Scrive i byte da write_buf mentre legge in read_buf. I buffer possono essere lo stesso o diversi, ma entrambi devono avere la stessa lunghezza. Restituisce None.

Costanti

MSB: int

Passa a firstbit per trasmettere/ricevere per primo il bit più significativo (l’ordinamento più comune).

LSB: int

Passa a firstbit per trasmettere/ricevere per primo il bit meno significativo.

class SoftSPI – bus SPI emulato via software

La classe SoftSPI implementa l’SPI tramite bit-banging di pin GPIO arbitrari. Espone la stessa superficie di metodi di SPI, quindi il codice esistente che usa l’SPI hardware può passare al software con la sola modifica del costruttore. Usala quando i pin di cui hai bisogno non sono cablati a un blocco SPI hardware, quando ti servono più bus di quelli hardware disponibili, oppure quando una periferica richiede un fasaggio di clock non standard che l’hardware non è in grado di produrre.

Costruttori

class machine.SoftSPI(baudrate: int = 500000, *, polarity: int = 0, phase: int = 0, bits: int = 8, firstbit: int = MSB, sck: Pin | None = None, mosi: Pin | None = None, miso: Pin | None = None)

Costruisce un oggetto SPI software. sck, mosi e miso devono essere forniti – non esiste alcuna selezione implicita dei pin. Vedi SPI.init() per il significato degli altri parametri. Il baudrate predefinito è inferiore rispetto all’SPI hardware SPI perché il ciclo di bit-bang ha un overhead maggiore.

Metodi

init(baudrate: int = 500000, *, polarity: int = 0, phase: int = 0, bits: int = 8, firstbit: int = SoftSPI.MSB, sck: Pin | None = None, mosi: Pin | None = None, miso: Pin | None = None) None

Reinizializza il bus SPI software con i parametri indicati. Vengono aggiornati solo gli argomenti forniti; gli altri mantengono i valori precedenti. Vedi SPI.init() per il significato di ogni argomento.

deinit() None

Rilascia i pin GPIO occupati dal driver bit-bang e smette di pilotare il bus.

read(nbytes: int, write: int = 0x00) bytes

Legge nbytes byte scrivendo continuamente il singolo byte write. Restituisce un oggetto bytes contenente i dati ricevuti.

readinto(buf: bytearray, write: int = 0x00) None

Legge in buf scrivendo continuamente il singolo byte write. Restituisce None.

write(buf: bytes) None

Scrive buf sul bus. I byte ricevuti vengono scartati.

write_readinto(write_buf: bytes, read_buf: bytearray) None

Scrive simultaneamente write_buf e legge in read_buf. Entrambi i buffer devono avere la stessa lunghezza; possono coincidere (alias).

Costanti

MSB: int

Passa a firstbit per trasmettere/ricevere per primo il bit più significativo.

LSB: int

Passa a firstbit per trasmettere/ricevere per primo il bit meno significativo.