PDA

View Full Version : Working with Arduino and SPI



crenn
08-10-2010, 09:05 AM
Working with Arduino and SPI


Summary
What I plan to do is show you how to work with an SPI device and an arduino. This includes setting up the registers, setting the mode of SPI and setting the speed of communication.

Why?
For one of the projects I'm working on, I have to interface with a triple axis accelerometer (An ADXL345) and get values back that I can use to help stabilise a mechanical system. I got this sensor almost a year ago and have only recently started getting it to work due to my limited knowledge at the time. One of the main problems that happened when I went to test this sensor was the different voltage levels, the micro that I had intended to use was 5v and the sensors were all 3.3v; and to solve this problem I had to bring in a voltage translator so I wouldn't burn out the sensor. The next problem I came up against was the electronics I designed, needed to be programmed, and also work with the various sensors. However I had a slight problem getting a custom PCB (we were out of budget) and using vero board resulted in a short somewhere which disabled the entire system. This was the first time I designed a system, and I learnt a lot. Regardless, fast forward to a few months ago. I decide to have another crack of getting this sensor to work, and I've mostly got it working (it's now a hardware issue which needs to be resolved, the software is working fine though). So I thought I might share the software side of what I did.

Why SPI and not I2C (Wire)?
The reason I went for SPI over I2C was:
SPI is faster than I2C
Easier for me to do the voltage translations than I2C
I2C has bidirectional data lines which makes it difficult to do the voltage translations (I've recently discovered there is an easy and interesting way to do it, but that's for another time and when I can try it)
Also note that there is 2 versions of SPI, 3 wire SPI and 4 wire SPI, I'm using 4 wire SPI as I'd encounter the same problem with 3 wire SPI that I had with I2C
Lack of knowledge about doing I2C communication (and SPI, although SPI seemed easier to me)Current state of code and example output

#define DATAOUT 11//MOSI orange wire
#define DATAIN 12//MISO
#define SPICLOCK 13//sck
#define SLAVESELECT 10//ss

#define SPI_CONTROL (1<<SPE)|(1<<MSTR)|(1<<CPHA)|(1<<CPOL)|

#define RW_MASK 0x80
#define MB_MASK 0x40
#define CB_MASK (RW_MASK|MB_MASK)


byte spi_transfer(byte data)
{
SPDR = data; // Start the transmission
while(!(SPSR & (1<<SPIF))); // Wait the end of the transmission
return SPDR; // return the received byte
}


void writeADXL(byte reg, byte data){
Serial.println("Slave low");
Serial.println("Transferring");
digitalWrite(SLAVESELECT,LOW);
delayMicroseconds(1);
spi_transfer(((~CB_MASK)&reg)); //write instruction and address
spi_transfer(data); //send data
delayMicroseconds(1);
digitalWrite(SLAVESELECT,HIGH);
delayMicroseconds(1);
Serial.println("Slave High");
Serial.print("Tranferred ");
Serial.print(data, HEX);
Serial.print(" to ");
Serial.println(reg, HEX);
}

byte readADXL(byte reg){
byte temp=0;
digitalWrite(SLAVESELECT,LOW);
delayMicroseconds(1);
spi_transfer(((~CB_MASK)&reg)|0x80); //read instruction and address
temp=spi_transfer(0xFF); //send data
delayMicroseconds(1);
digitalWrite(SLAVESELECT,HIGH);
delayMicroseconds(1);
Serial.print("Reg is ");
Serial.print(reg, HEX);
Serial.print(", data reads ");
Serial.println(temp, HEX);
return temp;
}

void intAXDL(){
writeADXL(0x2D,0x28);
delay(20);
writeADXL(0x31,0x0F);
delay(20);
writeADXL(0x38,0x00);
delay(20);
}


void setup()
{
byte clr;
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK, OUTPUT);
pinMode(SLAVESELECT, OUTPUT);
digitalWrite(SLAVESELECT,HIGH);
// start serial port at 9600 bps:
Serial.begin(9600);
SPCR = 0b01011111; //(1<<SPE)|(1<<DORD)|(1<<MSTR);
SPSR = 0;
clr=SPSR;
clr=SPDR;
delay(10);
Serial.println("Set mode");
intAXDL();
Serial.println("Initialization finished");
}

void loop()
{
readADXL(0x00);
readADXL(0x36);
readADXL(0x37);
delay(500);
} This is it for now, however there will be updates tomorrow on this post including newer, commented and cleaner code and a full explanation of everything going on.

crenn
08-10-2010, 09:05 AM
Reserved Post 1 - Just in case

crenn
08-10-2010, 09:06 AM
Reserved Post 2 - Just making sure

EDIT: If These additional posts aren't required, I'll delete them.

SXRguyinMA
08-10-2010, 12:42 PM
this should be neat, I can't wait to see what you come up with!