Pages: [1]   Go Down
Author Topic: SPI how-to  (Read 2128 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Full Member
***
Karma: 0
Posts: 117
oh H4x!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!
« Last Edit: October 16, 2010, 06:13:29 pm by manray » Logged

Manchester, New Hampshire
Offline Offline
Edison Member
*
Karma: 4
Posts: 1363
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 117
oh H4x!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry I forgot to be specific, I am connecting to the sparkfun WiFly shield which uses spi->uart chip SC16IS750
http://www.sparkfun.com/datasheets/Components/SMD/SC16IS740_750_760.pdf

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
Quote
#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.
Logged

Manchester, New Hampshire
Offline Offline
Edison Member
*
Karma: 4
Posts: 1363
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.)

Code:
 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.
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 117
oh H4x!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Quote
64 bytes FIFO (transmitter and receiver)
Quote
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.
Code:
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;
}
Code:
byte SPI::transfer(byte value) {
      digitalWrite(SS_PIN,LOW);
      SPDR = value;
      while (!(SPSR & (1<<SPIF))) ;
      digitalWrite(SS_PIN,HIGH);
      return SPDR;
}
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 117
oh H4x!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Manchester, New Hampshire
Offline Offline
Edison Member
*
Karma: 4
Posts: 1363
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

Code:
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.begin();
        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.
Logged

Pages: [1]   Go Up
Jump to: