Arduino Due SPI support

Hi everyone,

I try to understand how SPI works on the Due board.
In the spec for SPI for the Arduino Due it says that MISO, MOSI, and SCK are available in a consistent physical location on the ICSP header.
Is that true, that you can use HW-SPI only at the connector in the middle of the board?
And another question, the spec says that:
MOSI = ICSP-4
MISO = ICSP-1
CLK = ICSP-3
And the SS are at pins: 4, 10, 52.

Regarding the SS, what does this mean, that it is only possible to use three slaves/SPI-devices?

I see several discussions about the SPI for the Due board and a lot of these suggests that you should use the pins 4, 10, 52 for the slaves but the general spec for SPI is that you can use unlimited (theoreticly) number of SPI devices as I understand it.
I am confused!

Link to the spec:

Thanks.

Is that true, that you can use HW-SPI only at the connector in the middle of the board?

Yes, unlike other boards where you can access SPI pins on eg. 11-13 for Uno, on Due they are only available on the "SPI" header, you can lookup pin numbering from Due pinout diagram:
http://forum.arduino.cc/index.php?topic=132130.0

The special SPI SS pins support some slightly more advanced features around SPI transactions. These features are not useful to most people, not well supported in the library and you can write your own code to do the same thing.

While I know those features are there, I don't bother using them. I write my own code for transactions. It's never been important for any of my projects.

I've been having a rough time communicating with my IMU (LSM6DS3 from Sparkfun). Can't even get it to send the WHO_AM_I value. No matter what I do, the code below returns 255. I tried another LSM6DS3 chip, but same issue. I2C works for both so the chips are functioning.

The Arduino Due pinout diagram shows +5V next to the SPI MOSI pin. Are the MOSI/MISO +5V pins? My IMU is a 3.3V device. Could this be the problem? Or maybe the code below is wrong? Appreciate your help.

// Datasheet: https://cdn.sparkfun.com/assets/learn_tutorials/4/1/6/DM00133076.pdf
#include <SPI.h>

#define SSX  10 

void setup() {

    uint8_t  result1, result2;
    uint8_t  target = 0X0F;

    Serial.begin(115200);
    
    pinMode(SSX, OUTPUT);
    digitalWrite(SSX, HIGH);    

    SPI.begin(SSX);
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode(SSX, SPI_MODE3);
    SPI.setClockDivider(SSX,10);        // Due: (pin,divider) where divider is any value from 1 to 255

    delay(1000);

    digitalWrite(SSX, LOW);             // Select chip

        result1 = SPI.transfer(SSX, 0x80 | target, SPI_CONTINUE);  
        result2 = SPI.transfer(SSX, 0x00, SPI_LAST);
                  
    digitalWrite(SSX, HIGH);            // De-select chip

    Serial.println("Who Am I:");
    Serial.println(result1);
    Serial.println(result2);
}

void loop() {
}

Ok, thanks

MorganS, what is the basis of the special SPI SS pins support (how does it work) ?

It seems that it possible to use more than 3 SPI devices because I have now started to test my new Due with a multifont display (NHD-2.7-12864UMY3) and a WIZ820io module, and I got a display working with HW SPi using:
pin 31 as SS for display (not pin 4, 10 or 52).
pin 45 as SS for Multifont (not pin 4, 10 or 52).
pin 10 as SS for WIZ820io.

But I found a problem when I using the Multifont functionality, the WIZ820io stops working. But normal ascii character still works. Maybe someone can help me with this?

I looking with a oscilloscope I see that the SS (pin10) for the WIZ820io never goes high, always low.
That is weird, I see that the pin 31 goes low and allow print characters on the display but the WIZ still is low, and the Ethernet communication seems to work (maybe it is just to short time to interfere with the Ethernet).
I think this it is just a coincidence that the WIZ still works, I think it is because of short time/fast writing.

Anyone know why the pin 10 never goes high, when using the other SPI devices?

I using U8GLIB_NHD27OLED_2X_BW libraries for normal ascii display printing.
Here is the code for mutifont, maybe the problem is here?:

#define SLAVESELECT_MFD 45

void WriteTopMultiFont(long* Addres){  // Chinese characters for Top half of Display
  column = 0;
  row = 6;
  for(unsigned int j = 0; j < sizeof(taddress)/4;j++){
    byte adress[3];
    SPI.beginTransaction(SPI_DISPLAY_SETTINGS);
    digitalWrite(SLAVESELECT_MFD, LOW);
    SPI.transfer(SLAVESELECT_MFD, 0x0B);  //READ command
    for(int i=2;i>=0;i--){
      adress[i] = ((Addres[j] >>(8*i)) & 0xFF); 
      SPI.transfer(SLAVESELECT_MFD, adress[i]);  //Address Bytes 1 to 3
    }
    SPI.transfer(SLAVESELECT_MFD, 0xFF);  //Dummy Byte
    for(unsigned int i= 0;i<32;i++){
      buffer[i]=SPI.transfer(SLAVESELECT_MFD, 0);  //read dot-matrix font data
    }
    digitalWrite(SLAVESELECT_MFD, HIGH);
    SPI.endTransaction();
    if(adress[0]!=0x00){
      if(counter<sizeof(ttext)/2){
        for(unsigned int i= 0;i<sizeof(buffer)/2;i++){
          for(unsigned int j=0;j<8;j++)
          {
            //getKeypress();
            if(bitRead(buffer[i],j)) u8g.drawPixel(column+i,row+j);
          }
        }
        for(unsigned int i= 16;i<sizeof(buffer);i++)
        {
          for(unsigned int j=0;j<8;j++)
          {
            //getKeypress();
            if(bitRead(buffer[i],j)) u8g.drawPixel(column+i-16,row+j+8);
          }
        }
        counter++;
        column+=22;
      }
    }
    else {column +=40;}  
  }
  counter = 0;
  row = 0;
  memset(buffer,0x00,sizeof(buffer));
}

