
In part 1 (here), we saw to configure the SPI and other parameters required for ADXL345 operation in SPI mode. We shall continue from here:
8. adx345 read/write functions:
In order for the adxl345 to distinguish between SPI and I2C, when sending the address, a bit shall be set called multibyte as shown here:

Hence, we shall create two symbolic names for read operation and multibyte as following:
#define MULTI_BYTE_EN 0x40 #define READ_OPERATION 0x80
Hence, the adxl345 read function as following:
static void adxl345_read(uint8_t address, uint8_t * rxdata)
{
/*Set read operation*/
address |= READ_OPERATION;
/*Enable multi-byte*/
address |= MULTI_BYTE_EN;
/*Pull cs line low to enable slave*/
cs_enable();
/*Send address*/
spi1_transmit(&address,1);
/*Read 6 bytes */
spi1_receive(rxdata,6);
/*Pull cs line high to disable slave*/
cs_disable();
}
adxl345 write function:
static void adxl345_write(uint8_t address, uint8_t value)
{
uint8_t data[2];
/*Enable multi-byte, place address into buffer*/
data[0] = address|MULTI_BYTE_EN;
/*Place data into buffer*/
data[1] = value;
/*Pull cs line low to enable slave*/
cs_enable();
/*Transmit data and address*/
spi1_transmit(data, 2);
/*Pull cs line high to disable slave*/
cs_disable();
}The initialization is similar to the i2c guide:
void adxl345_init(adxl345Parameters param)
{
acc_range=param;
adxl_spi_pins_init();
adxl_spi_config();
/*Set data format range to +-4g*/
adxl345_write (DATA_FORMAT_R, param);
/*Reset all bits*/
adxl345_write (POWER_CTL_R, RESET);
/*Configure power control measure bit*/
adxl345_write (POWER_CTL_R, SET_MEASURE_B);
}
For the update adxl345 function:
void adxl345_update()
{
adxl345_read(DATA_START_ADDR,data_rec);
x = ((data_rec[1]<<8)|data_rec[0]);
y = ((data_rec[3]<<8)|data_rec[2]);
z = ((data_rec[5]<<8)|data_rec[4]);
}
For getting the values:
void adxl345_get_values(accleration_values_t * values)
{
float divider;
switch(acc_range)
{
case accl_2g: divider=0.003906; /*1/256*/ break;
case accl_4g: divider=0.0078125;/*1/128*/ break;
case accl_8g: divider=0.01563; /*1/64*/ break;
case accl_16g: divider=0.03125; /*1/32*/ break;
}
values->ax=x*divider;
values->ay=y*divider;
values->az=z*divider;
}
Hence, the entire adxl345.c source file:
#include "adxl345.h"
#include "spi.h"
#define DATA_FORMAT_R (0x31) /*data format register*/
#define POWER_CTL_R (0x2D) /*Power control register*/
#define DATA_START_ADDR (0x32) /*Start address to read the values*/
#define RESET (0x00) /*Reset value*/
#define SET_MEASURE_B (0x08) /*Put adxl345 into measurement mode*/
/*Variables which hold some variable*/
uint8_t data_rec[6];
uint8_t acc_range;
int16_t x,y,z;
#define MULTI_BYTE_EN 0x40
#define READ_OPERATION 0x80
static void adxl345_write(uint8_t address, uint8_t value)
{
uint8_t data[2];
/*Enable multi-byte, place address into buffer*/
data[0] = address|MULTI_BYTE_EN;
/*Place data into buffer*/
data[1] = value;
/*Pull cs line low to enable slave*/
cs_enable();
/*Transmit data and address*/
spi1_transmit(data, 2);
/*Pull cs line high to disable slave*/
cs_disable();
}
static void adxl345_read(uint8_t address, uint8_t * rxdata)
{
/*Set read operation*/
address |= READ_OPERATION;
/*Enable multi-byte*/
address |= MULTI_BYTE_EN;
/*Pull cs line low to enable slave*/
cs_enable();
/*Send address*/
spi1_transmit(&address,1);
/*Read 6 bytes */
spi1_receive(rxdata,6);
/*Pull cs line high to disable slave*/
cs_disable();
}
void adxl345_init(adxl345Parameters param)
{
acc_range=param;
adxl_spi_pins_init();
adxl_spi_config();
/*Set data format range to +-4g*/
adxl345_write (DATA_FORMAT_R, param);
/*Reset all bits*/
adxl345_write (POWER_CTL_R, RESET);
/*Configure power control measure bit*/
adxl345_write (POWER_CTL_R, SET_MEASURE_B);
}
void adxl345_update()
{
adxl345_read(DATA_START_ADDR,data_rec);
x = ((data_rec[1]<<8)|data_rec[0]);
y = ((data_rec[3]<<8)|data_rec[2]);
z = ((data_rec[5]<<8)|data_rec[4]);
}
void adxl345_get_values(accleration_values_t * values)
{
float divider;
switch(acc_range)
{
case accl_2g: divider=0.003906; /*1/256*/ break;
case accl_4g: divider=0.0078125;/*1/128*/ break;
case accl_8g: divider=0.01563; /*1/64*/ break;
case accl_16g: divider=0.03125; /*1/32*/ break;
}
values->ax=x*divider;
values->ay=y*divider;
values->az=z*divider;
}
adxl345.h header file:
#ifndef ADXL345_H_
#define ADXL345_H_
#include "stdint.h"
typedef enum
{
accl_2g=0,
accl_4g=1,
accl_8g=2,
accl_16g=3
}adxl345Parameters;
typedef struct
{
float ax;
float ay;
float az;
}accleration_values_t;
void adxl345_init(adxl345Parameters param);
void adxl345_update();
void adxl345_get_values(accleration_values_t * values);
#endif /* ADXL345_H_ */
Within main.c:
#include "delay.h"
#include "adxl345.h"
#include "stdio.h"
accleration_values_t accleration_values;
extern void uart2_rxtx_init(void);
int main(void)
{
uart2_rxtx_init();
adxl345_init(accl_4g);
while(1)
{
adxl345_update();
adxl345_get_values(&accleration_values);
printf("ax=%0.5f\tay=%0.5f\taz=%0.5f\r\n",accleration_values.ax,accleration_values.ay,accleration_values.az);
delay(20);
}
}
9. Code:
You may download the entire code from here:
10. Results:
Open your serial terminal application and set the baudrate to 115200 and you should get the following:

2 Comments
Dear Sir,
Namaskar, Good Morning,
Observed that the main.c in the Zipped version of code downloaded has i2c_init(),
if wrongly placed please make this corrections, else kindly neglect this mail,
sorry for the interruption.
thanks withr egards,
HSR-Rao.
Hi,
yes, I noticed it to.
However, it won’t effect the operation of the code.
Add Comment