SPI Modes

Hi all, I have a question about using multiple SPI devices on the same SPI bus.

On several ocasions I have needed to use two or more devices on the same SPI bus. Sometimes I'm lucky and the devices use the same settings, clock divider, mode (CPOL/CPHA) etc, but more often than not the devices require the SPI bus to be set up differently.

I would really like to know the most efficient way to manage this.

It's not such a problem where your using a device, then doing something else for a while then maybe using it again, in those instances I can set the mode etc, call SPI.begin again and use the aprreopriate device again.

Problems arise when for instance I'm reading a devices large buffer, say a camera buffer in a loop. I need to read say 32 bytes from the buffer then maybe use an RF device which uses spy to send the data on, then next itteration we are back to reading more of the camera buffer, then back to the RF device to send etc etc...

On those ocassions, if I have to reset the spi bus settings twice each itteration of the loop then the overhead might be many seconds.

Someone once mentioned having a SPI bus broker "The ideal is an SPI bus "broker" that handles all transactions between the Core and the devices" but I have no idea what this would entail.

Other people must have come across this issue before, I know I do nearly every project I work on because most of my projects involve 'piping' data between devices.

Any help or advice would be really appretiated, thanks guys, Rick.

You should only be doing one SPI.begin in the sketch, there are commands to change the mode, bit order etc.

Ah, ok, thanks for that, I thought I had to call begin each time I changed the clock etc to reset the bus.

So, is it the case that each time I need to use a device whose settings differ from what the bus is currently set to it is standard practice to just call setDataMode, setClockDivider and setBitOrder functions? If so, is there a noteworthy overhead to doing so?

No noticeable overhead. Here are the functions from SPI.cpp that you asked about:

void SPIClass::setBitOrder(uint8_t bitOrder)
{
  if(bitOrder == LSBFIRST) {
    SPCR |= _BV(DORD);
  } else {
    SPCR &= ~(_BV(DORD));
  }
}

void SPIClass::setDataMode(uint8_t mode)
{
  SPCR = (SPCR & ~SPI_MODE_MASK) | mode;
}

void SPIClass::setClockDivider(uint8_t rate)
{
  SPCR = (SPCR & ~SPI_CLOCK_MASK) | (rate & SPI_CLOCK_MASK);
  SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate >> 2) & SPI_2XCLOCK_MASK);
}

Hi, thanks, yes, I've seen the inner workings of those methods ta, just a bit of register bit setting. I find it difficult when I make assumptions of how something is physically working, for example changing the clock of the SPI. I know you just set some bits in a register but then I wasn't sure if the clock suddenly changed after those bits were set or if the SPI had to be 'rebooted' for the changes to take effect lol.

All changes happen immediately and are in effect when the function returns. No restart or reboot necessary. The only thing I recommend is make the changes when all SPI devices have their slave select pins HIGH (SPI disabled).

Ok, that's great to know. I can now rest easy when using multiple SPI devices, thanks :slight_smile: