3.22. SPI i kod

machine.SPI omsluter en SPI-styrenhet i hårdvara; CS-ledningar är vanliga Pin-utgångar som hanteras av skriptet. Skapa en SPI-instans med buss-id, önskad klockhastighet och (vid behov) läget:

from machine import SPI, Pin

spi = SPI(0, baudrate=1_000_000, polarity=0, phase=0)
cs = Pin("P3", Pin.OUT, value=1)         # CS idle high

id väljer vilket SPI-hårdvaroblock som ska användas; de tillgängliga numren och de SCK/MOSI/MISO-stift de mappas till beror på kortet (se OpenMV-kort). baudrate är SCK-frekvensen i hertz – den faktiska hastighet som hårdvaran uppnår kan vara något lägre på grund av klockdelning, vilket det utskrivna värdet för SPI-objektet visar.

CS-stiftet skapas med value=1 så att det vilar inaktiverat. Varje transaktion aktiverar CS (drar den låg), flyttar byten och inaktiverar CS (drar den hög) igen.

3.22.1. Läsa, skriva, utbyta

Tre metoder täcker de vanliga fallen:

cs.value(0)
spi.write(b"\x10\x20\x30")              # send 3 bytes, ignore what comes back
cs.value(1)

cs.value(0)
data = spi.read(4)                      # read 4 bytes; sends 0x00 while reading
cs.value(1)

rx = bytearray(2)
cs.value(0)
spi.write_readinto(b"\x9F\x00", rx)     # send 0x9F, 0x00; receive 2 bytes
cs.value(1)

write() är den snabba vägen för enbart skrivning; styrenheten skjuter ut byten och kastar bort det som kringutrustningen skickade tillbaka på MISO. read() är spegelbilden – den klockar N SCK-pulser samtidigt som den skickar en fast attrappbyte (0 som standard) på MOSI och lagrar MISO-byten. write_readinto() är full-duplex-formen: den skickar byten från en buffert och lagrar de samtidiga MISO-byten i en annan. Många kringutrustningar använder detta mönster – ”skicka en kommandobyte, läs sedan svaret i nästa överföring” – så de två operationerna ryms naturligt i ett enda write_readinto-anrop.

De flesta kringutrustningar förväntar sig att CS-ledningen förblir aktiverad under hela transaktionen (från kommandobyte till svarsbyte), så håll parenteserna cs.value(0) / cs.value(1) runt hela sekvensen, inte runt varje metodanrop.

3.22.2. En typisk sensoravläsning

Många SPI-sensorer organiserar sitt tillstånd som en uppsättning interna register och följer samma utbytesform: skicka registeradressen (med en läs/skriv-flagga i den översta biten) och läs eller skriv sedan registrets byte. En läsning av register 0x0F på en sådan enhet:

rx = bytearray(2)
cs.value(0)
spi.write_readinto(b"\x8F\x00", rx)     # 0x80 = "read" flag, then reg 0x0F
cs.value(1)
register_value = rx[1]

Den första MISO-byten är skräp (enheten höll fortfarande på att ta emot kommandot vid den tidpunkten); den andra MISO-byten innehåller registerinnehållet. Det exakta formatet för kommandobyten – vilken bit som är läs/skriv-flaggan, huruvida adressen ökas automatiskt vid flerbytläsningar – finns i enhetens datablad.

3.22.3. Bit-banging

Instansen SPI ovan använder ett SPI-hårdvaroblock: en dedikerad kringutrustning inuti MCU:n med eget skiftregister och egen klockgenerator som producerar SCK/MOSI/MISO-vågformerna i kisel. Programvaran lämnar bara över en byte; bitarna flyttas på ledningen utan vidare hjälp från CPU:n, vilket lämnar CPU:n fri att utföra annat arbete parallellt.

Alternativet är bit-banging: programvaran loopar över varje bit och växlar GPIO-stiften direkt för att producera samma vågform. Ingen hårdvarukringutrustning är inblandad – CPU:n drar SCK låg, sätter MOSI, drar SCK hög, avläser MISO, och så vidare för varje bit i varje byte. Det binder upp CPU:n under hela transaktionen och går långsammare än vad hårdvaroblocket kan, men det fungerar på vilket stift som helst och kräver inte att ett hårdvaroblock är ledigt.

machine.SoftSPI är bit-bang-implementeringen av samma SPI-API:

from machine import SoftSPI, Pin

spi = SoftSPI(baudrate=500_000, polarity=0, phase=0,
              sck=Pin("P2"), mosi=Pin("P0"), miso=Pin("P1"))

Använd den när enheten behöver sitta på stift som inte är kopplade till ett SPI-hårdvaroblock, eller när hårdvaroblocken alla är upptagna. 500 kHz är ett bekvämt tak på de flesta kameror; CPU:n förblir upptagen under hela transaktionen.