class SPI -- โปรโตคอลบัส Serial Peripheral Interface (ฝั่งคอนโทรลเลอร์)

SPI เป็นโปรโตคอลอนุกรมซิงโครนัสที่ขับเคลื่อนโดยคอนโทรลเลอร์ ในระดับฮาร์ดแวร์ บัสประกอบด้วย 3 สาย: SCK, MOSI, MISO หลายดีไวซ์สามารถแชร์บัสเดียวกันได้ แต่ละดีไวซ์ควรมีสัญญาณที่ 4 แยกต่างหากคือ CS (Chip Select) เพื่อเลือกดีไวซ์ที่ต้องการสื่อสารด้วยบนบัส การจัดการสัญญาณ CS ควรทำในโค้ดของผู้ใช้ (ผ่านคลาส machine.Pin)

มีทั้งการใช้งาน SPI แบบฮาร์ดแวร์และซอฟต์แวร์ผ่านคลาส SPI และ SoftSPI SPI แบบฮาร์ดแวร์ใช้การสนับสนุนฮาร์ดแวร์พื้นฐานของระบบในการอ่าน/เขียน ซึ่งมักมีประสิทธิภาพและรวดเร็ว แต่อาจมีข้อจำกัดเรื่องพินที่ใช้ได้ SPI แบบซอฟต์แวร์ใช้การ bit-bang และสามารถใช้กับพินใดก็ได้ แต่ไม่มีประสิทธิภาพเท่า คลาสเหล่านี้มีเมธอดเดียวกันและต่างกันหลักในวิธีการสร้าง

ตัวอย่างการใช้งาน:

from machine import SPI, Pin

spi = SPI(0, baudrate=400000)           # Create SPI peripheral 0 at frequency of 400kHz.
                                        # Depending on the use case, extra parameters may be required
                                        # to select the bus characteristics and/or pins to use.
cs = Pin(4, mode=Pin.OUT, value=1)      # Create chip-select on pin 4.

try:
    cs(0)                               # Select peripheral.
    spi.write(b"12345678")              # Write 8 bytes, and don't care about received data.
finally:
    cs(1)                               # Deselect peripheral.

try:
    cs(0)                               # Select peripheral.
    rxdata = spi.read(8, 0x42)          # Read 8 bytes while writing 0x42 for each byte.
finally:
    cs(1)                               # Deselect peripheral.

rxdata = bytearray(8)
try:
    cs(0)                               # Select peripheral.
    spi.readinto(rxdata, 0x42)          # Read 8 bytes inplace while writing 0x42 for each byte.
finally:
    cs(1)                               # Deselect peripheral.

txdata = b"12345678"
rxdata = bytearray(len(txdata))
try:
    cs(0)                               # Select peripheral.
    spi.write_readinto(txdata, rxdata)  # Simultaneously write and read bytes.
finally:
    cs(1)                               # Deselect peripheral.

คอนสตรักเตอร์

class machine.SPI(id: int, baudrate: int = 1000000, *, polarity: int = 0, phase: int = 0, bits: int = 8, firstbit: int = MSB, sck: Pin | None = None, mosi: Pin | None = None, miso: Pin | None = None)

สร้างออบเจกต์ SPI บนบัสที่กำหนด id ค่าของ id ขึ้นอยู่กับพอร์ตและฮาร์ดแวร์ที่ใช้ ค่า 0, 1 ฯลฯ มักใช้เพื่อเลือกบล็อก SPI ฮาร์ดแวร์หมายเลข #0, #1 ฯลฯ

เมื่อไม่มีพารามิเตอร์เพิ่มเติม ออบเจกต์ SPI จะถูกสร้างแต่ยังไม่เริ่มต้น (มีการตั้งค่าจากการเริ่มต้นครั้งล่าสุด ถ้ามี) หากมีอาร์กิวเมนต์เพิ่มเติม บัสจะถูกเริ่มต้น ดูพารามิเตอร์การเริ่มต้นใน init

เมธอด

init(baudrate: int = 1000000, *, polarity: int = 0, phase: int = 0, bits: int = 8, firstbit: int = SPI.MSB, sck: Pin | None = None, mosi: Pin | None = None, miso: Pin | None = None) None

เริ่มต้นบัส SPI ด้วยพารามิเตอร์ที่กำหนด:

  • baudrate คืออัตราสัญญาณนาฬิกา SCK

  • polarity มีค่าได้ 0 หรือ 1 ซึ่งคือระดับที่สายนาฬิกาจะอยู่ในสถานะพัก

  • phase มีค่าได้ 0 หรือ 1 เพื่อสุ่มตัวอย่างข้อมูลที่ขอบนาฬิกาแรกหรือที่สองตามลำดับ

  • bits คือความกว้างเป็นบิตของการถ่ายโอนแต่ละครั้ง ฮาร์ดแวร์ทุกตัวรับประกันว่ารองรับค่า 8 เท่านั้น

  • firstbit มีค่าได้ SPI.MSB หรือ SPI.LSB

  • sck, mosi, miso คือออบเจกต์พิน (machine.Pin) ที่ใช้สำหรับสัญญาณบัส สำหรับบล็อก SPI ฮาร์ดแวร์ส่วนใหญ่ (ตามที่เลือกด้วยพารามิเตอร์ id ในคอนสตรักเตอร์) พินจะถูกกำหนดตายตัวและเปลี่ยนไม่ได้ ในบางกรณี บล็อกฮาร์ดแวร์อนุญาตให้เลือกชุดพินทางเลือก 2-3 ชุด การกำหนดพินแบบสุ่มทำได้เฉพาะกับไดรเวอร์ SPI แบบ bitbanging (id = -1)

