SPI transfer takes too much time - ADuCM350

Hello,

I am trying to create a sine wave generator using a DAC and I communicate wth it over SPI. The problem is that the "adi_SPI_MasterTransfer" function in the ADuCM350 SDK does not allow me to transfer data fast enough.

With the 8MHz clock frequency and only sending 3 bytes per point from a lookup table (256 points max) to the DAC I gant only reach a sine wave of 42Hz.

How could I decrease the time needed to send data ?

Here is my SPI function I use:

void SPI_DAC(uint16_t DACreg)
{
  
  gTransmitBuffer[0] = 0x00;
  gTransmitBuffer[1] = ((uint8_t)((DACreg>>8) & 0xFF));
  gTransmitBuffer[2] = (DACreg & 0xFF);

  gPrologueBuffer[0]             = 0x00;
  transceive.pPrologue            = gPrologueBuffer;
  transceive.PrologueSize         = 0;
  transceive.pTxData              = gTransmitBuffer;
  transceive.pRxData              = gGarbageBuffer;//gReceiveBuffer;
  transceive.DataSize             = 3;
  transceive.bTxIncrement         = true;
  transceive.bRxIncrement         = false;
  
  adi_GPIO_SetLow(ADI_GPIO_PORT_0,ADI_GPIO_PIN_0);
 
  adi_SPI_MasterTransfer(hDevice, &transceive);
  
  adi_GPIO_SetHigh(ADI_GPIO_PORT_0,ADI_GPIO_PIN_0);
}

And here is my SPI initialization

ADI_SPI_RESULT_TYPE initSPI(void)
{
  ADI_SPI_DEV_ID_TYPE  const devID = ADI_SPI_DEVID_0;
  
  ADI_SPI_RESULT_TYPE Result = ADI_SPI_SUCCESS;  /* assume the best */
  ADI_SPI_DEV_GENERIC_SETTINGS_TYPE settings;
      
    *((volatile uint32_t *)REG_GPIO3_GPCON) |= SPI0_SCLK_PORTP3_MUX
     | SPI0_MISO_PORTP3_MUX | SPI0_MOSI_PORTP3_MUX;// | SPI0_CS_PORTP3_MUX;
    
    /* install and enable DMA error interrupt handeling with OSAL */
   // ADI_INSTALL_HANDLER(DMA_ERR_IRQn, DMA_Err_Int_Handler); // BrJ
   // ADI_ENABLE_INT(DMA_ERR_IRQn); // BrJ
  
  /* Initialize SPI */
    if ((Result =  adi_SPI_MasterInit(devID, &hDevice)) != ADI_SPI_SUCCESS) return Result;
    
    /* configure SPI */
    if ((Result = ConfigureSPI(hDevice)) != ADI_SPI_SUCCESS) return Result;

    if ((Result = adi_SPI_GetGenericSettings(hDevice, &settings)) != ADI_SPI_SUCCESS) return Result;

    return ADI_SPI_SUCCESS;
}


ADI_SPI_RESULT_TYPE ConfigureSPI(ADI_SPI_DEV_HANDLE hSpi)
{
  ADI_SPI_RESULT_TYPE Result = ADI_SPI_SUCCESS;  /* assume the best */
    while (1) {

        /* disable DMA (initially) */ 
        if ((Result = adi_SPI_SetDmaMode(hSpi, false)) != ADI_SPI_SUCCESS) return Result;

        /* set blocking mode so DMA transfers complete without need to poll */
        if ((Result = adi_SPI_SetBlockingMode(hSpi, false)) != ADI_SPI_SUCCESS) return Result;
        
        // Set MSB first 
        if ((Result = adi_SPI_SetLsbFirst(hSpi, false)) != ADI_SPI_SUCCESS) return Result;

        /* send zeros if tx SPI underflows*/
        if ((Result = adi_SPI_SetTransmitUnderflow(hSpi, true)) != ADI_SPI_SUCCESS) return Result;

        /* data transitions on rising edge of clock */
        if ((Result = adi_SPI_SetClockPhase(hSpi, true)) != ADI_SPI_SUCCESS) return Result;
        
        /* data transitions on rising edge of clock */
        if ((Result = adi_SPI_SetClockPolarity(hSpi, false)) != ADI_SPI_SUCCESS) return Result;

        /* run the SST25LF020A up to 1/2 core clock */
        if ((Result = adi_SPI_SetBitrate(hSpi, SPI_CLOCK)) != ADI_SPI_SUCCESS) return Result;
        
        uint32_t freq = adi_SPI_GetBitrate(hSpi);

        /* success */
        return ADI_SPI_SUCCESS;

    } /* end while */
}

I have approximately 10us between each of my 3 bytes I send and 90us between data blocks.

Thank you !



Add SPI clock measurement time
[edited by: JimmySIP at 5:59 AM (GMT -4) on 30 Sep 2021]
  • 0
    •  Analog Employees 
    on Oct 1, 2021 3:17 AM

    Hi Jimmy,

    Just to help me understand this better, are you using an external DAC to generate a sinewave? Are you using the ADUCM350's internal DAC somewhere else? 

    The maximum data rate for ADuCM350 is 8Mbps. An alternative is to use the ADuCM350's internal DAC to function as a waveform generator where you can generate a sine wave up to 100kHz with 1.2Vpp centered at 1.1V. 


    Please refer to page 316 of ADuCM350 Hardware Reference Manual (Rev. E) (analog.com) for more details on ADuCM350's waveform generator.

    Example codes are available for download in ADUCM350 Datasheet and Product Info | Analog Devices under design resources > Software development kit. I suggest using the Impedance measurement example as baseline, you will have to remove the ADC controls from the sequencer and just retain the waveform generator functions.

    regards,

    Mark

  • Hi Mark,

    Yes exactly, because I need a 14-16bits ADC and that's why I whould have prefered have an external one.

    Ok thanks a lot, I had a look to this example and I tried to generate someting according the page 316 and the example but I cannot generate a clean signal at 64kHz for example.

    It looks like this:

    Here is the sequence I send to the "adi_AFE_RunSequence" function:

    uint32_t seq_afe_acmeas2wire[] = {
        0x000A00F8,   /* Safety word: bits 31:16 = command count, bits 7:0 = CRC */
        
        0x84005818,   /* AFE_FIFO_CFG: DATA_FIFO_SOURCE_SEL = 10 */
        0x8A000034,   /* AFE_WG_CFG: TYPE_SEL = 10 */
        0x98000000,   /* AFE_WG_CFG: SINE_FCW = 0 (placeholder, user programmable) */
        0x9E0007FF,   /* AFE_WG_AMPLITUDE: SINE_AMPLITUDE = 0 (placeholder, user programmable) */
        0x88000F01,   /* AFE_DAC_CFG: DAC_ATTEN_EN = 1 */
        /* RCAL */
        0x86007788,   /* DMUX_STATE = 1, PMUX_STATE = 1, NMUX_STATE = 8, TMUX_STATE = 8 */
        0x00000640,   /* Wait 100us */
        0x80024EF0,   /* AFE_CFG: WAVEGEN_EN = 1 */
        0x04C4B400,   /* Wait 5s */
        0x82000002   /* AFE_SEQ_CFG: SEQ_EN = 0 */
    };

    Is there a way to improve this ?

    Thanks.

    Jimmy