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.