3.22. SPI koodissa

machine.SPI kääri laitteistopohjaisen SPI-ohjaimen; CS-linjat ovat tavallisia Pin -lähtöjä, joita skripti hallinnoi. Luo SPI-instanssi väylän id:llä, halutulla kellonopeudella ja (tarvittaessa) tilalla:

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 valitsee, mitä laitteistopohjaista SPI-lohkoa käytetään; käytettävissä olevat numerot ja niihin kuvautuvat SCK/MOSI/MISO-nastat riippuvat levystä (katso OpenMV-kortit). baudrate on SCK-taajuus hertseinä – laitteiston tosiasiallisesti saavuttama nopeus voi olla hieman matalampi kellonjaon vuoksi, minkä SPI-objektin tulostettu arvo näyttää.

CS-nasta luodaan arvolla value=1, jotta se lepää deaktivoituna. Jokainen tapahtuma aktivoi CS:n (vetää sen alas), siirtää tavut ja deaktivoi CS:n (vetää sen ylös) uudelleen.

3.22.1. Lukeminen, kirjoittaminen, vaihtaminen

Kolme metodia kattaa yleiset tapaukset:

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() on vain kirjoittava nopea polku; ohjain työntää tavut ja hylkää sen, mitä oheislaite lähetti takaisin MISO:lla. read() on peilikuva – se kellottaa N SCK-pulssia lähettäen samalla kiinteää täytetavua (oletuksena 0) MOSI:lla ja tallentaa MISO-tavut. write_readinto() on täysdupleksinen muoto: se lähettää tavut yhdestä puskurista ja tallentaa samanaikaiset MISO-tavut toiseen. Monet oheislaitteet käyttävät tätä mallia – ”lähetä komentotavu, lue sitten vastaus seuraavassa siirrossa” – joten nämä kaksi operaatiota sopivat luonnostaan yhteen write_readinto-kutsuun.

Useimmat oheislaitteet odottavat CS-linjan pysyvän aktivoituna koko tapahtuman ajan (komentotavuista vastaustavuihin), joten pidä cs.value(0) / cs.value(1) -sulkeet koko sekvenssin ympärillä, ei kunkin metodikutsun ympärillä.

3.22.2. Tyypillinen sensorin lukeminen

Monet SPI-sensorit järjestävät tilansa joukoksi sisäisiä rekistereitä ja noudattavat samaa vaihtomuotoa: lähetä rekisterin osoite (luku-/kirjoituslippu ylimmässä bitissä), lue tai kirjoita sitten rekisterin tavut. Rekisterin 0x0F lukeminen tällaisella laitteella:

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]

Ensimmäinen MISO-tavu on roskaa (laite oli tuolloin vielä vastaanottamassa komentoa); toinen MISO-tavu sisältää rekisterin sisällön. Tarkka komentotavun muoto – mikä bitti on luku-/kirjoituslippu, kasvaako osoite automaattisesti monitavuisissa luvuissa – löytyy laitteen tietolehdestä.

3.22.3. Bit-banging

SPI -instanssi yllä käyttää laitteistopohjaista SPI-lohkoa: MCU:n sisäistä erillistä oheislaitetta, jolla on oma siirtorekisteri ja kellogeneraattori ja joka tuottaa SCK/MOSI/MISO-aaltomuodot piissä. Ohjelmisto vain antaa sille tavun; bitit liikkuvat johdossa ilman lisäapua CPU:lta, jättäen CPU:n vapaaksi tekemään muuta työtä rinnakkain.

Vaihtoehto on bit-banging: ohjelmisto käy silmukassa läpi jokaisen bitin ja kytkee GPIO-nastoja suoraan tuottaakseen saman aaltomuodon. Mukana ei ole laitteistopohjaista oheislaitetta – CPU vetää SCK:n alas, asettaa MOSI:n, vetää SCK:n ylös, näytteistää MISO:n ja niin edelleen jokaiselle bitille jokaisesta tavusta. Se sitoo CPU:n koko tapahtuman ajaksi ja toimii hitaammin kuin laitteistolohko pystyy, mutta se toimii millä tahansa nastalla eikä vaadi laitteistolohkon olevan vapaana.

machine.SoftSPI on saman SPI-API:n bit-bang-toteutus:

from machine import SoftSPI, Pin

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

Käytä sitä, kun laitteen täytyy olla nastoissa, joita ei ole kytketty laitteistopohjaiseen SPI-lohkoon, tai kun kaikki laitteistolohkot ovat käytössä. 500 kHz on mukava yläraja useimmilla kameroilla; CPU pysyy varattuna koko tapahtuman ajan.