How do I change register values?

Hi, I am currently using the STEVAL-MKI208V1K sensor kit based on IIS3DWB. It is used with a 4-Bit Bidirectional Voltage-level Translator and Arduino Nano (ATMega328P) through SPI, where the Arduino is the Master and the sensor is the Slave.

IIS3DWB Datasheet
TXB0104 Datasheet
Arduino ATMega328P

I am facing problems in getting the acceleration values using the OUTX_L_A to OUTZ_H_A (0x28 to 0x2D) registers. However, I am able to read some registers such as the WHO_AM_I (0x0F) and PIN_CTRL (0x02) registers. When reading the values, I will change the bit 0 to 1 (in page 13 IIS3DWB Datasheet), and I have configured the SPI settings to MSB first. For example, if reading WHO_AM_I (0x0F) register, it will be changed to 0x8F. I am wondering why I am unable to change/set the register value for CTRL1_XL at 10100000 through doing a read register then a write.
I referred to these few websites: A example sketch for Arduino SPI communication | lbaigy's Tech-Blog , , .
Any help would be appreciated, thank you.

You failed to post your code so at the moment I expect the error to be in the code.

Hi, these are the codes I tried :

#include <SPI.h>

#define IIS3DWB_CTRL1_XL          0x10    //enable, disable axes
#define IIS3DWB_OUTX_L_XL         0x28    //x-axis acceleration data
#define IIS3DWB_OUTX_H_XL         0x29
#define IIS3DWB_OUTY_L_XL         0x2A    //y-axis acceleration data
#define IIS3DWB_OUTY_H_XL         0x2B
#define IIS3DWB_OUTZ_L_XL         0x2C    //z-axis acceleration data
#define IIS3DWB_OUTZ_H_XL         0x2D

SPISettings settings(1000000, MSBFIRST, SPI_MODE3);

//const int outPin = 11;                  // MOSI(SDA)(D2)
//const int inPin = 12;                   // MISO(SDO)(D3)
//const int clkPin = 13;                  // SCK(SCL) (D1)
const int CS = 10;                        // SS (CS) (D0)
const byte READ = 0x80;                   //read command |
const byte WRITE = 0x7F;                  //write command &

byte firstByte, secondByte;               //dummy data
int myArray[2] = {16, 160};               //decimal of 0x10 and 0xA0

void setup() {
  pinMode(CS, OUTPUT);
  digitalWrite(CS, LOW);
  SPI.transfer(myArray);                  //write 0x10 into 0xA0 register
  digitalWrite(CS, HIGH);

void loop() {
  digitalWrite(CS, LOW);
  SPI.transfer(0x10 | READ);              //check if reg changes (no change observed)
  firstByte = SPI.transfer(0);
  secondByte = SPI.transfer(0);
  digitalWrite(CS, HIGH);

Another code I got from online and modified it:

#include <SPI.h>

/*#define DATAOUT 11     //MOSI Arduino pin 11;
  #define DATAIN  12       //MISO Arduino pin12
  #define SPICLOCK  13     //SCK Arduino pin13
  #define CS 10            //CS

const int OUT_X_L = 0x28;              //X-axis acceleration data
const int OUT_X_H = 0x29;
const int OUT_Y_L = 0x2A;              //Y-axis acceleration data
const int OUT_Y_H = 0x2B;
const int OUT_Z_L = 0x2C;              //Z-axis acceleration data
const int OUT_Z_H = 0x2D;
const int CTRL1_XL = 0x10;             //enable, disable axes
const int WHO_AM_I = 0x0F;
const byte READ = 0b10000000;          //read command
const byte WRITE = 0b01111111;         //write command

int x_axis = 1;
int y_axis = 2;
int z_axis = 3;

SPISettings settings(1000000, MSBFIRST, SPI_MODE3);
const int CS = 10;

void setup()
  pinMode(CS, OUTPUT);
  writeRegister(CTRL1_XL, 0x07);

void loop()
  Serial.print(" x = ");
  Serial.print(" y = ");
  Serial.print(" z = ");

int getValue(int axis)
  int Val = 0;
  int h, l;
  if (axis == 1)
    l = readRegister(OUT_X_L);
    h = readRegister(OUT_X_H);
  else if (axis == 2)
    l = readRegister(OUT_Y_L);
    h = readRegister(OUT_Y_H);
  else if (axis == 3)
    l = readRegister(OUT_Z_L);
    h = readRegister(OUT_Z_H);

  //To get the full value, two bytes must be combined for each axis. That is why we shift eight bits left and set empty bits with l
  Val = ((h << 8) | l);

  return Val;

byte readRegister(byte thisRegister)
  byte result = 0;
  thisRegister = thisRegister >> 1;             //address bit 1-7, shift right by 1
  byte dataToSend = thisRegister | READ;        //combine register address and command into one byte
  digitalWrite(CS, LOW);
  //address = (0x80 | address);
  result = SPI.transfer(0x00);
  digitalWrite(CS, HIGH);
  return result;

void writeRegister(byte thisRegister, byte thisValue)
  thisRegister = thisRegister >> 1;
  byte dataToSend = thisRegister & WRITE;       //combine register address and command into one byte
  digitalWrite(CS, LOW);
  digitalWrite(CS, HIGH);

The first version doesn't even try to read the mentioned registers. Additionally the beginTransaction()/endTransaction() isn't used correctly.

The second version doesn't set CS HIGH by default, so the first read might fail. Also it shifts the register address for no obvious reason. I would expect the readRegister()/writeRegister() functions to fail for all register numbers.

I see, thank you the explanation. The beginTransation and endTransation have to be used together right.

You should use them at about the same place where you put the CS low and high.

Have you read the other comments? They are even more important for your case.