3.22. SPI dalam kode

machine.SPI membungkus kontroler SPI hardware; jalur CS adalah output Pin biasa yang dikelola oleh skrip. Buat instance SPI dengan id bus, kecepatan clock yang diinginkan, dan (jika diperlukan) mode:

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 memilih blok SPI hardware yang akan digunakan; nomor yang tersedia dan pin SCK/MOSI/MISO yang dipetakannya bergantung pada papan (lihat Papan OpenMV). baudrate adalah frekuensi SCK dalam hertz -- kecepatan aktual yang dicapai hardware mungkin sedikit lebih rendah karena pembagian clock, yang akan ditampilkan oleh nilai yang dicetak dari objek SPI.

Pin CS dikonstruksi dengan value=1 sehingga ia idle dalam keadaan tidak aktif. Setiap transaksi mengaktifkan CS (mengarahkannya rendah), memindahkan byte-byte tersebut, dan menonaktifkan CS (mengarahkannya tinggi) kembali.

3.22.1. Membaca, menulis, menukar

Tiga metode mencakup kasus-kasus umum:

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() adalah jalur cepat hanya-tulis; kontroler mendorong byte-byte dan membuang apa pun yang dikirimkan periferal kembali melalui MISO. read() adalah kebalikannya -- ia meng-clock N pulsa SCK sambil mengirimkan byte dummy tetap (0 secara default) pada MOSI dan menyimpan byte MISO. write_readinto() adalah bentuk full-duplex: ia mengirimkan byte dari satu buffer dan menyimpan byte MISO simultan ke buffer lain. Banyak periferal menggunakan pola ini -- "kirim byte perintah, lalu baca respons dalam transfer berikutnya" -- sehingga dua operasi ini secara alami masuk ke dalam satu panggilan write_readinto.

Sebagian besar periferal mengharapkan jalur CS tetap aktif untuk seluruh transaksi (dari byte perintah hingga byte respons), jadi pertahankan tanda kurung cs.value(0) / cs.value(1) di sekitar seluruh urutan, bukan di sekitar setiap panggilan metode.

3.22.2. Pembacaan sensor yang khas

Banyak sensor SPI mengorganisasi statusnya sebagai sekumpulan register internal dan mengikuti bentuk pertukaran yang sama: kirim alamat register (dengan flag baca/tulis di bit teratas), lalu baca atau tulis byte register tersebut. Pembacaan register 0x0F pada perangkat seperti itu:

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]

Byte MISO pertama adalah sampah (perangkat masih menerima perintah pada saat itu); byte MISO kedua berisi konten register. Format byte perintah yang tepat -- bit mana yang merupakan flag baca/tulis, apakah alamat auto-increment pada pembacaan multi-byte -- terdapat dalam lembar data perangkat.

3.22.3. Bit-banging

Instance SPI di atas menggunakan blok SPI hardware: periferal khusus di dalam MCU dengan shift register dan generator clock sendiri yang menghasilkan gelombang SCK / MOSI / MISO dalam silikon. Perangkat lunak cukup menyerahkan satu byte; bit-bit bergerak pada kabel tanpa bantuan CPU lebih lanjut, membiarkan CPU bebas melakukan pekerjaan lain secara paralel.

Alternatifnya adalah bit-banging: perangkat lunak melakukan loop pada setiap bit dan mengubah pin GPIO secara langsung untuk menghasilkan gelombang yang sama. Tidak ada periferal hardware yang terlibat -- CPU menggerakkan SCK rendah, mengatur MOSI, menggerakkan SCK tinggi, mengambil sampel MISO, dan seterusnya untuk setiap bit dari setiap byte. Hal itu mengikat CPU untuk seluruh transaksi dan berjalan lebih lambat dari yang dapat dilakukan blok hardware, tetapi bekerja pada pin mana pun dan tidak memerlukan blok hardware yang bebas.

machine.SoftSPI adalah implementasi bit-bang dari API SPI yang sama:

from machine import SoftSPI, Pin

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

Gunakan ini ketika perangkat perlu berada pada pin yang tidak terhubung ke blok SPI hardware, atau ketika semua blok hardware sedang digunakan. 500 kHz adalah batas atas yang nyaman pada sebagian besar kamera; CPU tetap sibuk untuk seluruh transaksi.