Using SPI modules with an arduino

From BitWizard Wiki
Jump to navigation Jump to search

intro

It is very convenient to expand your arduino with the bitwizard I2C or SPI modules. This article focuses on the SPI variant.

hardware

To connect your bitwizard module to your arduino I prefer to use the connector on the arduino that is originally for ICSP. Almost all the SPI signals are there. And we chose the pinout to be the same as well.

The only signal that does not appear on the ICSP connector is the "slave select" signal. The ICSP connector has "RESET" there.

So use the following connection:

 arduino    bitwizard
 ICSP        SPI
 1           1
 2           2 
 3           3
 4           4
 6           6

[todo find the names of the signals]

This leaves SS/RESET. We cannot use the RESET line on the ICSP connector. We recommend you use the D10 pin of the arduino as that is the pin recommended for the purpose by the chip manufacturer Atmel. So:

 arduino    bitwizard
             SPI
   D10       5

software

This example uses the BIGRELAY module, and rotates through the six relays each time you press the button. (no relays are activated until you first press the button. )

const int SPICLK  = 13;
const int SPIMOSI = 11;
const int SPIMISO = 12;
const int SPISS  = 10;
const int myswitch = 9;


void SPIinit(void)
{
  pinMode (SPICLK,  OUTPUT);
  pinMode (SPIMOSI, OUTPUT);
  pinMode (SPIMISO, OUTPUT);
  pinMode (SPISS,   OUTPUT);
  digitalWrite (SPISS, 1);
  
  SPCR    =  _BV(SPE) | _BV(MSTR) | _BV(SPR1) | _BV(SPR0);
}

char SPI(char d) 
{  // send character over SPI
  char received = 0;
  SPDR = d;
  while(!(SPSR & _BV(SPIF)));
  received = SPDR;
  return (received);
}

void SPI_startpkt (void)
{
  digitalWrite (SPISS, 0);
}

void SPI_endpkt (void)
{
  digitalWrite (SPISS, 1);
}

static unsigned char bigrelay = 0x9c;

#define WAIT1 25
#define WAIT2 15

void setregval (unsigned char addr, unsigned char reg, unsigned char val)
{

  SPI_startpkt ();
  delayMicroseconds (WAIT1);
  SPI (addr);
  delayMicroseconds (WAIT2);
  SPI (reg);
  delayMicroseconds (WAIT2);
  SPI (val);
  SPI_endpkt ();
}

void setup (void)
{
  int i;
  
  SPIinit ();
  pinMode (myswitch, INPUT_PULLUP);
}

//#define USE_SWITCH
#ifdef USE_SWITCH
#define DOIT digitalRead (myswitch) == 0
#else 
#define DOIT 1
#endif

void loop (void) 
{
  static int r;

  if (DOIT) {
     setregval (bigrelay, 0x10, 1 << r);
#ifdef USE_SWITCH 
     delay (10); // debounce
     while (digitalRead (myswitch) == 0)
         /* nothing */ ;
     delay (10); // debounce.
#else 
     delay (500);
#endif
     r = r + 1;
     if (r == 6) r = 0;
  }
}