randomvibe:
The Arduino Due pinout diagram shows +5V next to the SPI MOSI pin. Are the MOSI/MISO +5V pins? My IMU is a 3.3V device. Could this be the problem? Or maybe the code below is wrong? Appreciate your help.

No, that pin is so that a ISP programmer can power the board while it's programming. It's a standard header on all Arduinos so it must have a standard power voltage, even though the data pins are only 3.3V on the Due.

Anyone know why the pin 10 never goes high, when using the other SPI devices?

Why would it? Your snippet doesn't access pin 10. Pin 10 does whatever the rest of your code told it to do.

On the AVR Arduinos, pin 10 must be an output when using SPI as a master. If it's an input, the SPI system goes into slave mode and waits for that pin to go low. But as a master, you can control pin 10 to do whatever you want. It's just another pin.

MorganS:
No, that pin is so that a ISP programmer can power the board while it's programming. It's a standard header on all Arduinos so it must have a standard power voltage, even though the data pins are only 3.3V on the Due.

Then the problem with my LSM6DS3 IMU is the code. When I run the Due, it keeps returning the value 255. Even the WHO_AM_I register (0X0F) returns 255.

The small sketch below demonstrates the problem. Have you tried SPI for an accel, gyro or IMU? I appreciate your response.

#define SSX  4   

#include <SPI.h>

void setup() {

    uint8_t  result;
    uint8_t  address = 0X0F;

    Serial.begin(115200);
    
    pinMode(SSX, OUTPUT);
    digitalWrite(SSX, HIGH);

    SPI.begin(SSX);
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode(SSX, SPI_MODE3);
    SPI.setClockDivider(SSX,10);        // Due: (pin,divider: 1 to 255)

    digitalWrite(SSX, LOW);             // Select chip
    result = SPI.transfer(SSX, address);   
    digitalWrite(SSX, HIGH);            // De-select chip

    Serial.println("Who Am I:");
    Serial.println(result);
}

void loop() {
}

If you get 255, check your wiring. That's the value you get if MISO is high all the time.

MorganS:
Why would it? Your snippet doesn't access pin 10. Pin 10 does whatever the rest of your code told it to do.

On the AVR Arduinos, pin 10 must be an output when using SPI as a master. If it's an input, the SPI system goes into slave mode and waits for that pin to go low. But as a master, you can control pin 10 to do whatever you want. It's just another pin.

My code does not handle the pin 10, pin 10 is controlled by the device using it, which is the Ethernet object which using library for the Wiz820io device

I control the SS pins 31 and 45.
pin 31 as SS for display (not pin 4, 10 or 52).
pin 45 as SS for Multifont (not pin 4, 10 or 52).
pin 10 as SS for WIZ820io.

Do I using or setting up SPI in the wrong way?
U8GLIB_NHD27OLED_2X_BW u8g(31, 9, 8); // CS = 31, A0 = 9, RESET = 8 in my .ino
#define SPI_DISPLAY_SETTINGS 45, SPISettings(300000000, MSBFIRST, SPI_MODE0) in my .ino
Use of the multifont is attached earlier. Not rely tested on the Due yet.
Use of the normal display is standard like: u8g.print((const char*)ttext); No problem

#define W5200 in w5200.h
#define SPI_CS 10 in w5100.cpp.

And this I don't understand, if I using the display at the same time as the ethernet library want to talk to the Ethernet module, how or where does the SPI control the SS pins?
Hope anyone understand my question and can explain this, because maybe the control of the SPI pins causing the problem.

Regards

Can you get each of those devices to work individually when only one is plugged in?

Can you plug them in, set their CS pins to HIGH and then only use each one individually?

Some SPI devices don't conform to the spec. The common RA8875 display driver doesn't release the MISO line for other devices to use it.

MorganS:
If you get 255, check your wiring. That's the value you get if MISO is high all the time.

Okay, I found the issue. It's not the program, it's the wiring. The LSM6DS3 IMU is on a Sparkfun PCB board. It has a jumper labeled ADDR that is closed and has to be opened for SPI to function.

The whole purpose of trying out SPI communication was to see if the random ticks I observe in my accel & gyro readings with I2C communication go way. The result: less ticks with SPI, but still there. Some background: when the IMU is stationary, the noise floor is only 29 counts. But these ticks return 253, 254 or 255 counts. Tick occurrence is very random. This issue is not present with my analog IMU. Using the Due ADCs is very simple and straightforward, however the ADC resolution is only 12 bits. The main reason I tried the LSM6DS3 was the 16 bit capability.

I use a CAT5 cable that's about 3 feet long. I have decouple capacitors int he power rails and large, low-ESR, 1000 uf capacitor. All these help reduce the tics. I tried 6 inch log wires, but the same outcome.

The Adafruit IMU (link below) also returns ticks, but their return counts are very low. So I'll just stick with Adafruit IMU.

Could the source of these ticks be the Arduino Due board, and not the IMU boards?