This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SPI Communication is not working in NRF52840

Hi,

I am using nrf52840 customized dongle  in our project. We have interfaced ADS1118 using spi communication with nrf52840 (customized dongle). The problem here with the spi communication is i am not able to read the data from the ADS1118  using spi communication i am reading the adc value as 0.

When we checked with the oscilloscope  we are not getting clk signal ,MISO ,MOSI signal only Chip select is high.

I am here by attaching the code Please give me the solution what could be the problem.

/**
* Copyright (c) 2015 - 2019, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#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 "SEGGER_RTT.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. */

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

/**
* @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.");
SEGGER_RTT_printf(0," Transfer completed\n");

for(int i=0;i<5;i++)
{
NRF_LOG_INFO("Data=%x\n.",m_rx_buf[i]);
}

if (m_rx_buf[0] != 0)
{
NRF_LOG_INFO(" Received:");
SEGGER_RTT_printf(0," Recieved\n");

NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
}
}

int main(void)
{
bsp_board_init(BSP_INIT_LEDS);
uint8_t data=0xff;

APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
NRF_LOG_DEFAULT_BACKENDS_INIT();

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;
APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));

NRF_LOG_INFO("SPI example started.");

while (1)
{
// Reset rx buffer and transfer done flag
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;

nrf_gpio_cfg_output(31);
nrf_delay_us(100);


nrf_gpio_pin_clear(31);
nrf_delay_ms(100);
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf1, m_length, m_rx_buf1, m_length));
SEGGER_RTT_printf(0," Data Received1: %x\n",m_rx_buf1[0]);
SEGGER_RTT_printf(0," Data Received2: %x\n",m_rx_buf1[1]);


APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length));
SEGGER_RTT_printf(0," Received1: %x\n",m_rx_buf[0]);
SEGGER_RTT_printf(0," Received2: %x\n",m_rx_buf[1]);

nrf_delay_ms(200);
nrf_delay_ms(200);
nrf_gpio_pin_set(31);

while (!spi_xfer_done)
{
__WFE();
}

NRF_LOG_FLUSH();

bsp_board_led_invert(BSP_BOARD_LED_0);
nrf_delay_ms(500);
}
}

Parents
  • Hi,

    My guess is that either the program is asserting or you're not measuring on the correct pins. The latter might be due to using the wrong board file or pin assignments etc. The former can be checked by using an external debugger and debugging the fw on the Dongle. 

    regards

    Jared 

  • Thanks for the reply.

    We have checked that we are measuring on the correct pins and there is no problem in pin assignment also .But the doubt is the programming can you pleas tell me whether the programming is correct or do i need to make changes in the program  as  i had initialized the ads1118  of the configuration registers in the program. I am attaching the program file here.

    The doubt is do we need to pull up the pin of MISO,MOSI, CS pin in hardware?

    /**
     * Copyright (c) 2015 - 2019, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    #include <stdbool.h>
    #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 "SEGGER_RTT.h"
    #include "ADS118.h"
    //#include "drv_gpio.h"
    #include "boards.h"
    #include "nrf_gpio.h"
    #include "nrf_drv_gpiote.h"
    #include "app_error.h"
    #include "nrf_drv_qspi.h"
    
    
    static volatile bool m_finished = false;
    
    
    static uint8_t       m_tx_buf[2]; //= TEST_STRING;           /**< TX buffer. */
    static uint8_t       m_rx_buf[5];//sizeof(TEST_STRING) + 1];    /**< RX buffer. */
    static const uint8_t m_length = sizeof(40);        /**< Transfer length. */
    static uint8_t       m_rx_buf1[6];//sizeof(TEST_STRING) + 1];    /**< RX buffer. */
    
    
    
    
    
    #define SPI_INSTANCE  0 /**< SPI instance index. */ // 0 indicates cpha=0 and cpol=0
    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"
    
    
    /**
     * @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.");
    	//SEGGER_RTT_printf(0, "variable value: %s\n", strlen((const char *)m_rx_buf));
        if (m_rx_buf[0] != 0)
        {
            NRF_LOG_INFO(" Received:");
    			  SEGGER_RTT_printf(0, "Received:\n");
            NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
    			  SEGGER_RTT_printf(0," Transfer12 completed. Received: %s\n",(uint32_t)m_rx_buf);
        }
    }
    
    
    int main(void)
    {
    	  
        uint32_t i;
        uint32_t err_code;
        nrf_gpio_cfg_output(31);	
    	
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        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;
        APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
    	
     
    	  nrf_gpio_pin_clear(31);//cs
    	  nrf_delay_us(100);
    		
    //NRF_LOG_INFO("SPI example started.");
    																						//SEGGER_RTT_printf(0, "SPI example started\n");
      
    		adcinit();
    	
    				
    	
        while (1)
        {
    		
      
           ads1208ReadData();
    			
    			
         
    
        
        }
    }
    
    #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 "SEGGER_RTT.h"
    #include "ADS118.h"
    #include "boards.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  uint8_t m_tx_buf[4]={0x05,0x8b, 0x00,0x00};
    static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */
    static  uint8_t m_rx_buf[4];
    static  uint8_t m_rx_buf1[4];
    
    static  uint8_t m_tx_buf1[4]={0x00,0x00,0x52,0x7a};
    
    static const uint8_t m_length1 = sizeof(m_tx_buf1);  
    
    void adcinit()
    {
      nrf_gpio_cfg_output(31);
      nrf_gpio_cfg_output(29);
    	 
    	 nrf_delay_us(50);
     
    	
    	nrf_gpio_pin_clear(31);
    	nrf_gpio_pin_clear(29);
    
      nrf_delay_us(100);
    	nrf_drv_spi_transfer(&spi, m_tx_buf1, m_length1, m_rx_buf1, m_length1);
    	//nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length);
    	
    
    	nrf_gpio_pin_set(31); 
    
    }
    /****************************************************************************************************************
     * ADC data read function
    
       \param none.
    
     * return: ADC conversion result
     ****************************************************************************************************************/
    
    uint32_t ads1208ReadData()
    {
        uint8_t pui32DataTx[3] = {0}, pui32DataRx[4] = {0,0,0,0};
       
        nrf_gpio_pin_clear(29);
    	  nrf_gpio_pin_clear(31);
    
       
        nrf_drv_spi_transfer(&spi,  pui32DataTx, m_length1, pui32DataRx, m_length1);
    		
        int16_t ADCdatainbits = (pui32DataRx[0]|pui32DataRx[1]);
        nrf_gpio_pin_set(31);
        SEGGER_RTT_printf(0," Data Received1: %x\n",pui32DataRx[0]);
    		SEGGER_RTT_printf(0," Data Received2: %x\n",pui32DataRx[1]);
    		SEGGER_RTT_printf(0," Data Received3: %x\n",pui32DataRx[2]);
    		SEGGER_RTT_printf(0," Data Received4: %x\n",pui32DataRx[3]);
      	
      		
    
        
        return (ADCdatainbits);
    }
    
    i

    Initially when we have tried we were getting as zero as output when  we have changed the  NRFX_SPIM_MISO_PULL_CFG 1 (PULL DOWN)  to  NRFX_SPIM_MISO_PULL_CFG 3 (PULL UP) in software 

    we are reading as 00 and FF in the output . Can you please give me the suggestion where i am going wrong.

  • Hi 

    here are some points:

    1. No need to have pullup resistors on SPI i/o lines 

    2. The default SPI config - NRF_DRV_SPI_DEFAULT_CONFIG has mode set to NRF_DRV_SPI_MODE_0, you are not setting this to NRF_DRV_SPI_MODE_1. You should run the SPI with frequency like 1Mhz, the default NRF_DRV_SPI_FREQ_4M (4Mhz)

    3. When you assign a CS pin to SPI, this pin is controlled by the SPI instance, no need to add any code for that.

    4. The reference manual of ADS1118 suggests series resistor of 50ohm on each SPI l/o lines to provide short circuit protection. 

    5. Also the DRDY / Dout pin on nRF should be configured as falling edge triggered interrupt input.

    6. Since either config register or conversion register are 16bit type, you need to send 2 bytes , also the MSB goes first when writing / receiving the data.  

    There are two ways to config the device and read conversion values: 32bit mode or 16bit mode. 32bit is reading config register and followed by conversion register. If reading config register is not required, then use 16bit mode, which sends the config register set value (tx) and at the same time receive conversion value.

    For 32bit, you can send 4 bytes, tx_buf first two bytes represent config register values, and rx_buf will receive conversion data (2 bytes) followed by configReg value (2bytes). 

    First using 32bit mode: if configRegister = 0x058B (this is POR value), then since your buffers are 8bit 

    m_tx_buf[0] = configRegister >> 8; 

    m_tx_buf[1] = configRegister; 

    and then if you run the following SPI transfer commands, you should receive the same value in rx_buffer. If you read the same value, then your SPI is working fine. 

    nrf_drv_spi_transfer(&spi, m_tx_buf, 2, m_rx_buf, 4)

    the above will transmits 2 bytes which is the config register value and received data will be 4 bytes, this would be the conversion value followed by config reg value. The values in rx_buf[2] and rx_buf[3] should be same as tx_buf sent. 

    For 16bit mode which is just reading the conversion data after DRDY is low, you can just send current config reg value (2bytes) and receive conversion data (2bytes) at the same time 

    nrf_drv_spi_transfer(&spi, m_tx_buf, 2, m_rx_buf, 2)

    hope above helps. 

