Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Unable to interface nrf51822 with LIS3DH (accelerometer) using SPI being nrf as master

Hi, 

I tried interfacing LIS3Dh using SPI, I used the SPI example to start with, when I didn't get the desired result, I look numerous question on the forum and tried to modify the code but it does not seem to be working.

I am simply trying to read WHO_AM_I register/or any other register, I am getting FF always, 

the sensor is embedded on PCB with following configurations: 

Configurations:

LIS3DH nrf 51822 pin  sdk_config.h 
SCK 9 SPI_SCK_PIN 9
SDI 10 SPI_MOSI_PIN 10
CS 12 SPI_SS_PIN 12
SDO 7 SPI_MISO_PIN 11

Below code is trying to read who_am_i ( 0x0F) 

#define SPI_INSTANCE  0 /**< SPI instance index. */
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */

#define TEST_STRING "Nordic"
static uint8_t       m_tx_buf[]={0x0F};           /**< TX buffer. */
static uint8_t       m_rx_buf[]={0x00, 0x00,0x00, 0x00,0x00};    /**< RX buffer. */
//static const uint8_t m_length = sizeof(m_rx_buf);        /**< Transfer length. */

/**
 * @brief SPI user event handler.
 * @param event
 */
void spi_event_handler(nrf_drv_spi_evt_t const * p_event)
{
    spi_xfer_done = true;
    SEGGER_RTT_printf(0,"Transfer completed.\r\n");
    if (1 != 0)
    {
        SEGGER_RTT_printf(0," Received: \r\n");
        NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
        SEGGER_RTT_printf(0, "value: %u \r\n", *m_rx_buf);
        bsp_board_led_invert(BSP_BOARD_LED_1);
    }
}

int main(void)
{
    bsp_board_leds_init();

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));

    SEGGER_RTT_printf(0,"SPI example\r\n");

   nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
	spi_config.ss_pin   = SPI_SS_PIN;
	spi_config.miso_pin = SPI_MISO_PIN;
	spi_config.mosi_pin = SPI_MOSI_PIN;
	spi_config.sck_pin  = SPI_SCK_PIN;
	spi_config.frequency= NRF_DRV_SPI_FREQ_8M;
	spi_config.mode= NRF_DRV_SPI_MODE_2;
        
	APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler));
        
       
        uint8_t sizerx = 2;
        spi_xfer_done = false;
        
        APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, 1, m_rx_buf, sizerx));
        while (!spi_xfer_done){
	  __WFE();
        }

        if(sizerx!=0)
        {
            SEGGER_RTT_printf(0,"Received[0]: %x %x %x %x %x \n\r",m_rx_buf[0],m_rx_buf[1],m_rx_buf[2],m_rx_buf[3],m_rx_buf[4]);
        }else{
            SEGGER_RTT_printf(0,"no value return from \r\n");
        }
      
      SEGGER_RTT_printf(0,"miso-> %u \r\n", nrf_gpio_pin_out_read(11));
      SEGGER_RTT_printf(0,"mosi-> %u \r\n", nrf_gpio_pin_out_read(10));
      SEGGER_RTT_printf(0,"ss-> %u \r\n", nrf_gpio_pin_out_read(12));
                     
}

log output ( in every case I am getting FF value in rx_buff ) 

SDK Used: 12.2

using JLink to transfer the via SWO

I have tried with different modes and frequencies also but no luck. 

