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.

[参考译文] TMS320F28379D:SPI 软件 CS

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1577233/tms320f28379d-spi-software-cs

部件号: TMS320F28379D

你好。 我正在开发基于 F28379D 的器件。 它将有大约 10 个或更多的 SPI 从器件。 我想使用 CS 的软件控制。 遗憾的是、似乎没有标准的方法可以做到这一点。 我将使用 FIFO 进行同步传输、并计划在将来实现 DMA + FIFO 传输。 问题是我没有找到能够可靠地表明物理 SPI 传输已完成并且 CS 输出可设置为高电平的中断或寄存器标志。 你也可以 在这个论坛上查看另一张票从十年前与完全相同的问题,但在不同的微控制器. 遗憾的是、没有有效的解决方案。 这是我找到的最好的解决方案。  

bool SPI::transmitSync (const uint8_t *pBuff、uint32_t len、uint32_t TIMEOUT)
  Volatile uint16_t *pTxBuff =(volatile uint16_t *)(mPortBase + SPI_O_TXBUF);

  for(寄存器 uint32_t i = 0;i < len;i++)
  {
    while (SPI_getTxFIFOStatus (mPortBase)== SPI_FIFO_TXFULL){}
    *pTxBuff = pBuff[i]<< 8;
  }

  while (SPI_getTxFIFOStatus (mPortBase)!= SPI_FIFO_TXEMPTY){}

  SPI_resetRxFIFO (mPortBase);

  DELAY_SYSTEM (m8bitsDelay);

  返回 true;
}
 
但它无法稳定工作、在某些情况下、CS 仍会提前触发。  
 
这就是我设置 SPI 的方法。
 
void SPI::init (port_t 端口、uint32_t bitrate、bool 极性 Hi、uint8_t front)
  交换机(端口){
    案例 kPortA:
      mPortBase = SPIA_BASE;
      initGpioPortA();
      initDmaPortA();
      休息;

    Case kPortB:
      mPortBase = SPIB_BASE;
      initGpioPortB();
      initDmaPortB();
      休息;

    Case kPortC:
      mPortBase = spic_base;
      initGpioPortC();
      initDmaPortC();
      休息;

    默认值:
      断言 (false);
      返回;
  }

  spport[port]=此;

  spi_disableModule (mPortBase);

  SPI_TransferProtocol 协议;
  如果(偏振高){
    协议=(前)? SPI_PROT_POL1PHA1:SPI_PROT_POL1PHA0; //模式 3/2.
  }其他{
    协议=(前)? SPI_PROT_POL0PHA1:SPI_PROT_POL0PHA0; //模式 1/0
  }
  
  浮点 rawDelay = 8.0 *(1.0 /((float) bitrate / 10000000.0));
  m8bitsDelay = Calc_number_of_cycles_US (rawDelay < 1.0? 1UL:rawDelay);

  SPI_setConfig (mPortBase、DEVICE_LSPCLK_FREQ、协议、
         SPI_MODE_CONTROLLER、比特率、8);

  spi_disableLoopback (mPortBase);

  spi_setEmulationMode (mPortBase、spi_emulation_stop_after_transmit);

  SPI_enableFIFO (mPortBase);

  SPI_resetTxFIFO (mPortBase);   
  SPI_resetRxFIFO (mPortBase);

  SPI_clearInterruptStatus (mPortBase、SPI_INT_RXFF | SPI_INT_TXFF);
    
  SPI_setFIFO InterruptLevel (mPortBase、
    SPI_FIFO_TXEMPTY、(SPI_RxFIFOLevel)(mkFofoLevel));

  SPI_enableModule (mPortBase);
  SPI_enableTalk (mPortBase);
}
 
