SPI Questions —*default speed and quicker chip select

Status
Not open for further replies.

jcarruthers

Well-known member
Hi all,


I have a few questions:

What's the default SPI speed on a Teensy 3.1?

Do I need to use beginTransaction everywhere if I only have one SPI device? Can I just stick it in the setup() when initialising everything?

I have read about using "native" chip/slave select —*is this something a mere mortal can use? There must be something quicker than doing digitalWrite(DACCS, LOW)?

I found this by Paul — but when I get to the chip select bits they are a bit lost on me: http://dorkbotpdx.org/blog/paul/display_spi_optimization


James
 
when writing to DACs (or i guess anything else*) using SPIFIFO seems to be the best option by far; it's not very well documented but doable for mere mortals. if you only have one SPI device, you shouldn't run into problems. in that case, you don't have to explicitly pull high/low the CS -- take a look at SPIFIFO.h and there's some threads about it. using 'native' CS = use the pins labelled CS on the pinout diagram.

it's quite straightforward. here's for instance how you'd write to + update channel A of a DAC8564:

Code:
void set8564_CHA(uint16_t _data) {
  
       		//uint8_t _cmd = 0x10; // == B00010000;
                SPIFIFO.write(0x10, SPI_CONTINUE);
                SPIFIFO.write16(_data);
                SPIFIFO.read();   
                SPIFIFO.read();                       
}



* also see the spi flash / audio threads;

oh, and 24 MHz i think is the fastest speed at 96MHz. you can achieve 30 MHz @ 120MHz
 
What's the default SPI speed on a Teensy 3.1?

Whatever it happens to be, you shoudn't depend upon it. Always configure the speed.


Do I need to use beginTransaction everywhere if I only have one SPI device? Can I just stick it in the setup() when initialising everything?

You really should use beginTransaction(), even if you have only a single chip. beginTransaction with SPISettings lets you give the clock speed as a normal integer. That's a lot simpler than having to figure out clock divider settings. It also will automatically work on all future hardware.

I have read about using "native" chip/slave select —*is this something a mere mortal can use? There must be something quicker than doing digitalWrite(DACCS, LOW)?

Honestly, the speed improvements is usually very small compared to digitalWriteFast().

It is possible, for certain special uses, to gain much more speed. ILI9341_t3 is a good example. But those techniques are very difficult, even for experts, and they're only possible for very specific circumstances that depend greatly on the specific way a chip uses SPI.

The SPI library now has SPI.transfer(buffer, length). I'd recommend using that and digitalWriteFast() for chip select, and of course beginTransaction and endTransaction. That combination is easy and will give you pretty good performance, with painful optimization techniques.
 
Thank you both for your replies.

I'll give both those a go — it's not so much that my DAC is under-performing at the moment but I may as well drive it in the best way.

Is digitalWriteFast a good idea to use everywhere? I don't see any drawbacks — why isn't that just the default method?
 
The normal digitalWrite() emulates the AVR behavior of controlling the input pullup resistor if the pin is configured for input mode. Sadly, there are still a lot of sketches and libraries using this feature, so it's necessary for Arduino compatibility.

Normal digitalWrite() also does a pin number to register lookup at runtime.

When you use digitalWriteFast(), the fast code is only used if the pin number is a constant known at compile time. If the compiler doesn't know the pin number, it uses normal (slow) digitalWrite(). For example:

Code:
  for (int i=0; i<20; i++) {
    digitalWrite(i, LOW);   // can't be optimized by digitalWriteFast
  }

The compiler can only optimize digitalWriteFast(), placing the register definitions directly into your code, if the pin number is a known constant.
 
Thank you both for your replies.

I'll give both those a go — it's not so much that my DAC is under-performing at the moment but I may as well drive it in the best way.

just to clarify -- i was assuming you *had* performance issues. the vanilla SPI functions should be entirely ok if you're just writing to the DAC every now and then (as in a sequencer). SPIFIFO seems much more suitable though when, say, doing some kind of DDS, ie for LFOs and such, and things should happen fast.
 
Thanks both.

mxxx > I'd like to ensure everything is good for later on. There's every my code could run very fast depending on how fast it's clocked.
 
I have saved myself a good few microseconds —*my loop time is now less than 20us — about 10-15% quicker.

Part of that may be a couple of other optimisations I made at the same time — but it's all good.
 
Status
Not open for further replies.
Back
Top