Gaps in SPI Write for multiple byte transfer

Hi, I want to send 4 bytes of data to a chip which acts as a SPI slave. The ADC chip I am working has a sampling frequency of 128 KHz. I want to capture every read from the ADC.

I notice there are gaps in between the SCLKS. I understand Arduino sends data in chunks of 1 byte at a time, but the chip requires the whole SPI transaction to be complete before 7us. CS low to CS high. It also requires that the SCLK is triggered on a known CLK and no gaps between pulses.

See image below. I am using 3.3V compatible spi library. I am using Arduino GIGA R1 WiFi

byte dataToSend [] = {0x00, 0x86, 0xab, 0xF0};
digitalWrite(CS, LOW);  
SPI1.transfer(dataToSend,4);
digitalWrite(CS, HIGH);

Also, there is a huge gap of 1.5 us after the CS goes low, the SCLKS are sent. is there a way to control that too?

Thanks.

Well I guess it is a relative term, but I wouldn't call 1.5 us huge. It's probably a typical overhead for Arduino API calls. I think if you want to reduce the overhead you would need to implement your own SPI code.

What board are you running on?

1 Like

I would imagine that if a faster processor were used, the time taken by the software overhead could be reduced.

Is there a specific need for this requirement?

Can you clarify which Arduino and which SPI library you are using?

In general, specifying why you need code or hardware to meet a specific requirement tends to produce more informed answers than simply saying "I want". "I want" is quite often a symptom of an X-Y problem.

1 Like

The chip requires the whole SPI transaction to be complete before 7us. CS low to CS high. So, the overhead kills a lot of time. How do I implement own SPI protocol? I have tried bit banging the pins. They run slow too.

I am using Arduino Arduino GIGA R1 WiFi

Yes, the chip requires the whole SPI transaction to be complete before 7us. CS low to CS high.

I am using Arduino GIGA R1 WiFi and spi.h library. I am using the SPI1.transfer function to make use of the 3.3V compatible pins.

This is my first post here and you are right I should have given more information. The chip requires the whole SPI transaction to be complete before 7us. CS low to CS high. It also requires that the SCLK is triggered on a known CLK and no gaps between pulses.
Hope this helps for a better reply

Whitc ADC chip are you using?

Custom chip which is designed by us. It’s an ADC which has a data update rate of 128ksps.

Well, your Arduino and its STM32 processor are well above my pay grade. But if it were a lowly Arduino Uno or Nano, the library would set up and enable the SPI peripheral, which runs in the background unmolested by anything else going on, including other interrupts, so it can shift out the entire byte with no delays. Upon completion, it generates an interrupt. The service routine for that interrupt would initiate transfer of the next byte simply by writing it into the SPI shift register.

If the SPI peripheral is really fancy, it will be buffered, so on completion of the current transfer, it will shift the buffered byte into the shift register immediately and automatically, and generate a "transmit buffer empty" interrupt. That permits continuous transmission, with zero delay between bytes.

I wonder if the STM32 SPI library is inserting the delay deliberately for some reason. I think it's unlikely that the SPI peripheral actually needs it, but as I say, I'm not knowledgeable about your chip.

It might be productive to look through the library's source code to see how its transfer() function operates, and what any related ISRs do.

Straying seriously into the "I've no idea what I'm talking about" territory here AND that I don't own a Giga of any type of have any knowledge of one, have a look here as it may give you some ideas:

I would probably first start off trying some simple possible solutions.

Two parts:

  1. SPI.transfer(buffer, count) - you are already doing. I really wish Arduino would adopt the other form of spi.transfer that other
    boards, like esp32, teensy, ... support: transfer(tx_buffer, tx_count, rx_buffer, rx_count)... But...

  2. digitalWrite(cs_pin, HIGH) - is really slow:
    I have my own library for it: digitalWriteFast, which is currently
    sort of buried in a github project:
    Arduino_GIGA-stuff/libraries/GIGA_digitalWriteFast at main · KurtE/Arduino_GIGA-stuff · GitHub There are some other similar implementations for this. You might try it with 1) above to see if that gets you fast enough.

If the above is not fast enough, for my ILI9341 for the GIGA library ( KurtE/ILI9341_GIGA_n: Converted from ILI9341_t3n for the Arduino GIGA) I do some more heavy hacking, where I end up unrolling my digitalWriteFast down to simply setting a register. And I grab hold of a pointer to the hardware SPI object and do some direct writing to the SPI registers...

I have seen similar gaps due to the SPI transaction calls when using HW SPI. When writing bit banging SW SPI it depends on the platform if it is slower.
On AVR (UNO, MEGA) it certainly was.
On ESP32 I recall that bit banging was slightly slower per bit but on par per byte with the HW SPI. This interesting conclusion is then that as the SW SPI pulses were slightly longer, the quality of the communication (squareness of pulses) is actually better.

Don't have a GIGA to test, but agree with bobscousins that bit banging is worth a try.

To be clear, I really meant writing directly to the SPI registers instead of going through the Arduino API, rather than bitbanging.

I am assuming that the OP has things for the CPU to do other than collecting data from the ADC.

OK, my misinterpretation

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.