Reading LIS2DH12 register via SPI

Hi.

I am using a custom board on an nRF52810 microcontroller and a LIS2DH12 accelerometer connected to it via SPI. SDK version 2.7.0. 

Here's my settings:

.dts file -->

&spi0 {
    compatible = "nordic,nrf-spim";
	status = "okay";
	pinctrl-0 = <&spi0_default>;
	pinctrl-1 = <&spi0_sleep>;
	pinctrl-names = "default", "sleep";
	cs-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
	
	lis2dh12: lis2dh12@0{
        compatible = "st,lis2dh";
        reg = <0>;
		spi-max-frequency = <10000000>;
    };
};

Devicetree visual editor screen -->

pinctrl file -->

&pinctrl {

	spi0_default: spi0_default {
		group1 {
				psels = <NRF_PSEL(SPIM_SCK, 0, 9)>,
						<NRF_PSEL(SPIM_MOSI, 0, 6)>,
						<NRF_PSEL(SPIM_MISO, 0, 7)>;
		};
	};

	spi0_sleep: spi0_sleep {
		group1 {
				psels = <NRF_PSEL(SPIM_SCK, 0, 9)>,
						<NRF_PSEL(SPIM_MOSI, 0, 6)>,
						<NRF_PSEL(SPIM_MISO, 0, 7)>;
				low-power-enable;
		};
	};

};

prj.conf -->

# Enable SPI
CONFIG_SPI=y

main.c code -->

...
#include <zephyr/drivers/spi.h>
...

#define SLEEP_TIME_MS   3000

#define SPIOP SPI_WORD_SET(8) | SPI_TRANSFER_MSB
struct spi_dt_spec lis2dh12_spi = SPI_DT_SPEC_GET(DT_NODELABEL(lis2dh12), SPIOP, 0);

int32_t lis2dh12_read_reg(uint8_t reg, uint8_t *data, uint8_t size)
{
  int ret;

  if (data == NULL || size == 0) {
    return -EINVAL;
  }
 
  uint8_t tx_buffer = reg | 0x80;
  struct spi_buf tx_spi_buf = {.buf = (void *)&tx_buffer, .len = 1};
  struct spi_buf_set tx_spi_buf_set = {.buffers = &tx_spi_buf, .count = 1};
  
  uint8_t rx_buffer[size + 1];
  struct spi_buf rx_spi_bufs = {.buf = rx_buffer, .len = size + 1};
  struct spi_buf_set rx_spi_buf_set = {.buffers = &rx_spi_bufs, .count = 1};

  ret = spi_transceive_dt(&lis2dh12_spi, &tx_spi_buf_set, &rx_spi_buf_set);
  if (ret < 0) {
    LOG_ERR("spi_transceive_dt() failed, err: %d", ret);
    return ret;
  }

  memcpy(data, rx_buffer + 1, size);

  return 0;
}

int main(void)
{ 	
	int ret;
	uint8_t who_am_i;

	if (!device_is_ready(lis2dh12_spi.bus)) {
    printf("SPI bus %s is not ready\n", lis2dh12_spi.bus->name);
    return 0;
	}

	while (1) {

   // Read register WHO_AM_I
    ret = lis2dh12_read_reg(0x0F, &who_am_i, 1);
    if (ret == 0) {
        LOG_DBG("WHO_AM_I value: 0x%02X", who_am_i);
        if (who_am_i == 0x33) {  // 0x33 - expected value for LIS2DH12
            LOG_DBG("LIS2DH12 successfully identified");
        } else {
            LOG_DBG("Unexpected value WHO_AM_I\n");
        }
    } else {
        LOG_DBG("Error reading WHO_AM_I: %d\n", ret);
    }

	    k_msleep(SLEEP_TIME_MS);
	}
	
	return 0;
}

Terminal output -->

Logic analyzer output -->

As you can see, I get the wrong WHO_AM_I register value when reading. For some reason there is no signal on the SCK line (although there is physical contact between the microcontroller and LIS2DH12). Perhaps I made a mistake in the dts setup or code?
Please help me to solve this problem.

Also I don't understand why in devicetree editor the maximum frequency is 8MHz, although I set it to 10MHz?

Thanks.

Parents Reply
  • Hi,

    I don't understand why in devicetree editor the maximum frequency is 8MHz, although I set it to 10MHz?

    I think this is probably because the maximum supported speed for the 52810 is 8MHz :

    For some reason there is no signal on the SCK line (although there is physical contact between the microcontroller and LIS2DH12).

    Could you check that the pins you have used for the SPI communication , P0.06 - P0.08 are used solely for the SPI communication and are not used otherwise anywhere?

    -Priyanka

Children
Related