【问题标题】:Why if we have to read/write using SPI we have to do like this?为什么如果我们必须使用 SPI 读/写我们必须这样做?
【发布时间】:2021-12-12 02:33:32
【问题描述】:

我有一个关于 SPI 总线的问题。我经常在一些图书馆看到 我找到了,但我不明白它是如何工作的。

我找到的一个库中的快速示例。 SPI写作:

static void nRF24_WriteRegister(uint8_t reg, uint8_t val)
{
    uint8_t tmp[2];

    tmp[0] = NRF24_CMD_W_REGISTER | reg;
    tmp[1] = val;

    NRF24_CSN_LOW;

    nRF24_SendSpi(tmp, 2);

    NRF24_CSN_HIGH;
}

它是如何工作的,如果我们将相同的帧寄存器(我们正在写入)和数据 到这个寄存器?

但对我来说更令人困惑的是从 SPI 读取:

static uint8_t nRF24_ReadRegister(uint8_t reg)
{
    uint8_t result;

    reg = NRF24_CMD_R_REGISTER | reg;

    NRF24_CSN_LOW;
    nRF24_SendSpi(&reg, 1);
    nRF24_ReadSpi(&result, 1);
    NRF24_CSN_HIGH;

    return result;
}

为什么我们必须先发送一些信息然后再阅读?

【问题讨论】:

    标签: embedded stm32 spi


    【解决方案1】:

    SPI 设备包含一组寄存器。每个寄存器都有一个地址和一个值。寄存器值可以由主机读取和/或写入。 SPI 设备需要知道主设备正在读/写哪个寄存器地址。所以协议是主机首先写入寄存器地址,然后读取/写入寄存器值。有关可用寄存器和读/写协议的详细信息,请参阅器件数据表。

    在您的第一个示例中,nRF24_SendSpi(tmp, 2); 写入两个字节,首先是寄存器地址,然后是寄存器值。

    在第二个示例中,nRF24_SendSpi(&reg, 1); 写入一个字节,即寄存器地址。然后nRF24_ReadSpi(&result, 1); 读取一个字节,寄存器值。

    如果协议不是从写入寄存器地址开始的,那么 SPI 设备将不知道主设备正在尝试读取/写入哪个寄存器。

    【讨论】:

    • 天哪,现在有多清晰。非常感谢!
    【解决方案2】:

    SPI slave不产生时钟信号,只有master。所以 Slave 传输任何东西都需要来自 Master 的时钟信号。这就是为什么 Master 必须发送 dummy data 来为 Slave 生成​​时钟信号的原因。

    【讨论】:

      【解决方案3】:

      您的问题可能是关于特定设备的行为,而不是一般的 SPI。但是首先回答:

      为什么我们必须先发送一些信息然后再阅读?

      在这种情况下,您发送的“信息”是一个指定要读取的寄存器的命令。

      SPI 是一个“主/从”通信接口。从设备不能自行发起通信。 SPI 设备包含一个移位寄存器。在时钟沿,一位从 MOSI (Master-Out/Slave-In) 移入寄存器,一位从寄存器移出到 MISO (Master-In/Slave-Out)。主设备驱动时钟,因此要从设备读取,主设备必须将数据输入设备,以便从设备输出设备。这本质上是一种“双工”操作(即数据同时输入和输出。即使您只想读取,也必须写入,并且通常通过在 MOSI 上发送“虚拟”数据来完成。

      所以在你的第二个片段中:NRF24_CMD_R_REGISTER | reg 是一个读取寄存器索引reg 的命令。数据输出将是发送命令时移位寄存器中的任何内容,因此不会是实际读取的结果,因为尚未收到该命令。当设备接收到完整的命令时,它会将寄存器reg中的值加载到移位寄存器中,然后必须通过第二次总线操作读取数据,该总线操作会将虚拟数据计时到 MOSI以便从 MOSI 中检索读取指令的结果。

      关于:

      如果我们将数据放入同一个帧寄存器(我们正在写入)和数据到这个寄存器,它是如何工作的?

      在关联片段中,包含:NRF24_CMD_W_REGISTER | reg 的第一个字节是一个命令,它表示:将以下字节值写入寄存器reg。包含val 的第二个字节是要写入reg 的数据。当nRF24_SendSpi(tmp, 2); 被调用时,两个字节都在 MOSI 上通过时钟 SCLK 线 16 次发送。

      署名CBurnett来自https://en.wikipedia.org/wiki/Serial_Peripheral_Interface#/media/File:SPI_8-bit_circular_transfer.svg

      【讨论】:

      • 你的解释也非常非常好。谢谢楼主!
      • 你的图片在黑暗主题中看起来很有趣。使用 alpha 通道时要小心 :-)
      • @0andriy - 是的 - 对我来说也很有趣 - 不是我的形象(如署名所示)。我不会花太多时间在上面。我想如果你选择使用黑暗模式,这些事情就会发生。无论如何,这对electronics.stackexchange.com 来说确实是一个可能的问题。有合适的图here但未指定使用权限。
      猜你喜欢
      • 2020-07-17
      • 1970-01-01
      • 1970-01-01
      • 2019-04-17
      • 2022-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多