Thinking about the SPI library ...?

For many years I've used the two lines below (+ comments) when setting up my sketches to interface with an SD card (e.g. Adafruit microSD breakout).

#include <SdFat.h>                              // microSD interface
#include <SPI.h>                                  // required after IDE 1.5.4

However today (while contemplating how SPI libraryh really works) I found that I could comment SPI.h out and it made no difference. So I guess the SPI library is automagically installed by my IDE2.2.0 ?

My biggest question about SPI: Are the two SPI interfaces (e.g. on UNO or MEGA) combined or separate? If they are separate how do I distinguish them in my sketch.

i.e. if I have two unrelated sensors A and B each using SPI for a different purpose, how do I set them up so there's no clashes?

Many thanks in advance ...

The SPI library has always been part of the Arduino AVR board package and does not require installation. The reason why you used to include a header but now not is that the latest versions of the SD library already include the

in their files

Which "two SPI interfaces"? Both Mega and Uno has only one SPI interface.

1 Like

That's what the Slave Select (aka "Chip Select") is for

image

Well maybe you're answering my question ... but ... looking at the schematic for UNO :slightly_smiling_face:

  1. SPI pins SS,MOSI,MISO,SCK (D10-D13) connect to the ATMEGA328P PB2-PB5 and 6 pin ICSP

  2. the ATMEGA16U2 SPI pins MOSI2,MISO2,SCK2 (PB1-PB3 ) connect to the 6 pin ICSP1

So hardware wise they appear to be quite separate channels AFAIK.

and the MEGA's schematic shows the same

ICSP1 is a header of the different controller, used for interface the board to the USB bus.
The main arduino chip - Atmega328 (Uno) or 2560 (on Mega) has the one SPI interface only.

I've run devices using SPI off ICSP1 pins 50,51,52 several times in the past, so it does seem to be one and the same SPI bus

I answered the question about how you can have two (or more) different devices (eg, sensors) on a single SPI Bus.

Yes - not only are they quite separate channels, they are connected to entirely different chips!

  • ICSP and D10-13 connect only to the ATMEGA328P. This is the chip that runs your sketch, so these are the only pins your sketch has access to.

  • ICSP1 connects only to the ATMEGA16U2. This is the USB-to-UART converter - your sketch has no access to this.

So, as far as your sketch is concerned, there is just one SPI available.

(The USART in the ATMEGA328P can be put into an SPI mode; I don't know if that's supported in Arduino, and it would mean that you lose Serial.)

Look again at the schematics: there is no connection from ICSP1 to the SPI bus of the ATmega328P - it connects only to the ATmega16U2:

I understand the purpose of the ATMEGA 16U2 w.r.t. USB, but this discussion is about SPI.

Per my comments in post #7, even though MEGA pins 50,51,52 are from ICSP1 on and ATMEGA 16U2, they also function as part of the SPI bus. I've runs an Adafruit microSD this way many times (using nearby pin 48 for CS). So it seems the 328P and 16U2 share the one SPI bus in some intimate way. On the other hand, maybe they really are two separate SPI buses and the SPI library automatically caters for the two.

No, they don't: look at the schematics - you can see that there is no connection of the two separate SPIs!

1. The following digarm (Fig-1) may give you some idea about the SPI Port structures of two Arduinos.


Figure-1:

2. What role does SPI.h Library play in the sketch?
In Slave Sketch:
Referring to the following codes/sketch:

(1) The Library provides the meanings for the symbolic names: SS, MOSU, MISO, SCK.
(2) The codes for this function: SPI.attachInterrupt();
(3) The meaning/interpreation/codes for this ISR(): ISR(SPI_STC_vect)
(4) Many more...

#include<SPI.h>

byte txData[] = {0xAB, 0xCD};
byte rxData[2];
volatile byte byteCounter = 0;
volatile bool flag = false;
int i = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(SS, INPUT_PULLUP);
  pinMode(MISO, OUTPUT);
  bitClear(SPCR, MSTR);  //UNO-2 is Slave
  bitSet(SPCR, SPE);  //SPI Port is created
  SPI.attachInterrupt();  //LIE, GIE are active
}

void loop()
{
  if (flag == true)
  {
    noInterrupts();//critical section
    byte myCounter = byteCounter;
    byteCounter = 0;
    interrupts();
    Serial.print("Received Data: ");
    Serial.print(rxData[0], HEX);
    Serial.println(rxData[1], HEX);
    //------------------------------
    Serial.print("Number of bytes received: ");
    Serial.println(myCounter, DEC);
    flag = false;
  }
}

ISR(SPI_STC_vect)
{
  rxData[i] = SPDR;
  SPDR = txData[i];
  byteCounter++;
  i++;
  if (i == 2)
  {
    i = 0;
    flag = true;
  }
}

In Master Sketch:
Referring to the following sketch, it is not hard to see the role of SPI.h Library.

#include<SPI.h>
int y = 0x1234;

void setup()
{
  Serial.begin(9600);
  SPI.begin();  //default speed: 4 Mbits/sec
  digitalWrite(SS, LOW);   //Slave is enabled
}

void loop()
{
  byte y1 = SPI.transfer(highByte(y));
  delayMicroseconds(10);  //must be 
  byte y2 = SPI.transfer(lowByte(y));
  delayMicroseconds(10);  //must be 
  //--------------------------------
  int recInt = y2 << 8|y1;
  Serial.println((uint16_t)recInt, HEX);
  delay(1000);
}

This also applies to the USARTs (plural!) in the ATmega2560.

The ATmega2560 has four USARTs - so you could add extra SPIs without losing Serial...


Figure-1:

In Fig-1 shown above, it is observed that PPin-2/3 of ATmega328 MCU has the following aternate functions (no SPI signals):

IO lines:  PD0/PD1
UART Port: RXD/TXD
Pin Chnage Interrupt lines: PCINT16/PCINT17

When you use the USART in SPI mode, it repurposes the USART's Alternate Functions (TXD, RXD) - they are not considered distinct AFs.

1 Like

I should note that this supports SPI Master only.

For both ATmega328P and ATmega2560.

Thank you. I didn't know that.

1 Like

FYI: this discussion isn't about Master-Slave SPI connections. The two SPI interfaces (hardware pinouts) I am referring to appear on a single UNO, and they also appear on a single MEGA. These are referred to a ICSP and ICSP1 in the schematics

Lots of good info but I don't believe the main issue is resolved as yet. On a MEGA I can run a SPI LCD off pins D10-D13 and an SD card off SPI / ICSP1 pins 50,51,52 (+CS) . The first SPI port is connected to the main chip however the latter SPI is connected to the 16U2.
So ... still not clear IMO. Is there one SPI bus or two?

Pins 50,51,52 are the hardware SPI pins on a Mega, these are connected to the ICSP header for the atmega2560 chip. Pins 11, 12, 13 on the Mega are not connected to SPI hardware at all, if you are using those then a software implementation of SPI is being used. None of these pins are connected to the ICSP header for the 16u2, that is completely independent. < edit > An ohmmeter can be used to verify the connections of the ICSP headers to the pins.

1 Like