请告诉我问题是否有解决方案。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Deric:

    让我看看这个、然后回到您那里。

    此致、

    Delaney

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

    尊敬的 Deric:

    您是尝试向每个从动器件发送可变数量的字节数、还是该值是固定的? 此外、您正在将哪个 FIFO 级别用于 TX FIFO?  

    此致、

    Delaney

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

    嗨、Delaney。
    我不会发送固定数量的字节数。 字节数范围为 1 到 1024。
    将 FIFO 级别设置为 8 (mkFofLevel = 8)。

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

    尊敬的 Deric:

    谢谢您的澄清。  

    我认为当前代码的问题在于、等待 TX FIFO 为空并不一定意味着所有数据都要从 SPIDAT 寄存器移出 — 当 TX FIFO 为空时、最后一个字符仍可能处于移出的过程中。 您是否知道每个从设备将发送哪些数据? 例如、如果它始终为非零、我想您可以等到 SPIDAT 寄存器=零后再使 CS 变为高电平。  

    此致、

    Delaney

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

    嗨、Delaney。  

    这种方法并不总是有效的、因为发送到从器件的数据可能以零结束。

    也许在检查是否有空 FIFO 后检查接收到的字节标志是有意义的? 由于在事务期间、仅在最后一个 SCK 时钟周期之后才会认为接收到一个字节。 我还没有尝试过,也不知道这样的旗帜是否存在。

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

    尊敬的 Deric:

    我看、让我浏览一下、看看是否有这方面的标志。 我还将咨询另一位 SPI 专家、了解他们是否有其他想法。

    此致、

    Delaney

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

    嗨、Delaney。
    是否有任何变化?

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

    尊敬的 Deric:

    对延迟深表歉意。 是否在高速模式下运行? 您是否还能发送您的波形、让我看看它如何使用当前方法运行?

    此致、

    Delaney

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

    嗨、Delaney。
    不、目前我在正常 10MHz 模式下工作。

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

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

    ...

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

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

    这是 EEPROM 驱动程序库操作的一个片段。 如第二个屏幕截图所示、只有在最后一次传输 (P4) 中、CS 在 700ns 后上升、这是一个不错的时间。 在所有其他情况下、时钟周期结束与 CS 上升之间的时间延长了几倍。

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

    这是我当前使用的接收和发送实现。 一旦退出这些功能、CS 将立即停用。  

    bool Spi::transmitSync(const uint8_t *pBuff, uint32_t len)
    {
        volatile uint16_t *pTxBuff = (volatile uint16_t *)(mPortBase + SPI_O_TXBUF);
    
        for(register uint32_t i = 0; i < len; i++)
        {
            while(SPI_getTxFIFOStatus(mPortBase) == SPI_FIFO_TXFULL) {}
            *pTxBuff = pBuff[i] << 8;
        }
    
        while (SPI_getTxFIFOStatus(mPortBase) != SPI_FIFO_TXEMPTY) {}
    
        // SPI_resetRxFIFO(mPortBase);
    
        DELAY_SYSTEM(m8bitsDelay);
    
        return true;
    }
    
    bool Spi::receiveSync(uint8_t *pBuff, uint32_t len)
    {
        //
        // Reset the TX / RX FIFO buffers to default state
        //
        SPI_resetRxFIFO(mPortBase);
        SPI_resetTxFIFO(mPortBase);
    
        uint32_t remainingWords = len;
    
        volatile uint16_t *pTxBuff = (volatile uint16_t *)(mPortBase + SPI_O_TXBUF);
        volatile uint16_t *pRxBuff = (volatile uint16_t *)(mPortBase + SPI_O_RXBUF);
    
        for(register uint32_t i = 0; i < len; i += 16) {
    
            uint32_t length = remainingWords > 16? 16 : remainingWords;
            remainingWords -= length;
    
            for(uint32_t j = 0; j < length; j++) {
                while(SPI_getTxFIFOStatus(mPortBase) == SPI_FIFO_TXFULL) {}
                *pTxBuff = 0;
            }
    
            for(uint32_t j = 0; j < length; j++) {
                while(SPI_getRxFIFOStatus(mPortBase) == SPI_FIFO_RXEMPTY) {}
                pBuff[i + j] = *pRxBuff;
            }
    
        }
    
        DELAY_SYSTEM(m8bitsDelay);
    
        return true;
    }

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

    尊敬的 Deric:

    由于您在 FIFO 模式下运行、因此我认为最好的方法是在最后一个字节写入 SPITXBUF 后直接轮询 SPISTS.BUFFULL_FLAG 标志。 然后、在该标志变为低电平后、等待 x 段时间、然后再次将 CS 拉至高电平。 这个时长 x 应等于在给定波特率设置的情况下移出完整字节所需的时间,并且每次都应相同 — 但是我会对此进行测试以确保这一点。 您只需确保所有此过程不会中断、否则会将所有内容丢弃。 执行需要是确定性的。  

    此外、 此处的链接 是 数据表中包含 SPI 外设时序规格的部分、以供参考。 我来看看这是为了尝试将您的 CS 时序与模块 CS 的时序相匹配。 您还必须与所有从器件一起验证 CLK 和 CS 时序是否符合其规格。  

    此致、

    Delaney