Please help.

  • Sorry, my bad. I did try mode 0, which is the default one.

    I slightly modified the SPI example in SDK 14.2, here how it looks like.

    0x0F is the WHO_AM_I register, and I tried too 0X8F (bit 7 high for read operation).

    I really appreciate your help, thanks . There are a few other threads about this same problem here in the devzone.

    #include "nrf_drv_spi.h"
    #include "app_util_platform.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    #include "boards.h"
    #include "app_error.h"
    #include <string.h>
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #include "nrf_gpio.h"
    
    #define SPI_INSTANCE  0 /**< SPI instance index. */
    static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
    static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */
    
    // according to sdk_config.h
    //SPI0_ENABLED 1
    //SPI0_USE_EASY_DMA 1
    //SPI_SCK_PIN 3
    //SPI_MISO_PIN 28
    //SPI_MOSI_PIN 4
    //SPI_SS_PIN 29
    
    //#define TEST_STRING "Nordic"
    static uint8_t       m_tx_buf[] = {0x0F,0x00};           /**< TX buffer. */
    static uint8_t       m_rx_buf[] = {0x00,0x00};    /**< RX buffer. */
    static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */
    
    /**
     * @brief SPI user event handler.
     * @param event
     */
    void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                           void *                    p_context)
    {
        spi_xfer_done = true;
        NRF_LOG_INFO("Transfer completed.");
        if (m_rx_buf[0] != 0)
        {
            NRF_LOG_INFO(" Received:");
            NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
        }
    }
    
    int main(void)
    {
        bsp_board_leds_init();
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
        
        NRF_LOG_INFO("SPI example.");
    
        nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
        spi_config.ss_pin    = SPI_SS_PIN;
        spi_config.miso_pin  = SPI_MISO_PIN;
        spi_config.mosi_pin  = SPI_MOSI_PIN;
        spi_config.sck_pin   = SPI_SCK_PIN;
        spi_config.frequency = NRF_SPI_FREQ_125K;
        APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
    
        while (1)
        {
            // Reset rx buffer and transfer done flag
            memset(m_rx_buf, 0, m_length);
            spi_xfer_done = false;
    
            bsp_board_led_invert(BSP_BOARD_LED_0);
            
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, 2, m_rx_buf, 2));
    
            while (!spi_xfer_done)
            {
                __WFE();
            }
    
            NRF_LOG_FLUSH();
    
            bsp_board_led_invert(BSP_BOARD_LED_0);
            nrf_delay_ms(1000);
        }
    }
    

  • Ah-Ha! Try reading .. use 0x8F not 0x0F .. similar to this - or did you try that I now notice above

        uint8_t tx_buf[] = {0x80|LIS2DH12_WHO_AM_I, 0xFF};
    

  • I tried this, not working :/

    I appealed to the oscilloscope and this is my SPI bitbang that works

    Blue is the clock and yellow is the mosi of 0x8f (read whoami)
    mosi (y) and clock (b) of 0x8F

    Blue is the clock and yellow is the chip select

    Chip select (y) and clock (b)

    ------

    Now the part that doesn't work, from the nordic sdk api call to spi.

    Please note that this is on MODE 0.


       

    nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
    spi_config.ss_pin    = SPI_SS_PIN;
    spi_config.miso_pin  = SPI_MISO_PIN;
    spi_config.mosi_pin  = SPI_MOSI_PIN;
    spi_config.sck_pin   = SPI_SCK_PIN;
    spi_config.frequency = NRF_SPI_FREQ_125K;
    spi_config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;
    spi_config.mode      = NRF_DRV_SPI_MODE_0; 

    Blue is the clock and yellow is the mosi of 0x8f (read whoami)

    Clock (b) and mosi (y)

    Blue is clock and yellow is the chip select

    clock (b) and cs (y)

    Blue is the clock and yellow is the mosi of {0x8f,0xff} (read whoami), like suggested

    Clock (b) and miso (y)

  • The LIS3DH clocks data in on the rising clock edge; hence last 'scope screenshot shows a transmitted command value of 0x87 not 0x8F. The traces would be easier to read if they were vertically separated slightly .. while still overlapping. Perhaps post the function you are using to generate this trace, in case we see something there ..

  • It is weird, but I used the example from the sdk 14.2. I just modified the buffer to the register I wanted.

    #include "nrf_drv_spi.h"
    #include "app_util_platform.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    #include "boards.h"
    #include "app_error.h"
    #include <string.h>
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #include "nrf_gpio.h"
    
    #define SPI_INSTANCE  0 /**< SPI instance index. */
    static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
    static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */
    
    //sck//scl 03
    //miso//sdo 28
    //mosi//sda 4
    //ss/cs 29 
    
    //#define TEST_STRING "Nordic"
    static uint8_t       m_tx_buf[] = {0x87,0x00};           /**< TX buffer. */
    static uint8_t       m_rx_buf[] = {0x00,0x00};    /**< RX buffer. */
    static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */
    
    /**
     * @brief SPI user event handler.
     * @param event
     */
    void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                           void *                    p_context)
    {
        spi_xfer_done = true;
        NRF_LOG_INFO("Transfer completed.");
        if (m_rx_buf[0] != 0)
        {
            NRF_LOG_INFO(" Received:");
            NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
        }
    }
    
    int main(void)
      {
        bsp_board_leds_init();
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
        
        NRF_LOG_INFO("SPI example.");
    
        nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
        spi_config.ss_pin    = SPI_SS_PIN;
        spi_config.miso_pin  = SPI_MISO_PIN;
        spi_config.mosi_pin  = SPI_MOSI_PIN;
        spi_config.sck_pin   = SPI_SCK_PIN;
        spi_config.frequency = NRF_SPI_FREQ_125K;
        spi_config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;
        spi_config.mode      = NRF_DRV_SPI_MODE_3;           
        APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
    
        while (1)
        {
            // Reset rx buffer and transfer done flag
            memset(m_rx_buf, 0, m_length);
            spi_xfer_done = false;
    
            bsp_board_led_invert(BSP_BOARD_LED_0);
            
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length));
    
            while (!spi_xfer_done)
            {
                __WFE();
            }
    
            NRF_LOG_FLUSH();
    
            bsp_board_led_invert(BSP_BOARD_LED_0);
            nrf_delay_ms(1000);
        }
    }

Related