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.

[参考译文] TMS320F28027F:主器件(TMS320F28027)在 SPI (3线制模式)中向一个受控器件写入3个字节

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1330190/tms320f28027f-master-tms320f28027-writing-3-bytes-in-spi-3-wire-mode-to-an-slave

器件型号:TMS320F28027F
主题中讨论的其他器件:DAC70501

大家好!  

我无法配置 SPI 3线模式、即简单地向 SPI 从器件发送3个字节。  

已正确配置 GPIO:

SysCtrlRegs.PCLKCR0.bit.SPIAENCLK = 1;	// SPI-A
//--------------------------------------------------------------------------------------
//  GPIO-16 - PIN FUNCTION = SPISIMO-A
	GpioCtrlRegs.GPAPUD.bit.GPIO16 = 0;   // Enable pull-up on GPIO16 (SPISIMOA)
	GpioCtrlRegs.GPAQSEL2.bit.GPIO16 = 3; // Asynch input GPIO16 (SPISIMOA)
	GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1;	// 0=GPIO,  1=SPISIMO-A,  2=Resv,  3=TZ2
//--------------------------------------------------------------------------------------
//  GPIO-17 - PIN FUNCTION = SPISOMI-A (as GPIO not needed in 3-wire mode)
	GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 0;	// 0=GPIO,  1=SPISOMI-A,  2=Resv,  3=TZ3
	GpioCtrlRegs.GPADIR.bit.GPIO17 = 1;		// 1=OUTput,  0=INput
	GpioDataRegs.GPACLEAR.bit.GPIO17 = 1;	// uncomment if --> Set Low initially
//--------------------------------------------------------------------------------------
//  GPIO-18 - PIN FUNCTION = SPICLK-A
	GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0;   // Enable pull-up on GPIO18 (SPICLKA)
	GpioCtrlRegs.GPAQSEL2.bit.GPIO18 = 3; // Asynch input GPIO18 (SPICLKA)
	GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1;	// 0=GPIO,  1=SPICLK-A,  2=SCITX-A,  3=XCLKOUT
//--------------------------------------------------------------------------------------
//  GPIO-19 - PIN FUNCTION = SPISTE-A
	GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0;   // Enable pull-up on GPIO19 (SPISTEA)
	GpioCtrlRegs.GPAQSEL2.bit.GPIO19 = 3; // Asynch input GPIO19 (SPISTEA)
	GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1;	// 0=GPIO,  1=SPISTE-A,  2=SCIRX-A,  3=ECAP1
//--------------------------------------------------------------------------------------

然后、我为 TX 用3个级别初始化 FIFO、我不需要 RX (也许是肯定的?):  

void spi_fifo_init()
{
// Initialize SPI FIFO registers
    //SpiaRegs.SPIFFTX.all=0xE040;
    SpiaRegs.SPIFFTX.bit.SPIRST=1;      //SPI FIFO can resume transmit or receive
    SpiaRegs.SPIFFTX.bit.SPIFFENA=1;    //SPI FIFO enhancements are enabled
    SpiaRegs.SPIFFTX.bit.TXFFINTCLR =1; // Clear TXFIFO interrupt flag
    SpiaRegs.SPIFFTX.bit.TXFFIENA = 0;  // TXFIFO interrupt disabled
    SpiaRegs.SPIFFTX.bit.TXFFIL =3;     //3 levels for TXFIFO Interrupt (no needed)
    SpiaRegs.SPIFFTX.bit.TXFIFO =1;     //Release transmit FIFO from reset.

    //SpiaRegs.SPIFFRX.all=0x2044;

    SpiaRegs.SPIFFRX.bit.RXFFOVFCLR = 1;   // CLEAR OV rX flag
    SpiaRegs.SPIFFRX.bit.RXFFINTCLR =1;     //b6 Clear SPIFFRX flag
    SpiaRegs.SPIFFRX.bit.RXFFIENA = 0;      //b5 RXFIFO interrupt disabled
    SpiaRegs.SPIFFRX.bit.RXFFIL=0;          //level bits for RXFIFO Interrupt (no needed)
    SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1;   //b13 Re-enable receive FIFO operation.

    SpiaRegs.SPIFFCT.all=0x0;               //The next word in the TX FIFO buffer is transferred to
                                            //SPITXBUF immediately upon completion of transmission of the
                                            //previous word.
}

然后 SPI 初始化:

