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.

[参考译文] SPI 移位寄存器和 RXbuffer 问题

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1113024/spi-shift-register-and-rxbuffer-problems

主题中讨论的其他器件:TMS320F28055TMS320F28035
大家好、
我有2个通过 SPI 连接的控制器、一个是主控制器、另一个是从控制器。 
当我向从器件发送数据时、数据到达 SPIDAT 移位寄存器。
然后、数据应该被转发到 SPIRXBUF 缓冲区。
我还必须说、我发送了2个8位。
当我尝试发送数据时、它总是到达 SPIDAT 移位寄存器中、在调试模式下可以看到该寄存器、但数据并不总是在 SPIRXBUF 中、有时它会将数据推入、有时甚至不会完全推入。
它大约工作4次、然后是1次、它不再工作。 有人能告诉我问题所在。

感谢你的帮助。

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

    Markus、您好!  

    请提供更多信息。  此设计中使用了哪些 TI 器件?  

    方框图会非常有用。

    谢谢、

    ~Leonard   

      

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

    void SPI_init (void)

    //SpiaRegs.SPICCR.ALL = 0x0007;//数据在上升沿就绪)、环回关闭、8位数据
    SpiaRegs.SPICTL.ALL = 0x000E;//正常 SPI 时钟方案(上升沿锁存数据)主器件,4引脚选项,无中断
    SpiaRegs.SPICTL.bit.CLK_PHASE = 1;//1.
    SpiaRegs.SPIBRR = 0x0077;//BateRate 0.5MHz

    SpiaRegs.SPICCR.ALL = 0x0087;//SPI 已准备好发送或接收下一个字符。 测试发送16位0x0087

    SpiaRegs.SPICCR.bit.CLKPOLARITY = 0;//0
    SpiaRegs.SPIPRI.bit.FREE = 1;

    这是我使用 TMS320F28055的主器件的代码

    void SPI_init (void)

    SpiaRegs.SPICCR.bit.SPISWRESET = 0;
    //SpiaRegs.SPICCR.ALL = 0x0007;//数据在上升沿就绪)、环回关闭、8位数据

    //SpiaRegs.SPICTL.ALL = 0x000E;//正常 SPI 时钟方案(上升沿锁存数据)主器件,4引脚选项,无中断
    SpiaRegs.SPICTL.ALL = 0x000A;//8//正常 SPI 时钟方案(上升沿锁存器中的数据)从器件、4引脚选项、无中断
    SpiaRegs.SPICTL.bit.CLK_PHASE = 1;//1.
    SpiaRegs.SPIBRR = 0x0077;//BateRate 0.5MHz ist für den Slave nicht noftwendig
    SpiaRegs.SPICCR.ALL = 0x0087;//SPI 已准备好发送或接收下一个字符。
    SpiaRegs.SPICCR.bit.CLKPOLARITY = 0;//0
    SpiaRegs.SPICTL.bit.SPIINTENA=1;
    SpiaRegs.SPICTL.bit.OVERRUNINTENA=1;
    SpiaRegs.SPIPRI.bit.FREE = 1;
    SpiaRegs.SPICCR.bit.SPISWRESET=1;

    这是我的从 器件 TMS320F28035的代码

    我在这里使用一个中断、但我也在没有中断的情况下尝试了它

    uint16_t pdata = 0x1234;

    int dataH、dataL;
    dataH = 0;
    dataL = 0;

    dataH =(pdata >> 8);
    dataL =(pdata & 0x00FF);


    SPI_Xmit (dataH);
    SPI_Xmit (dataL);

    在这种情况下、我发送示例数据时、它是0x1234、当我发送时、它成功到达移位寄存器和缓冲区、但如果我想更频繁地发送、移位寄存器不会将数据完全移入缓冲区。至 检查我同时调试两个微控制器。 顺便说一下、我连续发送8个位、缓冲区大小为16位

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

    控制器通过芯片选择进行连接。然后连接时钟、然后连接 Miso-MISO 和 MOSI-MOSI、因为它应该有2个控制器。芯片选择永久设置为低电平、以便可以传输数据。

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

    我在这里做了一个表、我发送的示例数据是0x1234
    从机和主机下面的数字是我发送数据的次数。您可以看到、当第6个发送时、数据再次正确地位于缓冲区中、但在这两者之间不会将所有数据发送到缓冲区。

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

      

    此图可能会有所帮助。 我从 F2803x 的技术参考手册中得到了这一点。 对于我来说、当我从控制器发送数据时、数据完全在缓冲区中非常重要、因为我想进一步处理数据。 但是、如果我无法确保正确的数据始终送达、那么这很难。

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

    Markus、

    您没有为主器件包含 SPI_xmit ()函数、但必须将8位数据移位到 SPITXBUF 寄存器的 MSB 中。 这是因为 SPITXBUF 将被复制到 SPIDAT 寄存器中、并且 MSB 将首先移出。 在 SPI_xmit()函数中,在写入 SPITXBUF 之前,添加数据<<8。

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

    大家好、Gus、这是我的主器件和从器件函数

    uint16 SPI_xmit (int A)

    uint16 Ret_var = 0;

    SpiaRegs.SPITXBUF =(A << 8);
    while (SpiaRegs.SPISTS.bit.INT_flag = 0);

    RET_var = SpiaRegs.SPIRXBUF << 8;
    返回 Ret_var;

    我解决了从主机向从机发送数据时的问题、数据被捕获在从机中断中。之后、我必须在中断结束时发送 spixmit (0x00)。 如果我再次从主器件发送数据、则 RX 缓冲区中的数据是正确的。但我仍然不知道为什么我必须始终从从器件发送0x00。

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

    Markus、

    从 SPIRXBUF 读取时、不必移位数据。 请参阅下面 SPIDAT 寄存器的图。 只要 SPICLK 处于激活状态、SPI 将在 SIMO 引脚上移动 SPIDAT MSB、同时从 SPIDAT LSB 上的 SOMI 引脚移入数据。 因此、对于8位字符大小、在写入 SPITXBUF 时必须移位数据<<8、但在从 SPIRXBUF 读取时不必移位。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    大家好、Gus、
    也许我们相互误解了。 我想向从器件发送多个16位数据。 当数据到达从器件时、 
    我想将缓冲区中的数据保存在变量中。 我按您所说的数据推送数据<<来自主器件的数据。
    问题是如果您发送多个16位数据、则从机无法全部接受这些数据。 我在每8位后安装一个延迟、这是必要的。
    通过 SPI、主器件传输、从器件同时接收和发送。 因此、我必须从主器件发送数据。
    然后捕获从器件中断中的数据、然后将其存储在变量中并使用00发回16位。
    之后、当我从主器件发送多个数据包时、它可以正常工作。 我认为这是因为移位寄存器、因为从器件、
    否则、始终在每16位后自动发回来自主器件的数据、然后在某个时候移位寄存器中存在垃圾、这会妨碍主器件。
    如果从器件在每个接收到后发回16位00、它就会起作用。 或者、您认为我做了一些错误吗? 我尝试了很多东西,但这就是它的工作方式。你能给我另一个建议吗?
    我第一次通过 SPI 连接了2个控制器。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Markus、

    如果我不能完全理解您的问题、请向您道歉。  请记住、在从器件配置中、在主器件开始生成时钟之前、必须将值预先加载到 SPITXBUF 寄存器中。 否则、从器件 SPI 将发送当时 SPIDAT 寄存器中的任何内容。 但是、您不能将2个8位字符写回 SPITXBUF (除非您启用了 FIFO 模式、我认为您没有启用 FIFO 模式)。 在写入新字符之前、您必须等待前一个8位字符移出。 您可以使用 BUFFULL_FLAG 来确定 SPI 何时为更多数据做好准备。

    这是从器件应遵循的顺序、可能会有所帮助? 我假设这里没有中断。

    1. 等待 BUFFULL_FLAG = 0
    2. 将0x12写入 SPITXBUF => BUFFULL_FLAG、然后应设置为1。
    3. 等待 BUFFULL_FLAG = 0 (主器件需要在此处发送第一个8位字符)
    4. 将0x34写入 SPITXBUF => BUFFULL_FLAG、然后应设置为1。
    5. 重复
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Gus、
    感谢你的帮助。 我没有使用 FIFO 模式。 您知道如何正确配置它吗? 我以前没有使用过它、因为我以前使用过的控制器没有。 我尝试对其进行一次配置、但我没有得到我想要的结果。这就是我没有激活它的原因。 我尝试了 TI 的示例。 FIFO 模式是否具有主要优势、或者它们是否仅具有很小的可见度?

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

    您好、Gus、

    我当前的解决方案是、我从 SPITXBUF (主器件)发送16位、并始终等待标志位 BUFULL_FLAG = 0、正如您所说的。 我将8位传输更改为16位。在从机中、我截取中断中的值。每次我截取中断时、我都会从从从机发送回主机、也以16位的形式发送00、这就是它现在的工作方式。 您是否可以使用 FIFO 模式获得更好的解决方案、因为我对此并不是很熟悉。 请作出解释。

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

    Markus、

    我最近在这里发布了 FIFO 的简要说明:

    https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1112888/explanation-of-fifo-mode-in-spi-tms320f28035/4124567?tisearch=e2e-sitesearch&keymatch=%25252520user%2525253A13605#4124567

    有关更多详细信息、请参阅技术参考手册。  

    [引用 userid="525350" URL"~/support/microcontrollers/C2000-microcontrollers-group/C2000/f/C2000-microcontrollers-forum/1113024/SPI-shift-register-and-rxbuffer-problemes/4130094#413894"]我将8位更改为16位传输。在从从主机中我截取中断中的值,并在每次从主机/16位返回时都是如何操作的。]

    我看到您的方法唯一的缺点是、当您获得中断时、SPI 从器件可能已经移出一个新值(取决于主器件启动下一个字符事务的速度)。 始终存在这种竞争条件、除非您可以修改主代码以在字符之间插入延迟、前提是您的应用程序可以接受这种延迟。  

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

    您好、Gus、
    感谢你的帮助。 我还有一个问题、您知道吗?您是否必须将从器件与主器件同步? 因为主器件不知道从器件何时希望发送数据。 如果我只是与主器件保持计时、它不会同步。 我注意到、我总是从从从器件获取不同的数据、有时它可以工作、有时它会向我发送奇怪的数据、是因为它们需要同步吗?

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

    Markus、

    一旦主器件生成第一个 SPI CLK、从器件必须开始发送数据。 该数据是否有效取决于您的应用程序代码。  

    您可以在 UART 流控制中实现类似于 RTS/CTS 的"边带"信号。 您还可以为数据分配和添加起始字符和结束字符、并让主控方放弃该帧之外的任何数据。 您可以让主器件发送 X 个虚拟字符、并在 X+1字符上期望有效数据。 这实际上取决于您的应用。