SPI Slaves

Hi all,

Just a few questions on setting up an SPI slave. I’ve read through numerous examples of SPI but there seems to be very little information on configuring an arduino as a slave. I also read through several of user nickgammon’s posts explaining this very thing but some bits left me more confused than I was to start with.

Following the examples from https://forum.arduino.cc/index.php?topic=52111.0

In the Slave example, there’s this cryptic line:

// turn on SPI in slave mode
SPCR |= _BV(SPE);

which cued me to look-up SPCR and learn about the SPI Control Register. I’m confused though about the bitwise operation here. If I’m not mistaken, ‘|=’ is a compound OR operation. I’m confused how one can OR an 8 bit register with (what I assume is) a single Bit.
I’m also confused why the bit operations are acting to change the SPE bit of the SPCR and not the MSTR bit, which (https://www.arduino.cc/en/Tutorial/SPIEEPROM) informs me, sets whether the device is a Slave or Master. I found another example of setting up a slave on the forums and it contains the line:

// Enable SPI as slave.
SPCR = (1 << SPE);

Which I guess has the same effect as the code above. I’ve done some work with registers and bits before but I’m utterly confused why these bits are being set as they are and why this works. I’m also surprised that the SPI.h library doesn’t come with some way to declare a device as a slave. Any help would be great, thanks!

 SPCR |= _BV(SPE);

ChainReaction:
I’m confused how one can OR an 8 bit register with (what I assume is) a single Bit.

_BV(SPE) is not a single bit. It is a whole byte*. Same as saying (1 << SPE)

*Actually I think it works out to be in reality a 16 bit value. I know the (1 << SPE) does turn out to be 16 bit because the 1 is treated as a 16 bit int.

ChainReaction:
I’m also confused why the bit operations are acting to change the SPE bit of the SPCR and not the MSTR bit, which (https://www.arduino.cc/en/Tutorial/SPIEEPROM) informs me, sets whether the device is a Slave or Master. I found another example of setting up a slave on the forums and it contains the line:

// Enable SPI as slave.
SPCR = (1 << SPE);

Always check the datasheet:

Bit 4 – MSTR0: Master/Slave0 Select
This bit selects Master SPI mode when written to one, and Slave SPI mode when written logic zero. If SS
is configured as an input and is driven low while MSTR is set, MSTR will be cleared, and SPIF in SPSR
will become set. The user will then have to set MSTR to re-enable SPI Master mode

So, you see, you don’t have to explicitly set that bit. All you have to do is set your pin 10 to input and that forces the bit to 0 and puts you into slave mode.

The SPI library is written to get data out of SPI devices into your Arduino. It satisfies 98% of everybody’s requests for SPI. For the other 2%, they all need something different, so just one library won’t even begin to cover their requirements.

SPE is a number. It will be 6 for a 328P and probably on most other AVR processors.

If you take the single binary digit 1 and left-shift it by 6, your result will have a 1 in the #6 bit position. (Bits are numbered 0-7.) That’s what the code (1<<6) does. It is a little tricky because you’re not used to thinking about the binary values of base-10 constants. But a little thinking will reveal that 0b1 is equal to 0x1 is equal to 1

The _BV() macro “Bit Value” does the same thing as the left-shift.

The |= operator is used when you don’t want to change the values of any other bits already set in SPCR. Any bit that’s a zero on the right-hand side is untouched.

Thanks very much, both.