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.

TMS320F28377D: 使用28377d(作为主机)的spi通信接口与其他芯片开发板进行通信,无FIFO模式,在禁用loopback模式后,TXBUF依然和RXBUF的值保持一致,而并未接收到从机的返回数据

Part Number: TMS320F28377D

unsigned char trans[6] = {0xAA,0xC3,0x00,0xA2,0x00,0x24}; //所要发送的信息
void spi_xmit(Uint16 a); //发送一个数据
void Ready_Config(); //从机芯片ready标志位,此位读到1表明从机已经准备好,才可以与从机进行通信
void SPI_RXbuff(unsigned char *buff,unsigned int len);
void SPI_TXbuff(unsigned char *buff,unsigned int len);
unsigned char cmd_result[2] = {0x00}; //所要接收的返回信息存放数组,目前为0

void main(void)
{
    Ready_Config();

//TI官方spi loopback例程,给出的初始化
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xS_SysCtrl.c file.
   InitSysCtrl();

// Step 2. Initialize GPIO:
// This example function is found in the F2837xS_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
   InitGpio();  // Skipped for this example
// Setup only the GP I/O only for SPI-A functionality
// This function is found in F2837xS_Spi.c
   InitSpiaGpio();

// Step 3. Clear all __interrupts and initialize PIE vector table:
// Disable CPU __interrupts
   DINT;

// Initialize PIE control registers to their default state.
// The default state is all PIE __interrupts disabled and flags
// are cleared.
// This function is found in the F2837xS_PieCtrl.c file.
   InitPieCtrl();

// Disable CPU __interrupts and clear all CPU __interrupt flags:
   IER = 0x0000;
   IFR = 0x0000;

// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the __interrupt
// is not used in this example.  This is useful for debug purposes.
// The shell ISR routines are found in F2837xS_DefaultIsr.c.
// This function is found in F2837xS_PieVect.c.
   InitPieVectTable();

// Step 4. Initialize the Device Peripherals:
   InitSpi();        // init SPI
//发送接收
   SPI_TXbuff(trans,6);
   DELAY_US(10);
  SPI_RXbuff(cmd_result,2);
}

//各函数定义
void spi_xmit(Uint16 a)
{
    //while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG);
    SpiaRegs.SPITXBUF=a;    // SPI Serial Output Buffer Register
    //while(SpiaRegs.SPISTS.bit.INT_FLAG != 1);
}

//Ready信号接收引脚设置为GPIO10
void Ready_Config()
{
     EALLOW;
     GpioCtrlRegs.GPAMUX1.bit.GPIO10 = 0; //i/o
    // GpioCtrlRegs.GPAPUD.bit.GPIO10 = 0; //内部上拉
     GpioCtrlRegs.GPADIR.bit.GPIO10 = 0; //input
     EDIS;
}


//接收缓冲区数据函数
void SPI_RXbuff(unsigned char *buff,unsigned int len)  //uint8_t uint32_t
{
    unsigned int i = 0;
    if(len==0)  return;
    while(GpioDataRegs.GPADAT.bit.GPIO10 == 0);//等待从机就绪
    GpioDataRegs.GPACLEAR.bit.GPIO11 = 1; //拉低片选信号
    DELAY_US(10);
    for(i=0;i<len;i++)
    {
         buff[i] = (SpiaRegs.SPIRXBUF>>8);
         DELAY_US(10);
     }
    GpioDataRegs.GPASET.bit.GPIO11 = 1;//拉高片选信号
}

//发送缓冲区数据函数
void SPI_TXbuff(unsigned char *buff,unsigned int len)  //uint8_t uint32_t
{
    unsigned int i = 0;
    if(len==0)  return;
    while(GpioDataRegs.GPADAT.bit.GPIO10 == 0);//等待从机就绪
    GpioDataRegs.GPACLEAR.bit.GPIO11 = 1; //拉低片选信号
    DELAY_US(10);
    for(i=0;i<len;i++)
    {
        spi_xmit(buff[i]);  //左移8位,适应MSB的要求
        DELAY_US(10);
     }
    GpioDataRegs.GPASET.bit.GPIO11 = 1;//拉高片选信号
}


//spi.c文件里spi配置
#include "F2837xD_device.h"
#include "F2837xD_Examples.h"

//
// Calculate BRR: 7-bit baud rate register value
// SPI CLK freq = 115200 Hz
// LSPCLK freq  = CPU freq / 4  (by default)
// BRR          = (LSPCLK freq / SPI CLK freq) - 1
//
#if CPU_FRQ_200MHZ
#define SPI_BRR        ((200E6 / 4) / 115200) - 1
#endif

#if CPU_FRQ_150MHZ
#define SPI_BRR        ((150E6 / 4) / 115200) - 1
#endif

#if CPU_FRQ_120MHZ
#define SPI_BRR        ((120E6 / 4) / 115200) - 1
#endif

//
// InitSPI - This function initializes the SPI to a known state
//
void InitSpi(void)
{
    // Initialize SPI-A

    // Set reset low before configuration changes
    // Clock polarity (0 == rising, 1 == falling)
    // 8-bit character
    // disable loop-back
    SpiaRegs.SPICCR.bit.SPISWRESET = 0;
    SpiaRegs.SPICCR.bit.CLKPOLARITY = 0;
    SpiaRegs.SPICCR.bit.SPICHAR = (8-1);
    SpiaRegs.SPICCR.bit.SPILBK = 0;

    // Enable master (0 == slave, 1 == master)
    // Enable transmission (Talk)
    // Clock phase (0 == normal, 1 == delayed)
    // SPI interrupts are  disabled
    SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1;
    SpiaRegs.SPICTL.bit.TALK = 1;
    SpiaRegs.SPICTL.bit.CLK_PHASE = 0;
    SpiaRegs.SPICTL.bit.SPIINTENA = 0;

    // Set the baud rate
    SpiaRegs.SPIBRR.bit.SPI_BIT_RATE = SPI_BRR;

    // Set FREE bit
    // Halting on a breakpoint will not halt the SPI
    SpiaRegs.SPIPRI.bit.FREE = 1;

    // Release the SPI from reset
    SpiaRegs.SPICCR.bit.SPISWRESET = 1;
}

//
// InitSpiGpio - This function initializes GPIO pins to function as SPI pins.
//               Each GPIO pin can be configured as a GPIO pin or up to 3
//               different peripheral functional pins. By default all pins come
//               up as GPIO inputs after reset.
//
//               Caution:
//               For each SPI peripheral
//               Only one GPIO pin should be enabled for SPISOMO operation.
//               Only one GPIO pin should be enabled for SPISOMI operation.
//               Only one GPIO pin should be enabled for SPICLK  operation.
//               Only one GPIO pin should be enabled for SPISTE  operation.
//               Comment out other unwanted lines.
//
void InitSpiGpio()
{
   InitSpiaGpio();
}

