Arduino and ADXL345 via SPI

Hi guys,

I'm a complete noob to using the arduino and I have a bit of a problem. I have the above accelerometer and I want to control it via SPI.

However I can't seem to get anything back from it.

The code I have currently looks like this:

// define spi bus pins
#define SLAVESELECT 10
#define SPICLOCK 13
#define DATAOUT 11      //MOSI
#define DATAIN 12       //MISO
#define UBLB(a,b)  ( ( (a) << 8) | (b) )
#define UBLB19(a,b) ( ( (a) << 16 ) | (b) )

//Addresses
#define REVID 0x00      //ASIC Revision Number

char rev_in_byte;          
int temp_in;
unsigned long x;
unsigned long y;
unsigned long z;

void setup()
{
  byte clr;
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device  
  
  SPCR = B01010011; //MPIE=0, SPE=1 (on), DORD=0 (MSB first), MSTR=1 (master), CPOL=0 (clock idle when low), CPHA=0 (samples MOSI on rising edge), SPR1=0 & SPR0=0 (500kHz)
  
  clr=SPSR;
  clr=SPDR;
  delay(10);
  Serial.begin(9600);
  delay(500);

  Serial.print("Command Register set to ");
  Serial.println(SPCR, DEC);

  char tmp = read_register(0x31);

  Serial.print("Read from reg 0x31 ");
  Serial.println(tmp, DEC);

  rev_in_byte = read_register(REVID);
  
  Serial.print("Device id ");
  Serial.println(rev_in_byte, DEC);

  tmp &= 0xEF;

  Serial.print("Writing back to reg 0x31 ");
  Serial.println(tmp, DEC);

  write_register(0x31, tmp);

  Serial.println("Setup complete");
}

void loop()
{
  // Todo
  
  delay(250);
}

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


char read_register(char register_name)
{
    char in_byte;
    register_name <<= 2;
    register_name &= B11110100; //Read command
  
    digitalWrite(SLAVESELECT,LOW); //Select SPI Device
    delay(10);
    spi_transfer(register_name); //Write byte to device
    in_byte = spi_transfer(0x00); //Send nothing, but we should get back the register value
    digitalWrite(SLAVESELECT,HIGH);
    delay(10);    
    return(in_byte);

}

void write_register(char register_name, char register_value)
{
    register_name <<= 2;
    register_name |= B00000010; //Write command

    digitalWrite(SLAVESELECT,LOW); //Select SPI device
    spi_transfer(register_name); //Send register location
    spi_transfer(register_value); //Send value to record into register
    digitalWrite(SLAVESELECT,HIGH);
}

This code borrows heavily from some other code I found on the web for SPI comms to a barometer.

It doesn't do much at present, just a simple query of the data format register, but even this doesn't work.

I've also tried changing the SPDR values, to what I think the data sheet is telling me, but still no joy - the original settings are above however.

Can anyone tell me if there's something obviously wrong with the code, or whether I should look to wiring as being the problem or the chip being dud.

FYI the wiring is as follows:

adxl345 / Arduino

SCL = 13
SDA = 11
SDO = 12
CS = 10
VCC = 3v3
GND = Gnd

I have tried swapping the MISO and MOSI in the code above, but still no luck.

Thanks in advance guys.

Nobody answered you? Well I have the ADXL345 and I have it in a circuit with an SD card and the Nano 3.0. I am still working on the code but I will post on my efforts to get it working.

Thanks for putting up the code, it has given me a head start :slight_smile:

My pinout:

SCL: 13
SDA: 11
SDO: 12
CS: 9 (I have 10 reserved for the SD card)

My efforts to communicate with the SD card have been successful, still writing the bit for the sensor, so I might have a new update in a few days or so, hopefully I might be able to help your efforts as well.

Thanks,
Chris

Well still working on reading register values on the ADXL345. Although after looking through the datasheet several times I did find some issues with your original code.

SPCR = B01010011; //MPIE=0, SPE=1 (on), DORD=0 (MSB first), MSTR=1 (master), CPOL=0 (clock idle when low), CPHA=0 (samples MOSI on rising edge), SPR1=0 & SPR0=0 (500kHz)

The timing diagram for SPI 4-Wire Read shows that the clock is high when idle and data is read on the trailing edges of SCLK.

It also states in the datasheet,

The maximum SPI clock speed is 5 MHz with 100 pF maximum loading, and the timing scheme follows clock polarity (CPOL) = 1 and clock phase (CPHA) = 1.

So I changed my SPCR setup to this

//////////////////////////////
  // Initialize SPI control register (SPCR)
  // SPIE = 0
  // SPE  = 1 (On)
  // DORD = 0 (MSB first)
  // MSTR = 1 (Master)
  // CPOL = 1 (SCK High when idle)
  // CPHA = 1 (Sample data on trailing edge of clock)
  // SPR1/SPR0 = 11 (slowest (250KHz)
  
  SPCR = B01011111;

Like I said, im not getting back values still but I am thinking this is still the appropriate setup.