Reply
  • Hi 

    here are some points:

    1. No need to have pullup resistors on SPI i/o lines 

    2. The default SPI config - NRF_DRV_SPI_DEFAULT_CONFIG has mode set to NRF_DRV_SPI_MODE_0, you are not setting this to NRF_DRV_SPI_MODE_1. You should run the SPI with frequency like 1Mhz, the default NRF_DRV_SPI_FREQ_4M (4Mhz)

    3. When you assign a CS pin to SPI, this pin is controlled by the SPI instance, no need to add any code for that.

    4. The reference manual of ADS1118 suggests series resistor of 50ohm on each SPI l/o lines to provide short circuit protection. 

    5. Also the DRDY / Dout pin on nRF should be configured as falling edge triggered interrupt input.

    6. Since either config register or conversion register are 16bit type, you need to send 2 bytes , also the MSB goes first when writing / receiving the data.  

    There are two ways to config the device and read conversion values: 32bit mode or 16bit mode. 32bit is reading config register and followed by conversion register. If reading config register is not required, then use 16bit mode, which sends the config register set value (tx) and at the same time receive conversion value.

    For 32bit, you can send 4 bytes, tx_buf first two bytes represent config register values, and rx_buf will receive conversion data (2 bytes) followed by configReg value (2bytes). 

    First using 32bit mode: if configRegister = 0x058B (this is POR value), then since your buffers are 8bit 

    m_tx_buf[0] = configRegister >> 8; 

    m_tx_buf[1] = configRegister; 

    and then if you run the following SPI transfer commands, you should receive the same value in rx_buffer. If you read the same value, then your SPI is working fine. 

    nrf_drv_spi_transfer(&spi, m_tx_buf, 2, m_rx_buf, 4)

    the above will transmits 2 bytes which is the config register value and received data will be 4 bytes, this would be the conversion value followed by config reg value. The values in rx_buf[2] and rx_buf[3] should be same as tx_buf sent. 

    For 16bit mode which is just reading the conversion data after DRDY is low, you can just send current config reg value (2bytes) and receive conversion data (2bytes) at the same time 

    nrf_drv_spi_transfer(&spi, m_tx_buf, 2, m_rx_buf, 2)

    hope above helps. 

Children
No Data
Related