//
// InitSpiaGpio - Initialize SPIA GPIOs
//
void InitSpiaGpio()
{
   EALLOW;

    //
    // Enable internal pull-up for the selected pins
    //
    // Pull-ups can be enabled or disabled by the user.
    // This will enable the pullups for the specified pins.
    // Comment out other unwanted lines.
    //
    GpioCtrlRegs.GPAPUD.bit.GPIO16 = 0;  // Enable pull-up on GPIO16 (SPISIMOA)
//  GpioCtrlRegs.GPAPUD.bit.GPIO5 = 0;   // Enable pull-up on GPIO5 (SPISIMOA)
    GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0;  // Enable pull-up on GPIO17 (SPISOMIA)
//  GpioCtrlRegs.GPAPUD.bit.GPIO3 = 0;   // Enable pull-up on GPIO3 (SPISOMIA)
    GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0;  // Enable pull-up on GPIO18 (SPICLKA)
    GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0;  // Enable pull-up on GPIO19 (SPISTEA)

    //
    // Set qualification for selected pins to asynch only
    //
    // This will select asynch (no qualification) for the selected pins.
    // Comment out other unwanted lines.
    //
    GpioCtrlRegs.GPAQSEL2.bit.GPIO16 = 3; // Asynch input GPIO16 (SPISIMOA)
//  GpioCtrlRegs.GPAQSEL1.bit.GPIO5 = 3;  // Asynch input GPIO5 (SPISIMOA)
    GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 3; // Asynch input GPIO17 (SPISOMIA)
//  GpioCtrlRegs.GPAQSEL1.bit.GPIO3 = 3;  // Asynch input GPIO3 (SPISOMIA)
    GpioCtrlRegs.GPAQSEL2.bit.GPIO18 = 3; // Asynch input GPIO18 (SPICLKA)
    GpioCtrlRegs.GPAQSEL2.bit.GPIO19 = 3; // Asynch input GPIO19 (SPISTEA)

    //
    //Configure SPI-A pins using GPIO regs
    //
    // This specifies which of the possible GPIO pins will be SPI functional
    // pins.
    // Comment out other unwanted lines.
    //
    GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1; // Configure GPIO16 as SPISIMOA
//  GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 2;  // Configure GPIO5 as SPISIMOA
    GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1; // Configure GPIO17 as SPISOMIA
//  GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 2;  // Configure GPIO3 as SPISOMIA
    GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1; // Configure GPIO18 as SPICLKA
    GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1; // Configure GPIO19 as SPISTEA


    //使能软件片选信号 GPIO11
    GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 0;  // 设置为普通的GPIO模式
    GpioCtrlRegs.GPADIR.bit.GPIO11 = 1;   //设置为输出i/o


    EDIS;
}

//
// End of file
//

debug结果为:

可以看出RXBUF的值就是TXBUF的值左移8位(用16进制可以很明显观察到,比如TXBUF是0x24,RXBUF就是0x2400)。loopback模式已经禁用,可是还是感觉数据传输处于loopback模式里,没有真正接收到从机返回值。

