PlatformIO Community

Speed-up SPI transfer rate

I’m new to PlatformIO and I have some problems with a small SPI-project on my Arduino DUE. The aim of the project is to read in an analog input, process the data (not important at the moment) and send the data via a SPI connection to a DAC (DAC8811). This works properly, but now I’m trying to speed-up the SPI transfer rate and have some issues with that. As you can see on the pictures below, I tried to change the ClockDivider but surprisingly the time difference between two 16-bit transfer packages didn’t change.
(Clock Frequenca Arduino DUE = 84MHz;
left picture: ClockDivider = 2 → SPI Clock = 84/2 MHz | right picture: ClockDivider = 11 → SPI Clock = 84/11

Picture Explanation:
.) Line 1 - yellow Line: CS (low-active)
.) Line 2 - green Line: SPI Clock
.) Line 3 - purple line = data (0x7FFF = 0b0111 1111)

The associated code is quite short, and I can’t see the problem there.

Now my question is how to reduce the time delay between the data packages the increase the transfer speed rate.
Thanks in advance,

The clock divider affects the frequency of SPI clock of the transfer, it doesn’t change the processing / computation delay your sketch has between the end of one SPI transfer to the start of the next one.

It’s hard to judge what code is being executed between one SPI transfer to the next since the code is not given. If you do a ADC reading between each transfer, that’s of course going to delay stuff.

General optimization hints:

  • Minimize the runtime of the code executed between two SPI transfers
  • If using the SPI.h library, make sure you give it as much data as you can in one go, aka the transfer() function that takes a whole byte array
  • Even the SPI.h is polling-based. You may find an interrupt-driven or DMA-driven way of driving the SPI to be far more performant. This of course depends on your application and when the data you want to send over SPI is available.

Thanks maxgerhardt for the quick reply!
As you hopefully can see in the picture (sorry for the bad quality…) when I choose a small clock divider (=high frequency), the time for sending data is obviously shorter, but therefore the delay between the end of one data-package to the beginning of the next data-package increases. Decreasing the clock-frequency even leads to a more-or-less continious stream of data.
Here is a picture of the SPI_write function, but I also can’t see a problem there because it just sends the data…

The ADC reading also shouldn’t be a problem, because at the moment I don’t even use it in the program / the loop.

In microseconds, what’s the time between the end of one SPI package and the beginning of a new one when you chose a high or low clock divider?

with low clock divider (high frequency) ~ 2.6 us
with high clock divider (high frequency) ~ 2 us

Therefore, at the moment it doesn’t matter which clock divider I choose, because the time between two data packages always remains about 3.5us
I really don’t understand…

Well there’s still optimization potential:

  • consolidate the two my_SPI_write() calls into one that receives the 16-bit data_ADC0 in one function (that also gets rid of some comparisons for _mode since you know the sequence
  • since pin is static, precompute things like ch and SPI_PCS(ch) in a global variable
  • Remove all usages of Serial
  • in one loop iteration, send data multiple times with by duplicating the call to the send function – avoids the delay between multiple runs of the loop function, since after your loop runs, this code runs, and it will check all serial objects for incoming data.

ok, thank you for your help!
But do you have any idea why the delay time between two data packages change when I vary the clock divider? In my opinion, the most time gets “lost” in this inactive area and I want to minimize it.

@maxgerhardt I think I found the problem. When I add a while(1) - loop in the void loop() fuction, the data is sent more or less continiously without these long breaks between. It looks like the program needs so much time when starting the “void loop()”.
Thanks for your help,

1 Like

So basically

This thing right here.

Yeah, thanks. I adopted your suggestions and it works quite well!