void spi_init_DAC70501()
{
    //SpiaRegs.SPICCR.all =0x000F;                 // Reset on, rising edge, 16-bit char bits


    //SpiaRegs.SPICTL.all =0x0006;                 // Enable master mode, normal phase,
                                                 // enable talk, and SPI int disabled.
    SpiaRegs.SPICCR.bit.SPISWRESET = 0; //Reset SPI before configuration
    SpiaRegs.SPICCR.bit.CLKPOLARITY =1; //falling edge
    SpiaRegs.SPICCR.bit.SPICHAR =7; //8-bit char bits


    SpiaRegs.SPICTL.bit.MASTER_SLAVE=1; //Enable master mode
    SpiaRegs.SPICTL.bit.CLK_PHASE=1; // phase with delay
    SpiaRegs.SPICTL.bit.TALK = 1;    // Enable Transmit path
    SpiaRegs.SPICTL.bit.OVERRUNINTENA = 0; //disbale overrun interruption
    SpiaRegs.SPICTL.bit.SPIINTENA = 0;     ////disable SPIinterruption

    SpiaRegs.SPIBRR =127;   // SPI Baud Rate=LSPCLK/(SPIBRR+1)  LSPCLK=CPU_FREQ/4
                                // 15MHz/(127+1)=117kHz
                                // 15MHz/(14+1)=1MHz
    SpiaRegs.SPIPRI.bit.TRIWIRE=1; //3-wire SPI mode enable
                                   //(The unused pin SPISOMI is free for GPIO)

    //SpiaRegs.SPICCR.all =0x009F;                 // Relinquish SPI from Reset
    SpiaRegs.SPICCR.bit.SPISWRESET = 1;           // Relinquish SPI from Reset
    SpiaRegs.SPIPRI.bit.FREE = 1;                // Set so breakpoints don't disturb xmission


}

最后、这是我将 在主程序中定期调用的 TX 函数:

/**********************************************************************
* Function: spi_xmit()
*
* Description: Transmit 16bit to SPIA using 3-Wire Mode Transmit
* When the master transmits, it receives the data it
* transmits (because SPISIMOx and SPISOMIx are connected
*  internally in 3-wire mode). Therefore, the junk data received
*  must be cleared from the receive buffer every time data is transmitted.
**********************************************************************/
void spi_xmit(char a)
{

Uint16 data= (Uint16)(a<<8);
Uint16 dummy;

    SpiaRegs.SPICTL.bit.TALK = 1; // Enable Transmit path
    SpiaRegs.SPITXBUF = data; // Master transmits data
    while(SpiaRegs.SPISTS.bit.INT_FLAG !=1) {} // Waits until data rx’d
    dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself
    SpiaRegs.SPITXBUF = data; // Master transmits data
    while(SpiaRegs.SPISTS.bit.INT_FLAG !=1) {} // Waits until data rx’d
    dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself
    SpiaRegs.SPITXBUF = data; // Master transmits data
    while(SpiaRegs.SPISTS.bit.INT_FLAG !=1) {} // Waits until data rx’d
    dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself
}

我可以在示波器中检查第一个字节已发送、但之后通信会被阻止。  

如果没有3线制模式或 FIFO、我就能够顺利发送2个字节(没有阻塞)。  

我做错了什么? 通过 SPI 向外部从器件发送3个字节的正确方法是什么?

提前感谢。  

