3.22. SPI u kodu

machine.SPI obavija hardverski SPI kontroler; CS linije su obični Pin izlazi kojima upravlja skripta. SPI instancu konstruirajte s id-om sabirnice, željenom brzinom takta i (po potrebi) načinom rada:

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 odabire koji hardverski SPI blok koristiti; dostupni brojevi i SCK/MOSI/MISO pinovi na koje se preslikavaju ovise o pločici (vidi OpenMV ploče). baudrate je frekvencija SCK-a u hercima – stvarna brzina koju hardver postigne može biti nešto niža zbog dijeljenja takta, što će pokazati ispisana vrijednost SPI objekta.

CS pin se konstruira s value=1 tako da miruje deaktiviran. Svaka transakcija aktivira CS (spušta ga na nisku razinu), prenosi bajtove i ponovno deaktivira CS (podiže ga na visoku razinu).

3.22.1. Čitanje, pisanje, razmjena

Tri metode pokrivaju uobičajene slučajeve:

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() je brzi put samo za pisanje; kontroler šalje bajtove i odbacuje sve što periferija pošalje natrag na MISO. read() je zrcalna slika – taktira N SCK impulsa dok na MOSI šalje fiksni lažni bajt (zadano 0) i pohranjuje MISO bajtove. write_readinto() je potpuno dupleksni oblik: šalje bajtove iz jednog međuspremnika i istovremene MISO bajtove pohranjuje u drugi. Mnoge periferije koriste ovaj obrazac – „pošalji naredbeni bajt, zatim u sljedećem prijenosu pročitaj odgovor” – pa se dvije operacije prirodno uklapaju u jedan write_readinto poziv.

Većina periferija očekuje da CS linija ostane aktivirana tijekom cijele transakcije (od naredbenih bajtova do bajtova odgovora), pa zadržite cs.value(0) / cs.value(1) zagrade oko cijelog slijeda, a ne oko svakog poziva metode.

3.22.2. Tipično čitanje senzora

Mnogi SPI senzori organiziraju svoje stanje kao skup internih registara i slijede isti oblik razmjene: pošalji adresu registra (s zastavicom čitanja/pisanja u najvišem bitu), zatim pročitaj ili zapiši bajtove registra. Čitanje registra 0x0F na takvom uređaju:

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]

Prvi MISO bajt je smeće (uređaj je u tom trenutku još primao naredbu); drugi MISO bajt sadrži sadržaj registra. Točan format naredbenog bajta – koji je bit zastavica čitanja/pisanja, povećava li se adresa automatski pri višebajtnim čitanjima – nalazi se u tehničkom listu uređaja.

3.22.3. Bit-banging

SPI instanca iznad koristi hardverski SPI blok: namjensku periferiju unutar MCU-a s vlastitim posmačnim registrom i generatorom takta koji proizvodi SCK / MOSI / MISO valne oblike u silikonu. Softver mu samo preda bajt; bitovi se pomiču po žici bez daljnje pomoći CPU-a, ostavljajući CPU slobodan za obavljanje drugog posla usporedo.

Alternativa je bit-banging: softver u petlji prolazi kroz svaki bit i izravno mijenja stanje GPIO pinova kako bi proizveo isti valni oblik. Nema uključene hardverske periferije – CPU spušta SCK na nisku razinu, postavlja MOSI, podiže SCK na visoku razinu, uzorkuje MISO, i tako za svaki bit svakog bajta. To zauzima CPU tijekom cijele transakcije i radi sporije nego što to može hardverski blok, ali funkcionira na svakom pinu i ne zahtijeva da hardverski blok bude slobodan.

machine.SoftSPI je bit-bang izvedba istog SPI API-ja:

from machine import SoftSPI, Pin

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

Koristite je kada uređaj treba biti na pinovima koji nisu spojeni na hardverski SPI blok ili kada su svi hardverski blokovi u upotrebi. 500 kHz je ugodna gornja granica na većini kamera; CPU ostaje zauzet tijekom cijele transakcije.