Wednesday, February 20, 2013

Arduino Due Hardware SPI

The Arduino documentation for the Due board has extended library calls for hardware SPI, handling up to three devices.  The extended documentation is good but not overly complete.  In learning the device, I have found a number of things that may clarify the library in practical use.

The library for hardware SPI is SPI.h.  It defines different functions than the AVR Arduino library.  This is due to expanded capabilities described below.  If you port code from old programs, you will have to edit calls to new syntax.

Pins: Hardware SPI MISO, MOSI, and SCK pins are only on the SPI header (not to be confused with the ICSP header which is different on the Due).  See below.
What this does not show are the digital pin numbers.  They are not needed for SPI library calls but will be used later so we should know them.  The Arduino IDE has predefined variables MISO, MOSI, and SCK (something not readily known or documented).  If you use a short sketch to print them to the serial monitor, they are: MISO - Digital Pin 74, MOSI - Digital Pin 75, and SCK - Digital Pin 76.

Instead of one Chip Select (SS) pin, the Due supports three.  These are hardware Digital Pin 10 (SPI-CS0), Digital Pin 4 (SPI-CS1) and Digital 52 (SPI-CS2).  These pin values are used in the Due SPI library calls to determine which hardware SPI device you are addressing (up to three at the same time).

Clock settings: different from the AVR Arduinos as well.  The function call is:
  SPI.setClockDivider(SS, divisor);

The preset values of SPI_CLOCK_DIV2 etc. from AVR days are not defined. The divisor is an integer from 1 to 255. You calculate the clock rate as follows:  The Due system clock is 84 Megahertz.  The divisor is the number you divide into 84 MHz to get your desired clock frequency.  So common values would be:

Divisor   SPI Clock Frequency
84          1 MHz
42          2 MHz
21          4 MHz   (Default value, usually what AVR SPI bus uses)

It appears there is no way to get 8 MHz as the function takes integer divisors. (Need to double check this, very little documentation).

For now, it would appear that setting pins using pinMode and digitalWrite are not allowed.  The comment on the reference is: once SPI.begin() is called, the declared pin will not be available as a general purpose I/O pin, so do not set pinMode for the SPI lines if also using SPI library calls.

Finally, the hardware SPI library is only for 8 bit data values (send and receive).  If you need 9 bit SPI as is used on some graphical displays, the hardware library will not work.  But do not fret, there are some that have used low level calls to do software SPI which is capable of 9 bit SPI, I'll look into that next.