此致  

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

    您好!

    如果您说通信被"阻止"、您是说代码卡在"while"循环中、等待 INT_flag 设置为1吗? 或者、您能否详细说明一下含义?

    您是否还能提供一些示波器捕获 SPI 线路上的行为、以便我们可以查看该行为?

    艾里森

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

    尊敬的 Allison:  

    是的、您答对了、分块是由于行:

    while (SpiaRegs.SPISTS.bit.INT_flag!=1){}//等待数据接收

    删除它后、我可以看到3个字节已正确发送。

    void spi_xmit(char a)
    {
    
        SpiaRegs.SPICTL.bit.TALK = 1; // Enable Transmit path
        SpiaRegs.SPITXBUF = (Uint16)(0x03<<8); // Master transmits data
        dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself
        SpiaRegs.SPITXBUF = (Uint16)(0x01<<8); // Master transmits data
        dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself
        SpiaRegs.SPITXBUF = (Uint16)(0x00<<8); // Master transmits data
        dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself
    }

    数据(红色)和时钟(蓝色)

    SPISTE 线路(红色)和时钟(蓝色)。  

    看起来现在是正确发送3个字节。 但是、DAC (SPI 从器件)似乎没有反应。 可以是 SPI 的极性和相位吗? 从 DAC 规格来看、我认为它是带延迟的下降沿。 可能是错了吗?  

    感谢您的帮助  

    此致  

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

    您好!

    很高兴听到数据似乎正在正确发送! 简单解释一下:

    • 如果您 不是 通过使用 FIFO、SPISTS 位可用于检测传输是否完成。
      • 由于您处于 FIFO 模式、但尝试使用 SPISTS、因此我认为这就是您在该"while"循环中被挂起的原因
    • 如果您 远近 使用 FIFO、您可以使用 SPIFFRxRXFFST 以检测 SPI 何时完成传输。 由于 SPI 是移位寄存器、因此当接收器收到预期数量的数据时、您便知道发送器已完全传输数据。

    通常、最佳做法是检查其中之一(取决于您处于 FIFO 模式还是非 FIFO 模式)、以 确保传输不会被覆盖/损坏

    至于时钟、从您所连接的图像来看、我觉得数据会在时钟的上升沿传输并在时钟的下降沿锁存、 这表明 F28027时钟极性应该为0、相位应该为0。 从器件 TRM 第8.3.6节 SPI 时钟方案中、这将是 "无延迟的上升沿。 SPI 在 SPICLK 信号的上升沿上发送数据、而在 SPICLK 信号的下降沿上接收数据。' 请告诉我使用时钟模式是否会改变行为!  

    此致、

    艾里森

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

    尊敬的 Allison:  

    您对时钟极性和相位没有任何疑问。 它现在与"无延迟的上升沿"一起工作非常完美。

    关于 SPI 配置、我会复制并粘贴我的最终配置、以帮助其他用户、并澄清一些疑问。 我的目标是作为主器件向 SPI 从器件(在本例中为 DAC 70501)传输3个字节:

    配置 SPI 引脚并启用 SPI 时钟  

    GPIO 配置为 SPI 3线(GPIO-17免费用于其他用途) :  

    GPIO-16 - PIN 功能= SPISIMO-A

    -GPIO-18 - PIN 功能= SPICLK-A

    - GPIO-19 - PIN 功能= SPISTE-A

    SPI FIFO 配置:

    /**********************************************************************
    * Function: spi_fifo_init_DAC70501()
    *
    * Description: Sets the SPI fifo configuration for the DAC70501
    * - Enable FIFO enhancement
    * - No interruptions
    **********************************************************************/
    void spi_fifo_init_DAC70501()
    {
    // Initialize SPI FIFO registers
        //SpiaRegs.SPIFFTX.all=0xE040;
        SpiaRegs.SPIFFTX.bit.SPIRST=1;      //SPI FIFO can resume transmit or receive
        SpiaRegs.SPIFFTX.bit.SPIFFENA=1;    //SPI FIFO enhancements are enabled
        SpiaRegs.SPIFFTX.bit.TXFFINTCLR =1; // Clear TXFIFO interrupt flag
        SpiaRegs.SPIFFTX.bit.TXFFIENA = 0;  // TXFIFO interrupt disabled
        SpiaRegs.SPIFFTX.bit.TXFFIL =0;     //levels for TXFIFO Interrupt (no needed)
        SpiaRegs.SPIFFTX.bit.TXFIFO =1;     //Release transmit FIFO from reset.
    
        //SpiaRegs.SPIFFRX.all=0x2044;
        SpiaRegs.SPIFFRX.bit.RXFFOVFCLR = 1;   // CLEAR OV rX flag
        SpiaRegs.SPIFFRX.bit.RXFFINTCLR =1;     //b6 Clear SPIFFRX flag
        SpiaRegs.SPIFFRX.bit.RXFFIENA = 0;      //b5 RXFIFO interrupt disabled
        SpiaRegs.SPIFFRX.bit.RXFFIL=0;          //level bits for RXFIFO Interrupt (no needed)
        SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1;   //b13 Re-enable receive FIFO operation.
    
        SpiaRegs.SPIFFCT.all=0x0;               //The next word in the TX FIFO buffer is transferred to
                                                //SPITXBUF immediately upon completion of transmission of the
                                                //previous word.
    }
    

    SPI  配置:

    /**********************************************************************
    * Function: spi_init_DAC70501()
    *
    * Description: Initializes spi on the piccolo for DAC70501 SPI specs
    * - CLOCK polarity and Phase:
    *    data is being transmitted on the rising edge of the clock and latched
    *    on the falling edge of the clock, which would indicated that the F28027
    *    clock polarity should be 0 and phase should be 0.
    *    From the device TRM section 8.3.6 SPI Clocking Schemes, this would be
    *    "Rising Edge Without Delay.
    *    The SPI transmits data on the rising edge of the SPICLK signal and
    *    receives data on the falling edge of the SPICLK signal."
    *  - 8 bit char--> each transmitted word is configured to be a byte (8 bits)
    *  - 3-wire SPI mode enable:
    *       When the master transmits, it receives the data it
    *       transmits (because SPISIMOx and SPISOMIx are connected
    *       internally in 3-wire mode). Therefore, the junk data received
    *       must be cleared from the receive buffer every time data is transmitted.
    
    * GPIOs are initialised in Gpio.c and CLOCKs in InitSysCtrl()
    **********************************************************************/
    void spi_init_DAC70501()
    {
        //SpiaRegs.SPICCR.all =0x000F;                 // Reset on, rising edge, 16-bit char bits
    
    
        //SpiaRegs.SPICTL.all =0x0006;                 // Enable master mode, normal phase,
                                                     // enable talk, and SPI int disabled.
        SpiaRegs.SPICCR.bit.SPISWRESET = 0; //Reset SPI before configuration
        SpiaRegs.SPICCR.bit.CLKPOLARITY =0; //rising edge
        SpiaRegs.SPICCR.bit.SPICHAR =7; //8-bit char bits
    
    
        SpiaRegs.SPICTL.bit.MASTER_SLAVE=1; //Enable master mode
        SpiaRegs.SPICTL.bit.CLK_PHASE=0; // phase without delay
        SpiaRegs.SPICTL.bit.TALK = 1;    // Enable Transmit path
        SpiaRegs.SPICTL.bit.OVERRUNINTENA = 0; //disbale overrun interruption
        SpiaRegs.SPICTL.bit.SPIINTENA = 0;     ////disable SPIinterruption
    
        SpiaRegs.SPIBRR =14;        // SPI Baud Rate=LSPCLK/(SPIBRR+1)  LSPCLK=CPU_FREQ/4
                                    // 15MHz/(127+1)=117kHz
                                    // 15MHz/(14+1)=1MHz
        SpiaRegs.SPIPRI.bit.TRIWIRE=1; //3-wire SPI mode enable
                                       //(The unused pin SPISOMI is free for GPIO)
    
        //SpiaRegs.SPICCR.all =0x009F;                 // Relinquish SPI from Reset
        SpiaRegs.SPICCR.bit.SPISWRESET = 1;           // Relinquish SPI from Reset
        SpiaRegs.SPIPRI.bit.FREE = 1;                // Set so breakpoints don't disturb xmission
    
    

    3. SPI 传输功能:

    /**********************************************************************
    * Function: DAC70501_setVoltage_SPI()
    *
    * Description: Sets the output voltage to a fraction of source vref.  (Value
                can be 0..16383  (0-0x3FFF))
                output:
                    The 14-bit value representing the relationship between
                    the DAC's input voltage and its output voltage.
    
    **********************************************************************/
    void DAC70501_setVoltage_SPI(uint16_t output)
    {
    uint16_t data;
    uint16_t dummy;
    
        data = (uint16_t)(output<<2);     //shift to the left DAC_data reads 14bits left-aligned
    
    char byte1=DAC70501_DAC_DATA;           //command value in this case 0x08
    char byte2=(char) ((data >> 8) & 0xFF);// DAC DATA MSB
    char byte3=(char) (data);
    
        SpiaRegs.SPITXBUF = (Uint16)(byte1<<8); // Master transmits data
        dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself
        SpiaRegs.SPITXBUF = (Uint16)(byte2<<8); // Master transmits data
        dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself
        SpiaRegs.SPITXBUF = (Uint16)(byte3<<8); // Master transmits data
        dummy = SpiaRegs.SPIRXBUF; // Clears junk data from itself
        while(SpiaRegs.SPIFFRX.bit.RXFFST !=1) {}
    }

    在最后一个函数中、是对 SPIFFRX 的检查。 可以删除 RXFFST 位、以及以下行:

    "虚拟= SpiaRegs. SPIRXBUF;//自行清除无用数据"

    我不知道为什么、但在没有这些线路的情况下、SPI 传输功能工作正常。 我还在 示波器中检查 SPISTE 线路、它运行良好、在3字节传输前设置为低电平、在3字节传输后立即设置为高电平。  

    这是我不理解的:

     MCU 如何识别它必须仅传输3个字节? 我刚刚将 SPICHAR 配置为8位字符位、但未将 FIFO 级别设置为任何。  

    此致