Reading ADXL312 with Bitbang C Code

ADXL312

The ADXL312 is little easy to use 3-axis accelerometer which is found on many sensor boards and cheap imu modules. It is low power and has a good resolution up to ±12g. To read this sensor you can use I2C or spi communication.

Here is my implementation of reading the ADXL312 with bitbang spi with MSP430F248 but the code is easy to port and will work on any microcontroller with minor changes.

Adxl312.c file

#include "Adxl312.h"

void init_acc_ports(void)
{
	P5OUT |= ACCEL_DI + ACCEL_CLOCK + ACCEL_CS;
	P5DIR |= ACCEL_DI + ACCEL_CLOCK + ACCEL_CS;

	CLOCK_HIGH();

	UNSELECT_ACCEL();
}



char adxl345_read(char register_address){

	char read_address=0;
	char register_value=0;
	int bit=0;

	read_address=0x80 | register_address;

	CLOCK_HIGH();
	SELECT_ACCEL();	//Lower CS pin.
	_nop();
	_nop();
	_nop();
	_nop();
	for(bit=7; bit>=0; bit--){
		CLOCK_LOW();

		if((read_address & (1<<bit))==(1<<bit)) ADXL_COM_PORT |= ACCEL_DI; 
else ADXL_COM_PORT &= ~ACCEL_DI; delay(1); CLOCK_HIGH(); _nop(); _nop(); _nop(); _nop(); } for(bit=7; bit&gt;=0; bit--){
		CLOCK_LOW();
		_nop();
		_nop();
		_nop();
		_nop();

		CLOCK_HIGH();
		_nop();
		_nop();
		_nop();
		_nop();

		if((ADXL_COM_PIN  & ACCEL_DO)==ACCEL_DO)
			register_value |= (1<<bit);
		else register_value &= ~(1<<bit); } UNSELECT_ACCEL(); return register_value; } void adxl345_write(char register_address, char register_value){ int bit=0; CLOCK_HIGH(); SELECT_ACCEL(); //Lower CS pin. delay(1); for(bit=7; bit&gt;=0; bit--){
		CLOCK_LOW();

		if((register_address & (1<<bit))==(1<<bit)) ADXL_COM_PORT |= ACCEL_DI; else ADXL_COM_PORT &= ~ACCEL_DI; _nop(); _nop(); _nop(); _nop(); CLOCK_HIGH(); _nop(); _nop(); _nop(); _nop(); } for(bit=7; bit&gt;=0; bit--){
		CLOCK_LOW();

		if((register_value & (1<<bit))==(1<<bit))
			ADXL_COM_PORT |= ACCEL_DI;
		else ADXL_COM_PORT &= ~ACCEL_DI;	
		_nop();
		_nop();
		_nop();
		_nop();

		CLOCK_HIGH();
		_nop();
		_nop();
		_nop();
		_nop();		
	}

	UNSELECT_ACCEL();

}

void read_Accelerations (int* x_value,int* y_value,int* z_value)
{
	char interrupt_source=0;
	char high_byte,low_byte;

	interrupt_source=adxl345_read(0x30); //read source reg
	if((interrupt_source & 0x80)== 0x80)
	{
		high_byte = adxl345_read(DATAX1);
		low_byte = adxl345_read(DATAX0);
		*x_value = (high_byte << 8) | low_byte;

		high_byte = adxl345_read(DATAY1);
		low_byte = adxl345_read(DATAY0);
		*y_value = (high_byte << 8) | low_byte;

		high_byte = adxl345_read(DATAZ1);
		low_byte = adxl345_read(DATAZ0);
		*z_value = (high_byte << 8) | low_byte;

	}

}

int setupADXL312 (void)
{
	char data=0;

	data=adxl345_read(0x00);
	adxl345_write(INT_ENABLE, DATA_READY);	//Activate Data Ready Interrupt
	adxl345_write(POWER_CTL, MEASURE);		// measurement mode	
	return (int)data;
}


Adxl312.h file

#ifndef ADXL312_H_
#define ADXL312_H_

#include 

#define READ	0x8000

#define	DEVID			0x00	//Device ID Register
#define POWER_CTL		0x2D	//Power Control Register
#define	INT_ENABLE		0x2E	//Interrupt Enable Control
#define	INT_MAP			0x2F	//Interrupt Mapping Control
#define	INT_SOURCE		0x30	//Source of interrupts
#define	DATA_FORMAT		0x31	//Data format control
#define DATAX0			0x32	//X-Axis Data 0
#define DATAX1			0x33	//X-Axis Data 1
#define DATAY0			0x34	//Y-Axis Data 0
#define DATAY1			0x35	//Y-Axis Data 1
#define DATAZ0			0x36	//Z-Axis Data 0
#define DATAZ1			0x37	//Z-Axis Data 1

#define	MEASURE		(1<<3)	//Measurement Mode

#define	DATA_READY	(1<<7)

#define ADXL_COM_PIN  	P5IN
#define ADXL_COM_PORT	P5OUT
#define ACCEL_DI		0x02
#define ACCEL_DO		0x04

#define ACCEL_CLOCK		0x01
#define ACCEL_CS		0x08

#define CLOCK_HIGH() P5OUT |= ACCEL_CLOCK  // Set clock high 
#define CLOCK_LOW()	 P5OUT &= ~ACCEL_CLOCK

#define	UNSELECT_ACCEL()  P5OUT |= ACCEL_CS
#define SELECT_ACCEL()	  P5OUT &= ~ACCEL_CS

int setupADXL312 (void);
void init_acc_ports(void);
void adxl345_write(char register_address, char register_value);
char adxl345_read(char register_address);
void delay(int y);
void read_Accelerations (int* x_value,int* y_value,int* z_value);
#endif /*ADXL312_H_*/