SPI

通常会发现 串行外设接口(SPI)器件需要快速的数据传输速率。 SPI非常适合高带宽用例,如外部非易失性存储器和图形显示器。除了 I2C 之外,许多传感器器件都支持SPI。

SPI是同步 串行接口,这意味着它依赖于共享时钟信号来同步器件之间的数据传输。主器件控制时钟信号的触发,所有其他连接的外设称为从站器件。每个设备连接到同一组数据信号以形成总线

理论上,SPI的数据传输速率仅受主机切换时钟信号的速度的限制。时钟速度通常在16MHz至25MHz范围内。这种高速共享时钟允许SPI外设更快速地传输数据,误码率比 UART 少。

""

SPI支持全双工 数据传输,意味着主机和从机可以同时交换信息。为了支持全双工传输,总线必须提供以下单独的信号,这使SPI成为最小的4-Wire接口:

  • 主机 Out 从机 In (MOSI)
  • 主机 In 从机 Out (MISO)
  • 共享时钟信号(CLK)
  • 公共接地参考(GND)

SPI支持沿同一总线连接的多个从设备。与 I2C 不同,从器件使用硬件进行寻址。每个从器件需要一个外部 芯片选择 信号,以允许主器件将该特定器件寻址作为数据传输目标。如果仅使用单个从器件,则不需要此信号。

管理设备连接

为了打开与特定SPI从站的连接,您需要知道总线的唯一名称。在开发初始阶段,或将应用程序移植到新硬件时,使用 getSpiBusList()PeripheralManagerService 发现所有可用的设备名称:

PeripheralManagerService manager = new PeripheralManagerService();
List<String> deviceList = manager.getSpiBusList();
if (deviceList.isEmpty()) {
    Log.i(TAG, "No SPI bus available on this device.");
} else {
    Log.i(TAG, "List of available devices: " + deviceList);
}

支持多个硬件芯片选择的SPI控制器将会将每个可用从站端口报告为单独的设备名称。例如,在同一SPI总线上支持CS0CS1CS2 的电路板将从 getSpiBusList() 中返回类似于“SPI0.0”“SPI0.1”“SPI0.2” 的名称。

知道目标名称后,使用 PeripheralManagerService 连接到该设备。完成与外围设备通信后,关闭连接以释放资源。此外,在现有连接关闭之前,您无法打开与设备的新连接。要关闭连接,请使用设备的close() 方法。

public class HomeActivity extends Activity {
    // SPI Device Name
    private static final String SPI_DEVICE_NAME = ...;

    private SpiDevice mDevice;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Attempt to access the SPI device
        try {
            PeripheralManagerService manager = new PeripheralManagerService();
            mDevice = manager.openSpiDevice(SPI_DEVICE_NAME);
        } catch (IOException e) {
             Log.w(TAG, "Unable to access SPI device", e);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mDevice != null) {
            try {
                mDevice.close();
                mDevice = null;
            } catch (IOException e) {
                Log.w(TAG, "Unable to close SPI device", e);
            }
        }
    }
}

配置时钟和数据模式

在与SPI总线建立连接后,配置数据传输速率和操作模式,使同一总线上的从设备相匹配。要使数据传输成功,总线上的所有器件都必须具有相同的时钟和数据格式。

  1. 设置SPI模式,定义时钟信号的极性和相位。您选择的模式基于三个属性:

    1. 空闲电平: 当没有数据传输时,时钟信号的电平(低或高)。
    2. Leading Edge: 每个时钟脉冲的前沿。
    3. Trailing Edge:在每个时钟脉冲中与前沿相反的转换。
    4. </ol>

      支持以下模式:

      • MODE0 - 时钟信号空闲低,数据在前沿时钟边沿传输。
      • MODE1 - 时钟信号空闲低,数据在后续时钟边沿传输
      • MODE2 - 时钟信号空闲高,数据在前沿时钟边沿传输
      • MODE3 - 时钟信号空闲高,数据在后续时钟边沿传输
      • </ul> </li>

      • 设置以下 SpiDevice 参数:

        • 频率 - 以Hz为单位指定共享时钟信号。时钟信号功能将在设备硬件上有所不同。您应该在设置此值之前验证特定设备的支持频率。
        • 对齐 - 指定每个字节中通过总线传输的各个位的顺序。这也被称为数据的字节数。默认情况下,数据将首先以最高有效位(MSB)发送。
        • 位/字 - 配置在给定从站的切换选择行之间的一次传输的位数。默认值为8位/字。
        • </ul> </li> </ol>

          以下代码配置模式0,16MHz时钟,每字8位,MSB的SPI连接:

          public void configureSpiDevice(SpiDevice device) throws IOException {
              // Low clock, leading edge transfer
              device.setMode(SpiDevice.MODE0);
          
              device.setFrequency(16000000);     // 16MHz
              device.setBitsPerWord(8);          // 8 BPW
              device.setBitJustification(false); // MSB first
          }
          

          传输数据

          SPI支持半双工和全双工数据传输。大多数应用程序应该使用半双工 write()read() 方法与从设备交换数据。

          // Half-duplex data transfer
          public void sendCommand(SpiDevice device, byte[] buffer) throws IOException {
              // Shift data out to slave
              device.write(buffer, buffer.length);
          
              // Read the response
              byte[] response = new byte[32];
              device.read(response, response.length);
              ...
          }
          

          要执行全双工交换,请改用 transfer() 方法。该方法接受两个读写缓冲区。写缓冲区包含要发送给从站的数据,而读缓冲区为空,并接受来自从站的数据。

          数据长度必须小于或等于最小缓冲区大小。通常全双工传输缓冲区大小相等。

          // Full-duplex data transfer
          public void sendCommand(SpiDevice device, byte[] buffer) throws IOException {
              byte[] response = new byte[buffer.length];
              device.transfer(buffer, response, buffer.length);
              ...
          }
          

          results matching ""

            No results matching ""