ในกรณีของ SPI ฮาร์ดแวร์ ความถี่นาฬิกาจริงอาจต่ำกว่าอัตราบอดที่ขอ ขึ้นอยู่กับฮาร์ดแวร์ของแพลตฟอร์ม อัตราจริงสามารถตรวจสอบได้โดยการพิมพ์ออบเจกต์ SPI

deinit() None

ปิดบัส SPI

read(nbytes: int, write: int = 0x00) bytes

อ่านจำนวนไบต์ที่กำหนดโดย nbytes ขณะเขียนไบต์เดี่ยวที่กำหนดโดย write อย่างต่อเนื่อง คืนค่าออบเจกต์ bytes ที่มีข้อมูลที่อ่านมา

readinto(buf: bytearray, write: int = 0x00) None

อ่านลงในบัฟเฟอร์ที่กำหนดโดย buf ขณะเขียนไบต์เดี่ยวที่กำหนดโดย write อย่างต่อเนื่อง คืนค่า None

write(buf: bytes) None

เขียนไบต์ที่บรรจุอยู่ใน buf คืนค่า None

write_readinto(write_buf: bytes, read_buf: bytearray) None

เขียนไบต์จาก write_buf ขณะอ่านลงใน read_buf บัฟเฟอร์สามารถเป็นตัวเดียวกันหรือต่างกันก็ได้ แต่ทั้งสองต้องมีความยาวเท่ากัน คืนค่า None

ค่าคงที่

MSB: int

ส่งให้ firstbit เพื่อส่ง/รับบิตที่มีนัยสำคัญมากที่สุดก่อน (การเรียงลำดับที่พบบ่อยที่สุด)

LSB: int

ส่งให้ firstbit เพื่อส่ง/รับบิตที่มีนัยสำคัญน้อยที่สุดก่อน

class SoftSPI -- บัส SPI แบบซอฟต์แวร์จำลอง

คลาส SoftSPI ใช้งาน SPI โดยการ bit-bang พิน GPIO ตามอำเภอใจ เปิดเผยพื้นผิวเมธอดเดียวกับ SPI เพื่อให้โค้ดที่มีอยู่ซึ่งกำหนดเป้าหมายเป็น SPI ฮาร์ดแวร์สามารถเปลี่ยนไปใช้ซอฟต์แวร์ได้ด้วยการเปลี่ยนแค่คอนสตรักเตอร์ ใช้เมื่อพินที่ต้องการไม่ได้ต่อสายกับบล็อก SPI ฮาร์ดแวร์ เมื่อต้องการบัสฮาร์ดแวร์มากกว่าที่มี หรือเมื่ออุปกรณ์ต่อพ่วงต้องการ clock phasing ที่ไม่ใช่มาตรฐานซึ่งฮาร์ดแวร์ผลิตไม่ได้

คอนสตรักเตอร์

class machine.SoftSPI(baudrate: int = 500000, *, polarity: int = 0, phase: int = 0, bits: int = 8, firstbit: int = MSB, sck: Pin | None = None, mosi: Pin | None = None, miso: Pin | None = None)

สร้างออบเจกต์ SPI แบบซอฟต์แวร์ ต้องระบุ sck, mosi และ miso -- ไม่มีการเลือกพินโดยปริยาย ดู SPI.init() สำหรับความหมายของพารามิเตอร์อื่น ๆ ค่าเริ่มต้น baudrate ต่ำกว่า SPI ฮาร์ดแวร์เนื่องจาก bit-bang loop มีค่าใช้จ่ายสูงกว่า

เมธอด

init(baudrate: int = 500000, *, polarity: int = 0, phase: int = 0, bits: int = 8, firstbit: int = SoftSPI.MSB, sck: Pin | None = None, mosi: Pin | None = None, miso: Pin | None = None) None

เริ่มต้นบัส SPI ซอฟต์แวร์ใหม่ด้วยพารามิเตอร์ที่กำหนด อาร์กิวเมนต์ที่ส่งมาเท่านั้นที่จะถูกอัปเดต ส่วนที่เหลือจะคงค่าเดิมไว้ ดู SPI.init() สำหรับความหมายของแต่ละอาร์กิวเมนต์

deinit() None

ปล่อยพิน GPIO ที่ไดรเวอร์ bit-bang ใช้อยู่และหยุดขับเคลื่อนบัส

read(nbytes: int, write: int = 0x00) bytes

อ่าน nbytes ไบต์ขณะเขียนไบต์เดี่ยว write อย่างต่อเนื่อง คืนค่าออบเจกต์ bytes ที่มีข้อมูลที่รับมา

readinto(buf: bytearray, write: int = 0x00) None

อ่านลงใน buf ขณะเขียนไบต์เดี่ยว write อย่างต่อเนื่อง คืนค่า None

write(buf: bytes) None

เขียน buf ลงบัส ไบต์ที่รับมาจะถูกทิ้ง

write_readinto(write_buf: bytes, read_buf: bytearray) None

เขียน write_buf และอ่านลงใน read_buf พร้อมกัน บัฟเฟอร์ทั้งสองต้องมีความยาวเท่ากัน สามารถเป็นบัฟเฟอร์เดียวกันได้

ค่าคงที่

MSB: int

ส่งให้ firstbit เพื่อส่ง/รับบิตที่มีนัยสำคัญมากที่สุดก่อน

LSB: int

ส่งให้ firstbit เพื่อส่ง/รับบิตที่มีนัยสำคัญน้อยที่สุดก่อน