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