SPI how-to

I am lost when it comes to initializing and communicating with the spi device using the arduino spi library. I have already read the arduino documentation and several threads, but its not clear on what I have to do. Can somebody with experience clarify/explain to me the basics.? Thanks in advanced!

Without knowing what kind of chip you're using or how you've connected it, it's hard to give advice.

But I just leanred to do SPI recently, and one thing you need to know is before you transmit a byte, you need to set the pin you have connected to the chip select pin of your ic low, and send your bytes with the SPI commands, an then set it high again. If you onlky have one device you might as well use pin 10 since that's the standard pin for SPI, but if you have multiple devices on the same SPI bus you'll need to use other pins to activate those devices at the right time.

You also don't need to waste the input pin if your device doesn't need to talk to the arduino. You can use that for other things, as long as you're outputting. Inputting on it would be bad and cause the arduino to go into slave mode.

Lastly, you need to look at your datasheet and see what kind of SPI protol it uses. I think they call it a mode. You need to make sure you set that right.

Sorry I forgot to be specific, I am connecting to the sparkfun WiFly shield which uses spi->uart chip SC16IS750

And I am using a mega, I already know I have to use pins 50-53.

So I have to tell the spi chip that I am going to send it some data with a specific chip command, than I send my data? And I do this through the transfer function in the SPI class? Is that correct?

I saw

#define THR 0x00 << 3
#define RHR 0x00 << 3
#define IER 0x01 << 3
#define FCR 0x02 << 3
#define IIR 0x02 << 3
#define LCR 0x03 << 3
#define MCR 0x04 << 3
#define LSR 0x05 << 3
#define MSR 0x06 << 3
#define SPR 0x07 << 3
#define TXLVL 0x08 << 3
#define RXLVL 0x09 << 3
#define DLAB 0x80 << 3
#define IODIR 0x0A << 3
#define IOSTATE 0x0B << 3
#define IOINTMSK 0x0C << 3
#define IOCTRL 0x0E << 3
#define EFCR 0x0F << 3

#define DLL 0x00 << 3
#define DLM 0x01 << 3
#define EFR 0x02 << 3
#define XON1 0x04 << 3
#define XON2 0x05 << 3
#define XOFF1 0x06 << 3
#define XOFF2 0x07 << 3

in a couple of the examples I was using, but that just sent my head spinning.

You tell the chip you're going to start sending it bits by setting the pin of the arduino which is attached to it's chip select pin low, and then setting it high again once you've sent one or more bytes to it.

Take my dac for example. The datasheet shows that it wants 16 bits per command. So I set pin 10 low, send two bytes, and set it high again.

Your chip may want 8-bit commands, or 24-bit commands. So you may send one or three bytes to it before setting the CS pin high again.

I don't know what all those constants are. But they look like they are bit masks for different portions of the command structure. On my dac for example, those 16 bits I send contain 4 configuration bits, and then 12 bits indicating how much voltage it should output.

Here's the code I use to send the dac data btw: (Or at least, which I used until I determined I really needed to send it data with an interrupt to send it 30,000 updates a second while doing other things.)

  void updateDAC() {
    static unsigned long lastToggle = 0; 
    static unsigned long sample = 0;
    byte dataHigh, dataLow;

      DAC data format:

      bit 15 A/B: DACA or DACB Select bit
        1 = Write to DACB
        0 = Write to DACA

      bit 14 BUF: VREF Input Buffer Control bit
        1 = Buffered
        0 = Unbuffered

      bit 13 GA: Output Gain Select bit
        1 = 1x (VOUT = VREF * D/4096)
        0 = 2x (VOUT = 2 * VREF * D/4096)

      bit 12 SHDN: Output Power Down Control bit
        1 = Output Power Down Control bit
        0 = Output buffer disabled, Output is high impedance

      bit 11-0 D11:D0: DAC Data bits
        12 bit number “D” which sets the output value. Contains a value between 0 and 4095.    

    if ((micros()-lastToggle) >= 250) { // 4000hz = 1000000/4000 microseconds ... Does this time need to be divided by 2?
      lastToggle = micros(); 
      //if (sample == 0) { sample = 4095; } else { sample = 0; } // Simulate square wave.
      sample = random(4096);
      // Take the SS pin low to select the DAC.
        digitalWrite(pinSPI_SS, LOW);
      // Send the 16 bits needed to reconfigure the DAC.
        //dataHigh = B00110000 | (sample >> 8);
        //dataLow = sample & B11111111;
        SPI.transfer(B00110000 | (sample >> 8));
        SPI.transfer(sample & B11111111);
      // take the SS pin high to de-select the chip:
        digitalWrite(pinSPI_SS, HIGH);    

Note that my dac wants the high bits of the 16 bit word first. So I set up the SPI transfer mode elsewhere in the code to send the bits of the bytes in reverse order. And then in my function I make sure I send the high byte of my word first. Your chip may require something different.

I saw some of things that might tell me how many bytes I can send, but I am not sure, here is what I found:

64 bytes FIFO (transmitter and receiver)

Fully programmable character formatting
5-bit, 6-bit, 7-bit or 8-bit character
Even, odd, or no parity
1, 11[ch8260]2, or 2 stop bits

How does this look? The first function gets a command to send to the uart device. I than pass this to the spi transfer function which I modified to set the slave to low before sending and high after sending.

String SPIDevice::sendCommand(String command) {
      char comArr = command.toCharArray();
      int length = command.length();
      char response;
      for (int i=0; i<length; i++) {
            response = spi.transfer(comArr[i]);
      String returnResponse = String(response);
      return returnResponse;
byte SPI::transfer(byte value) {
      SPDR = value;
      while (!(SPSR & (1<<SPIF))) ;
      return SPDR;

How do those functions look? What words should I look for in the chip manual to find the amount of bits I can send?

scswift, do you mind posting your entire code? It would be very appreciated.

I replied via PM, but since others might want to see some more of the code, here's the variables and setup for the SPI transfer:

 const int pinSPI_SS = 10;   // DAC CS pin.  This pin needs to be set LOW when we begin sending bytes to the DAC, and set HIGH once we've sent 16 bits to it so it latches the data to its output.
  const int pinSPI_MOSI = 11; // DAC SDI pin
  const int pinSPI_MISO = 12; // Not used.
  const int pinSPI_SCK = 13;  // DAC SCK pin

  // Initialize Serial-Parralel Interface:

        pinMode(pinSPI_SS, OUTPUT); // Set the slave/chip select pin to output.

        SPI.setBitOrder(MSBFIRST); // Send most significant bit first when transferring a byte.
        SPI.setDataMode(SPI_MODE0); // Base value of clock is 0, data is captured on clock's rising edge.
        //SPI.setClockDivider(SPI_CLOCK_DIV4); // Set SPI data rate to 16mhz/4. IE: 4mhz.
        SPI.setClockDivider(SPI_CLOCK_DIV2); // Set SPI data rate to 16mhz/2. IE: 8mhz.