以上问题无论是否启用中断模式都是一样存在。

  • RXBUF数据与TXBUF数据左移八位的问题参考论坛内其他问题的讨论,将发送函数改为:

    void SPI_TXbuff(unsigned char *buff,unsigned int len) 
    {
        unsigned int i = 0;
        if(len==0)  return;
        while(GpioDataRegs.GPADAT.bit.GPIO10 == 0);//等待从机就绪
        GpioDataRegs.GPACLEAR.bit.GPIO11 = 1; //拉低片选信号
        DELAY_US(10);
        for(i=0;i<len;i++)
        {
            spi_xmit((Uint16)buff[i]<<8);  //左移8位,适应MSB的要求
            //delay_loop();
            DELAY_US(10);
         }
        GpioDataRegs.GPASET.bit.GPIO11 = 1;//拉高片选信号
    }

    即强制移位8位再送入缓冲区。但这样以来出现了新的问题,就是SPIDAT寄存器的值一直为0,好像没有在发送了,RXBUF的值也一直为0,怀疑是没有发送出去,从机也没有返回值进来。

    不知道这样是什么原因呢?难道是spi设置上出了什么问题?

  • 你好,你这里len的值是多少?我没找到相关的定义。

  • 您好,这里的len是一个函数形参,void SPI_RXbuff(unsigned char *buff,unsigned int len),在调用函数的时候付给函数。比如这个语句:SPI_TXbuff(trans,6); 6就是len的值

  • 能否使用单步调试看看程序能否进入到各个函数?以及观察一下SPI相关buffer的值是如何变化?这样可以帮助定位问题。

  • 可以的,以下是我调试的结果,事实上,程序流程进行的还算顺利,我先附上我程序的完整版,我在上面的问题里附上的实际上只是一次发送接收的过程的代码,事实上我完整的程序需要几次发送和接收。

    我在测试第一次发送和接收时就出现了问题SPIDAT始终为0的问题,调试程序时,我运行至SPI_TXbuff(cmd_loadkey,6)函数,函数成功进行至spi_xmit(Uint16 a)函数,并将要发送的数据发送给SPITXBUF,但遗憾的是,SPITXBUF里的值并没有出现在SPIDAT里面,SPIDAT的值始终保持为0。

    在用SPI_TXbuff(cmd_loadkey,6)发送完一个长度为6的数组数据后,SPITXBUF的值为cmd_loadkey数组数据的最后一个值0x24(值得注意的是由于spi_xmit(Uint16 a)需要的参数长度为16位,而我所要发送的数组元素均为长度8位的数据,且dsp的spi发送默认采取MSB方式,所以根据网上资料的建议,将数据左移8位并进行强制类型转换进行发送(spi_xmit((Uint16)buff[i]<<8);),所以SPITXBUF数据显示为9216(0x2400))。但是SPIDAT寄存器始终为0,当然SPIRXBUF也没有接收的返回值,始终为0。

    附上调试的图片和完整代码

  • 你这里的配置看起来是没有什么问题的,你的从机是什么?相关的接线是否正确?

    RXBUF数据与TXBUF数据左移八位的问题参考论坛内其他问题的讨论

    这里你参考的是哪篇帖子?

    能否分享下你的工程?

  • 您好,我的从机是一款加密芯片,相关接线目前排查正确的,而且我个人感觉如果是SPIDAT寄存器始终为0的话,可能是28377d这边的问题,因为从spitxbuf传送至spidat的过程按理来说应该是28377d芯片内部自行进行的过程。

    我的工程要怎样分享给您呢?好像论坛上只能发布代码?

    参考的帖子链接为e2echina.ti.com/.../f28335-spi-w25q64

  • 抱歉今天没有关注邮箱,回复稍迟,请见谅。

  • 没关系。你可以将工程文件压缩后发上来。

  • 您看这个工程文件您能否打开?

    另外,我在前期在网上搜集dsp spi通讯的资料时并没有找到spi发送接收一个数组数据的例程,不知道如果要用spi发送和接收一个数组的数据,除了我目前工程里使用的for循环将数组数据一个个的送入发送缓冲区进行发送,接收时也利用for循环从接收缓冲区里将接收的数组数据一个个读取至存放接收信息的数组内的这种方法还有什么更好的方法吗?同时,我这种接收方法是否会导致数据丢失呢,因为从机发回的数据也是数组,但缓冲区一次只能接收一个数据,这样是否可能会导致接收数据丢失?又该如何避免呢?

  • 您看这个工程文件您能否打开?

    我这边打开后这些文件都缺失了:

    我这边一般也是采取和您一样的方法接收数组。

    我怀疑可能是您工程中的配置问题或是代码中有些细节问题我没有注意到,所以想直接看看您的工程。

    您在loopback模式下调试有问题吗?您可以先在loopback模式中调试一下。

  • 您好,我是在TI官网给出的spi_loopback例程基础上改的程序,此前进行过loopback测试,测试没有问题的,测试结果如下(sdata=0x0100,rdata=1,因为发送数据是8位的,按照MSB规则,发出的是0x01,测试是成功的)。loopback调试结果图为:

    工程文件打不开可能是存在一些路径问题,我将整个例程文件发给您吧。

    解压后一直点进去,到这个界面时点击:

    再找到spi_loopback程序就可以了:

  • 好的,我这边尝试下能否复现您的问题。

  • 好的,谢谢您

  • 您好,不知您那边是否能复现这个问题?我在我的开发板上,即使不接从机芯片进行数据发送依然存在这个SPIDAT寄存器内数值始终为0的问题。这是否可以说明这个问题是出在DSP开发板这一侧呢?另外,像这种问题依照您的经验来看,一般是DSP开发板的硬件问题还是程序软件配置问题呢?

  • 你好,我需要一点时间调试您的程序。

    一般是DSP开发板的硬件问题还是程序软件配置问题呢

    我认为一般情况下是软件上的问题。

  • 好的,那拜托您啦,谢谢~

  • 你好,我这边出了点问题,所以暂时无法测试您的程序。

    我咨询了一下资深工程师,这边建议您使用示波器观察下SPI的4个引脚的信号看看是否有什么缺失,以及这边认为您的spi初始化可能有些问题,建议按照TRM第18.4.2章节来初始化spi。

    TRM链接:www.ti.com/.../spruhm8j.pdf

  • 好的,但是我这个SPI的设置是在TI官网例程下改的。而且也是按照这个文档里进行设置的,刚刚我又检查了一遍,好像是与这个18章里面的流程一致的

    唯一的问题是,咱们官网28377d的SPI例程是否是我上面所发的那样?我看您给的链接中,TRM 18.5.1里面给出了一个例程位置,但是我并没有找到这里的这个路径,可以看到这里例程的命名与我所下载的例程命名不同,他这里是spi_ex1_loopback.c,我那个是spi_loopback_cpu1

    以下是我spi.c文件的设置,好像流程上与18.4.2设置的是一样的。唯一的区别是OVERRUNFLAG和INTFLAG没有单独置0,但是根据手册,这两个标志位会在SPISWRESET置0时被清除,所以也是被置0过的了,而且即使加上这两个标志位置0的语句,SPIDAT内数据为0的问题也并未消失。

    您看我这个spi.c的设置中存在问题吗?如果没有的话还可能有什么地方的设置会影响SPI呢?(事实上其他地方的设置我也并没有动过,全部都是例程的设置)

    //###########################################################################
    //
    // FILE:   F2837xD_Spi.c
    //
    // TITLE:  F2837xD SPI Initialization & Support Functions.
    //
    //###########################################################################
    // $TI Release: F2837xD Support Library v210 $
    // $Release Date: Tue Nov  1 14:46:15 CDT 2016 $
    // $Copyright: Copyright (C) 2013-2016 Texas Instruments Incorporated -
    //             http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "F2837xD_device.h"
    #include "F2837xD_Examples.h"
    
    //
    // Calculate BRR: 7-bit baud rate register value
    // SPI CLK freq = 500 kHz
    // LSPCLK freq  = CPU freq / 4  (by default)
    // BRR          = (LSPCLK freq / SPI CLK freq) - 1
    //
    #if CPU_FRQ_200MHZ
    #define SPI_BRR        ((200E6 / 4) / 500000) - 1
    #endif
    
    #if CPU_FRQ_150MHZ
    #define SPI_BRR        ((150E6 / 4) / 500000) - 1
    #endif
    
    #if CPU_FRQ_120MHZ
    #define SPI_BRR        ((120E6 / 4) / 500000) - 1
    #endif
    
    //
    // InitSPI - This function initializes the SPI to a known state
    //
    void InitSpi(void)
    {
        // Initialize SPI-A
        SpiaRegs.SPISTS.bit.BUFFULL_FLAG = 0;
        SpiaRegs.SPISTS.bit.INT_FLAG = 0;
        // Set reset low before configuration changes
        // Clock polarity (0 == rising, 1 == falling)
        // 16-bit character
        // Enable loop-back
        SpiaRegs.SPICCR.bit.SPISWRESET = 0;
        SpiaRegs.SPICCR.bit.CLKPOLARITY = 0;
        SpiaRegs.SPICCR.bit.SPICHAR = (8-1);
        SpiaRegs.SPICCR.bit.SPILBK = 0;
    
        // Enable master (0 == slave, 1 == master)
        // Enable transmission (Talk)
        // Clock phase (0 == normal, 1 == delayed)
        // SPI interrupts are disabled
        SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1;
        SpiaRegs.SPICTL.bit.TALK = 1;
        SpiaRegs.SPICTL.bit.CLK_PHASE = 0;
        SpiaRegs.SPICTL.bit.SPIINTENA = 0;
    
        // Set the baud rate
        SpiaRegs.SPIBRR.bit.SPI_BIT_RATE = SPI_BRR;
    
        // Set FREE bit
        // Halting on a breakpoint will not halt the SPI
        SpiaRegs.SPIPRI.bit.FREE = 1;
    
        // Release the SPI from reset
        SpiaRegs.SPICCR.bit.SPISWRESET = 1;
    }
    
    //
    // InitSpiGpio - This function initializes GPIO pins to function as SPI pins.
    //               Each GPIO pin can be configured as a GPIO pin or up to 3
    //               different peripheral functional pins. By default all pins come
    //               up as GPIO inputs after reset.
    //
    //               Caution:
    //               For each SPI peripheral
    //               Only one GPIO pin should be enabled for SPISOMO operation.
    //               Only one GPIO pin should be enabled for SPISOMI operation.
    //               Only one GPIO pin should be enabled for SPICLK  operation.
    //               Only one GPIO pin should be enabled for SPISTE  operation.
    //               Comment out other unwanted lines.
    //
    void InitSpiGpio()
    {
       InitSpiaGpio();
    }
    
    //
    // InitSpiaGpio - Initialize SPIA GPIOs
    //
    void InitSpiaGpio()
    {
       EALLOW;
    
        //
        // Enable internal pull-up for the selected pins
        //
        // Pull-ups can be enabled or disabled by the user.
        // This will enable the pullups for the specified pins.
        // Comment out other unwanted lines.
        //
        GpioCtrlRegs.GPAPUD.bit.GPIO16 = 0;  // Enable pull-up on GPIO16 (SPISIMOA)
    //  GpioCtrlRegs.GPAPUD.bit.GPIO5 = 0;   // Enable pull-up on GPIO5 (SPISIMOA)
        GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0;  // Enable pull-up on GPIO17 (SPISOMIA)
    //  GpioCtrlRegs.GPAPUD.bit.GPIO3 = 0;   // Enable pull-up on GPIO3 (SPISOMIA)
        GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0;  // Enable pull-up on GPIO18 (SPICLKA)
        GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0;  // Enable pull-up on GPIO19 (SPISTEA)
    
        //
        // Set qualification for selected pins to asynch only
        //
        // This will select asynch (no qualification) for the selected pins.
        // Comment out other unwanted lines.
        //
        GpioCtrlRegs.GPAQSEL2.bit.GPIO16 = 3; // Asynch input GPIO16 (SPISIMOA)
    //  GpioCtrlRegs.GPAQSEL1.bit.GPIO5 = 3;  // Asynch input GPIO5 (SPISIMOA)
        GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 3; // Asynch input GPIO17 (SPISOMIA)
    //  GpioCtrlRegs.GPAQSEL1.bit.GPIO3 = 3;  // Asynch input GPIO3 (SPISOMIA)
        GpioCtrlRegs.GPAQSEL2.bit.GPIO18 = 3; // Asynch input GPIO18 (SPICLKA)
        GpioCtrlRegs.GPAQSEL2.bit.GPIO19 = 3; // Asynch input GPIO19 (SPISTEA)
    
        //
        //Configure SPI-A pins using GPIO regs
        //
        // This specifies which of the possible GPIO pins will be SPI functional
        // pins.
        // Comment out other unwanted lines.
        //
        GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1; // Configure GPIO16 as SPISIMOA
    //  GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 2;  // Configure GPIO5 as SPISIMOA
        GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1; // Configure GPIO17 as SPISOMIA
    //  GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 2;  // Configure GPIO3 as SPISOMIA
        GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1; // Configure GPIO18 as SPICLKA
        GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1; // Configure GPIO19 as SPISTEA
    
        EDIS;
    }
    
    //
    // End of file
    //
    

  • 您好,刚刚我进行了一下关闭loopback模式,将MOSI和MISO短接进行测试,结果是可以收发数据,结果如下:

    这样的结果是否说明可能是从机硬件上存在问题?

  • 的确有可能。我这边向工程师跟进下。

  • 好的,谢谢您~,祝新年快乐。

  • 不客气呀,新年快乐

  • 对了,我想可能要向您说明我们这边目前已经排除的一些错误,之前的波特率设置可能有些问题,SPI时钟频率应该设为1MHZ及以下,但是在我们采用了正确波特率设置后也并未解决该通信问题。在这里我们分别尝试了1E6和0.5E6两个值,对应SPI时钟频率为标准的1MHZ和更低的0.5MHZ,均未解决问题,改动如图:

    另外,我们这边也检查了CPOL和CPHA的设置,两者均为0,是没有问题的。如下图所示:

    目前的现象是:从机芯片接上后和没有连接从机芯片的情况下,均是SPIDAT始终为0。只有loopback自测,或者将dsp的MOSI和MISO短接时,才能正常将SPITXBUF中数据送入SPIDAT,并接收到相同的数据。

    期待您这边工程师的回复。

  • 你好,参考下工程师的回复:

    感谢您到目前为止的回复和有关您发现的信息。所以重申一下(如果我的理解是错误的,请纠正):

    • 当您关闭内部环回模式并将 MISO/MOSI 线路从外部连接在一起时,您可以看到预期的通信
    • 当您关闭内部环回模式并使用 4 条 SPI 线连接到从机(没有短接 MISO 到 MOSI)尝试将数据传输到加密芯片(并从芯片接收数据)时,您会看到 SPITXBUF 有数据并且 SPIDAT 始终为 0

    如果您在执行外部环回(MISO/MOSI 短路)时看到发送了正确的数据,则说明您的代码运行正常,并且您有正确的 SPI 通信成功。在主机模式下,当您向TXBUF写入数据时,数据将转移到SPIDAT并立即在MOSI线路上发送出去,因此您将不会在SPIDAT中看到传输的数据。相反,SPIDAT将显示从MISO线移入的接收数据。因此,如果从设备发送零,这就是您在 SPIDAT 中看到的内容。

    因此,为了帮助调试,请使用示波器/分析仪查看 4 条 SPI 线路上的活动。具体来说,我们需要检查 SPICLK 是否显示脉冲,并检查 MISO 线路,以查看从设备是否正在向主设备发送数据或发送零。

  • 同时,您可以看到厂家给出的基于STM32的例程中,在发送与接收之间都存在一些延时,这样的延时在dsp 28377d的spi通讯中是可以被允许的吗?会不会造成接收数据的丢失呢?

  • 另外有一个大方向上的问题,

    建议您可以咨询下对接您的FAE。其他问题我会跟进到工程师。

  • 好的,谢谢您啦~

  • 你好,

    之前的问题可能是由于spi是一个全双工通讯协议,要接收必须先发送,要发送也会接收,所以我修改了一下程序,把发送和接收合并了一下。程序改动如下:

    好的,我跟进下

    这样的延时在dsp 28377d的spi通讯中是可以被允许的吗?会不会造成接收数据的丢失呢?

    没有必要使用延时,但是如果你使用了FIFO模式,则最好在写入 TXBUF 之前检查发送 FIFO 中是否有空间,并在读RXBUFF之前检查 FIFO 中是否有预期数量的完整/有效数据。这可以通过一个简单的“while”循环来完成,该循环在写入/读取之前检查 FIFO (TXFFST 和 RXFFST 位)。 

  • 通过今天下午的测试,我发现这个发送函数会在它实际开始运行之前(我使用了单步调试)发送出一个2048给从机,这并非我计划内的发送,不知道为什么会出现这一数据。

    没有必要使用延时,但是如果你使用了FIFO模式,则最好在写入 TXBUF 之前检查发送 FIFO 中是否有空间,并在读RXBUFF之前检查 FIFO 中是否有预期数量的完整/有效数据。这可以通过一个简单的“while”循环来完成,该循环在写入/读取之前检查 FIFO (TXFFST 和 RXFFST 位)。 

    嗯嗯,我在新增的数据发送接收函数的接收数据之前进行了RXFFST的检查,至于您说的TXFFST的检查我似乎不太理解是什么意思?您能详细讲讲吗?

  • 噢对了,这个2048的数据发送出现在spi_fifo_init()函数执行完之后

    spi.c的设置没有变化

  • 重新上电后则会在运行完spi_fifo_init()后显示发送了59377,接收了19640,均无任何意义。再次运行时会像上述一样运行完spi_fifo_init()后发送2048

  • 您好,问题已经解决了,我更换了信号线,可能是之前的杜邦线存在老化故障的原因,之前也有很多问题可能是因为这个原因。当然,这个调试过程中最为显著的问题是,之前没有认识到全双工通信接收的同时必须发送这一问题,导致没有发送的话,主机就没有时钟信号给从机,通信就无法进行。

    最后,十分感谢您一直以来的认真回复,谢谢您啦~

  • 嗯嗯好的,不客气呀,问题解决就好。