This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSPM0G3507:是否有 SPI 控制器示例?

Guru**** 2625255 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1375747/mspm0g3507-is-there-a-spi-controller-example

器件型号:MSPM0G3507

工具与软件:

您好!

我正在尝试找到一个 SPI 通信的示例。 仅找到 BSL_SPI_FLASH_interface、其中 SPI 配置为外设而不是控制器。

SPI 作为控制器是否有任何示例?

最终我的问题是这个。 当 MCU 是 SPI 控制器时、从器件的响应时钟将如何生成?

在用于从器件接收数据的 driverlib API 中、它不会发送虚拟数据来生成时钟。

__STATIC_INLINE uint8_t DL_SPI_receiveData8(SPI_Regs *spi)
{
    return ((uint8_t)(spi->RXDATA));
}

上面的 API 只读取寄存器。
 
谢谢!
起重机
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    一个相当简单的示例是 spi_controller_multibyte_fifo_poll、如下所示:

    https://dev.ti.com/tirex/explore/node?node=A__ALvL6z3rHe7SZbfM4PrMvA__MSPM0-SDK__a3PaaoK__LATEST

    要(仅)接收字节、您需要传输如此多的字节来触发 SPI。 该示例使您似乎必须传输一些有意义的内容、但这些"虚拟"字节可以全部是0xFF、0x00或0x5A。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢 Bruce。

    但从这个示例中、我不知道它在传输数据后是如何接收数据的。

    它只调用 DL_SPI_receiveDataBlocking8()来接收、而不传输任何虚拟数据。  

        /*
         * Wait to receive the SPI data
         * This loop expects SPI_PACKET_SIZE bytes
         */
        for (uint8_t i = 0; i < SPI_PACKET_SIZE; i++) {
            gRxPacket[i] = DL_SPI_receiveDataBlocking8(SPI_0_INST);
        }

    它可能与示例的功能相关。  

    然后、我查看了另一个示例 SPI_CONTROLLER_COMMAND_DATA_CONTROL、该示例更接近我的情况。

    但在这个例子中、它只传输命令、然后不接收任何内容。 我仍然无法了解接收的工作方式。

    我尝试通过发送 API 来提交虚拟数据、然后检查 MISO 线路上来自外设的响应、但外设使用任何数据进行响应似乎无法正常工作。

        CS_ENABLE;
        
        drv_SPI_sendByte(CMD_READ_ID);
        for(i=0; i<9; i++) {
            drv_SPI_sendByte(0); 
            if (DL_SPI_isRXFIFOEmpty(BSL_SPI) == false) {
                drv_SPI_RxData = DL_SPI_receiveData8(BSL_SPI);
                *(data + i) = drv_SPI_RxData;
            }
            else {
                *(data + i) = 0x55;
            }
        }
    
        CS_DISABLE;

     这种方式是否接收正确、因为两个样本都没有显示这一点?

    谢谢!

    起重机

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    SPI 本质上是全双工的、对于您发送的每个字节、您都会收到一个;如果您想要接收一个字节、您必须发送一个字节。 我们指的是"仅传输"和"仅接收"交易、但这些交易仅意味着另一端 对 数据不感兴趣。

    该示例 传输的字节如下:

    > DL_SPI_fillTXFIFO8 (SPI_0_INST、&gTxPacket[0]、SPI_PACKET_SIZE);

    > while (DL_SPI_isBusy (SPI_0_INST));

    将一个字节放入 Tx FIFO 中会立即发送该字节、只要 Tx FIFO 不为空、SPI 就会保持繁忙状态。 到该序列结束时、Rx FIFO 中已经有4 (=SPI_PACKET_SIZE)个字节。 (实际上、它不需要使用"阻止"调用来获取它们。)

    为了简化该示例、作者选择了一个4字节的事务、正好适合 FIFO。 如果您想做更多的事情、代码会变得更复杂一些。 如果您的 drv_spi_sendByte 函数等待完成(DL_SPI_isBusy 正常、或者您可以使用 DL_SPI_receiveDataBlocking8)、我预计 Rx FIFO 检查将始终显示为 non-empty。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    例如、L6470 SPI 步进电机控制器使用 NOP 字节在单字节请求信息命令后接收多字节响应:

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Bruce 和 Keith。

    我确实多接收到一个字节、但所有接收到的数据都是0。

    但现在的主要问题是我需要这样的 CS 信号:

    通过提交虚拟数据、我确实能够得到接收响应的时钟、但我也能得到 像这样每个字节之间不连续的 CS 信号。 这使得外设处于始终等待命令的状态。 我想这就是我只得到0的原因。

    如何生成时钟以便外设响应并使 CS 信号同时保持活动状态?

    然后、从示例中可以看到、用于多字节提交的不连续 CS 也存在。 但 外设在 命令提交期间需要 CS、 如下所示:

    如何实现?

    谢谢!

    起重机

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    它看起来只有3线模式可实现此 CS。

    4线制模式能否正常工作?

    谢谢!

    起重机

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的、我建议使用3线模式、并使用 GPIO 生成 CS (如果您不想重新接线、则您选择的 GPIO 可以是 SPI 单元在4线模式下使用的 GPIO)。 您发布的代码片段似乎在做正确的事情。

    只是要说明:第一个(命令)字节将导致接收字节、您需要读取并丢弃该字节。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、明白了。  

    要接收来自提交的该字节、命令是清除 RxFIFO 非空状态 或清除数据缓冲区、还是一起清除? 在规格书中、我没有看到有关状态更新方式和数据缓冲区更新方式的描述。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    只需读取接收字节并将其丢弃。 可能类似于:

      CS_ENABLE;
      DL_SPI_transmitDataBlocking8(SPI_0_INST, command);
      (void)DL_SPI_receiveDataBlocking8(SPI_0_INST); // Read and throw away 
      DL_SPI_transmitDataBlocking8(SPI_0_INST, 0x5A); // Dummy write (0x5a looks good on a scope)
      response = DL_SPI_receiveDataBlocking8(SPI_0_INST); // Read the result
      CS_DISABLE;

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的、理解。

    尝试了解背后的原因、以便了解当命令有多个字节(序列和数量)时如何读取和丢弃。

    最终发现它可以在命令发送后立即读取和丢弃与命令中提交的字节数相同的字节数。 我想这是它的工作方式。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的、对于例如3字节的"命令"、您可能会(可能)丢弃前3个接收字节。 我建议的模型不是很好地使用 FIFO、但对于短事务来说、这无关紧要。 (对于较长的事务、您应该 考虑 DMA。)

    [这"(可能)"是这些波形出现的位置。 您发布的第一个字节在 Rx 上显示了第一个 Tx 字节期间的平坦线、但这实际上是 Rx 字节、只是不有趣的字节。 同样、在第二个字节期间、Tx 显示为扁平线、但这是虚拟 Tx 字节(它并不是真正的" Hi-Z "、但也可能是)。 对于多字节命令、(理论上)目标可能会在命令完成之前开始发送结果、在这种情况下、其数据表中的波形会反映这一点。]

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的、回答正确。 那些显示"SI"的平线对于 Hi-Z 或来自外设的东西应该是虚的。 在那里放置 Hi-Z 是令人困惑的。  

    我的问题到此结束。 感谢 Bruce 的帮助!

    起重机