class SPI -- 串行外设接口总线协议(控制器端)

SPI 是一种由控制器驱动的同步串行协议。在物理层面上,总线由 3 条线组成:SCK、MOSI、MISO。多个设备可以共享同一条总线。每个设备应有一条独立的第 4 条信号线 CS(片选),用于选择总线上要与之通信的特定设备。CS 信号的管理应在用户代码中进行(通过 machine.Pin 类)。

通过 SPISoftSPI 类,存在硬件和软件两种 SPI 实现。硬件 SPI 利用系统的底层硬件支持来执行读写,通常高效快速,但可能对可使用的引脚有限制。软件 SPI 通过位操作(bit-banging)实现,可用于任何引脚,但效率不及硬件。这些类提供相同的方法,主要区别在于构造方式。

用法示例:

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)

在给定的总线 id 上构造一个 SPI 对象。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.MSBSPI.LSB

  • sckmosimiso 是用于总线信号的引脚(machine.Pin)对象。对于大多数硬件 SPI 块(由构造函数的 id 参数选择),引脚是固定的,无法更改。在某些情况下,硬件块允许为一个硬件 SPI 块使用 2-3 组备选引脚集。只有对于位操作(bitbanging)SPI 驱动(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

在读取数据到 read_buf 的同时写入 write_buf 中的字节。两个缓冲区可以相同也可以不同,但两者长度必须相同。返回 None

常量

MSB: int

传递给 firstbit 以最高有效位优先发送/接收(最常见的顺序)。

LSB: int

传递给 firstbit 以最低有效位优先发送/接收。

class SoftSPI -- 软件模拟的 SPI 总线

SoftSPI 通过对任意 GPIO 引脚进行位操作(bit-banging)来实现 SPI。它公开了与 SPI 相同的方法接口,因此针对硬件 SPI 编写的现有代码只需更改构造函数即可切换到软件实现。当你需要的引脚未连接到硬件 SPI 块时、当你需要的总线数量超过可用的硬件总线时,或当某个外设要求硬件无法产生的非标准时钟相位时,可使用它。

构造函数

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 对象。必须提供 sckmosimiso —— 不存在隐式的引脚选择。有关其他参数的含义,请参阅 SPI.init()。默认的 baudrate 低于硬件 SPI,因为位操作循环的开销更大。

方法

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 引脚并停止驱动总线。

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

在读取数据到 read_buf 的同时写入 write_buf。两个缓冲区必须长度相同;它们可以是别名(指向同一对象)。

常量

MSB: int

传递给 firstbit 以最高有效位优先发送/接收。

LSB: int

传递给 firstbit 以最低有效位优先发送/接收。