Reading BMA280 data via SPI with Due

Hi everyone, I’m trying to use the Arduino Due to read sensor data from the BMA280. This is a 3-axis accelerometer (datasheet: Protocol that I use is SPI.

Acceleration data for each axis has a width of 14-bit. Problem is, for each axis I always get 65532, which is (1111111111111100)2. I don’t understand why it keeps returning this value. I bit-masked the last two bits because these are useless data as specified in the datasheet. The codes are as shown:

#include <SPI.h>

const int CS = 52;

byte PMU_Range = 0x0F;
byte PMU_BW = 0x10;
byte PMU_SELF_TEST = 0x32;

byte DATAX0 = 0x02;   // x-axis LSB
byte DATAX1 = 0x03;   // x-axis MSB

void setup(){

SPI.setDataMode(CS, 0);   // set SPI mode to '00'
SPI.setClockDivider(CS, 84);


pinMode(CS, OUTPUT);
digitalWrite(CS, HIGH);

writeRegister(PMU_Range, 0x03);   // set ge-range to +/- 2G
writeRegister(PMU_BW, 0x0E);   // set bandwidth to 500Hz
writeRegister(PMU_SELF_TEST, 0x00);   // disable self-test


void loop(){
// read 2 bytes of data (LSB and MSB of x-axis) starting at register DATAX0
unsigned int xData = readRegister(DATAX0, 2);



void writeRegister(byte registerAddress, byte value){
// Set Chip Select pin low to signal the beginning of an SPI packet.
digitalWrite(CS, LOW);
// Transfer the register address over SPI.
// Transfer the desired register value over SPI.
// Set the Chip Select pin high to signal the end of an SPI packet.
digitalWrite(CS, HIGH);

unsigned int readRegister(byte thisRegister, int bytesToRead) {
byte lsb = 0;           // least significant byte
unsigned int msb = 0;   // most significant byte

// read process requires setting the first bit to 1
thisRegister = 0x80 | thisRegister;

digitalWrite(CS, LOW);


// read least significant byte returned
lsb = SPI.transfer(0x00);
// decrement the number of bytes left to read:

if (bytesToRead > 0) {
 // read most significant byte returned
 msb = SPI.transfer(0x00);
 // shift most significant byte left
 msb = msb << 8;
 // combine the byte you just got with the previous one:
 msb = msb | (lsb & 0xFC);
 // decrement the number of bytes left to read:
// take the chip select high to de-select:
digitalWrite(CS, HIGH);
// return the result:
return (msb);

I’m using the BMA280 shuttle board (schematic in attachment) which is easy to wire, so I suppose the problem lies in the software. I’d be grateful for any advice. Thanks! :slight_smile:

shuttle board schematic.jpg

Some thoughts:

After a fast reading of the datasheet, it appears that this sensor can be read in SPI 4 wires by default or 3 wires.

If you are using the default SPI mode 4 wires (Pin 11 to Gnd, page 106), I guess connections should be:
SDI to MOSI, SDO to MISO, CSM to CSS, SCK to SCK, Gnd to Gnd. Is that your wiring ?

I noticed (datasheet page 18) that :
Accel_Data = (uint16_t) (MSB << 6) // Bits 13 to 6
| (uint16_t)(LSB & 0b00111111); // Bits 6 to 0, remove flag bits
which is not what I can see in your code.

Hi ard_newbie, thanks for your reply!

  1. Yes I'm using the SPI 4 wire mode, and the wiring is as you've stated.

  2. I tried using the code you suggested, but it still doesn't work, it keeps returning 16383. I suppose the SPI is not initiated properly in the first place. But I have no clue how I can modify the code.

Now it works and returns reasonable values. :slight_smile:

I was using the ICSP interface and I changed to the SPI interface on the Due. Apart from that I added the command SPI.setBitOrder(CS, LSBFIRST) to the code.