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

nRF52840-DK SPI communication with digital potentiometer

Hello,

I'm a beginner and I have lots of questions. So I wanna communication with MCP4110 chip. But I can't. I configured SS, MISO and CLK pin in sdk_config.h. (SEGGER Embedded Studio, Mac OS). So I wrote this code:

#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"

#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. */

static const nrf_drv_spi_t m_spi_master_0 = NRF_DRV_SPI_INSTANCE(0);

#define ContrReg "{0x21, 0x00}"     //constant
#define FreqRegL "{0x4D, 0xB8}"     //90C7
#define FreqRegM "{0x40, 0x1A}"     //8000
#define PhaseReg "{0xC0, 0x00}"     //constant
#define Exit_Reg "{0x11, 0x10}"     //constant
#define Potmeter "{0x11, 0x11}"     //0x1_ write data, 0x2_ shut down, 0x_0 no ch, 0x_1 0.ch; value
#define High 1

static uint8_t m_tx_buf0[]  = ContrReg;           // SINGEN_DATA
static uint8_t m_tx_buf1[]  = FreqRegL;           // SINGEN_DATA
static uint8_t m_tx_buf2[]  = FreqRegM;           // SINGEN_DATA
static uint8_t m_tx_buf3[]  = PhaseReg;           // SINGEN_DATA
static uint8_t m_tx_buf4[]  = Exit_Reg;           // SINGEN_DATA
static uint8_t m_tx_buf5[]  = Potmeter;           // POTMETER_DATA

static uint8_t m_rx_buf[sizeof(NULL) + 1];            /**< RX buffer. */

static const uint8_t m_length0 = sizeof(m_tx_buf5);        /**< Transfer length. */
//static const uint8_t m_length1 = sizeof(m_tx_buf1);        /**< Transfer length. */
//static const uint8_t m_length2 = sizeof(m_tx_buf2);        /**< Transfer length. */
//static const uint8_t m_length3 = sizeof(m_tx_buf3);        /**< Transfer length. */
//static const uint8_t m_length4 = sizeof(m_tx_buf4);        /**< Transfer length. */
//static const uint8_t m_length5 = sizeof(m_tx_buf5);        /**< Transfer length. */


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)
{
    nrf_gpio_pin_dir_set(SPI_SS_PIN, '1');
    bsp_board_init(BSP_INIT_LEDS);

    //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.sck_pin    = SPI_SCK_PIN;
    nrf_gpio_pin_dir_set(SPI_SS_PIN, NULL);
    spi_config.frequency  = NRF_SPIM_FREQ_125K;
    spi_config.mode       = NRF_DRV_SPI_MODE_0;
    spi_config.bit_order  = NRF_SPI_BIT_ORDER_LSB_FIRST;
    spi_config.ss_pin     = NRF_DRV_SPI_PIN_NOT_USED;
    spi_config.miso_pin   = NRF_DRV_SPI_PIN_NOT_USED;


    //APP_ERROR_CHECK(nrf_drv_spi_init(&m_spi_master_0, &spi_config, spi_event_handler, NULL));
        //APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));

    uint32_t err_code = nrf_drv_spi_init(&m_spi_master_0, &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_length0);
        spi_xfer_done = false;

        //APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf0, m_length0, NULL, NULL));
        /*
        err_code =  nrf_drv_spi_transfer(&m_spi_master_0, m_tx_buf0, sizeof(m_tx_buf0), m_rx_buf, sizeof(m_rx_buf));
        APP_ERROR_CHECK(err_code);
        nrf_delay_us(2);
        err_code =  nrf_drv_spi_transfer(&m_spi_master_0, m_tx_buf1, sizeof(m_tx_buf1), m_rx_buf, sizeof(m_rx_buf));
        APP_ERROR_CHECK(err_code);
        nrf_delay_us(2);
        err_code =  nrf_drv_spi_transfer(&m_spi_master_0, m_tx_buf2, sizeof(m_tx_buf2), m_rx_buf, sizeof(m_rx_buf));
        APP_ERROR_CHECK(err_code);
        nrf_delay_us(2);
        err_code =  nrf_drv_spi_transfer(&m_spi_master_0, m_tx_buf3, sizeof(m_tx_buf3), m_rx_buf, sizeof(m_rx_buf));
        APP_ERROR_CHECK(err_code);
        nrf_delay_us(2);
        err_code =  nrf_drv_spi_transfer(&m_spi_master_0, m_tx_buf4, sizeof(m_tx_buf4), m_rx_buf, sizeof(m_rx_buf));
        APP_ERROR_CHECK(err_code);
        nrf_delay_ms(2);*/
        
        err_code =  nrf_drv_spi_transfer(&m_spi_master_0, m_tx_buf5, sizeof(m_tx_buf5), m_rx_buf, sizeof(m_rx_buf));
        APP_ERROR_CHECK(err_code);

        //while(1){};
        
        while (!spi_xfer_done)
        {
           __WFE();
        }

        NRF_LOG_FLUSH();

        while(1){};
    } 
}

(0-4 buffers is sinus generator data, later I want to use 2 spi. First they should operate separately.)

My experience MISO pin always show 1.2V and CLK 0V. The CLK will be 0 if communication is ended? The digital potetiometer's wiper can't move. I check ohm from wiper to A pin, and B is 0V.

1) What do you think abaut my code? Where I made fault?

2) If you have a good spi code what is use 2 channel I'll be very happy:)

3) I want to use the potentiometer ({0x11, 0x00-FF}) get data from bluetooth.

4) Finally, If I have a good code in DK I want to write this code nRF52840 dongle.

Thanks your answers.

Regards,

Beni

Parents
  • Haven't used MCP4110 myself so I cannot answer anything specific to that sensor.

            while (!spi_xfer_done)
            {
               __WFE();
            }

    Waiting for a flag and using only __WFE could cause problems. To understand, read this thread. I see that the SPI example in the SDK is written this way, but I think it could be changed.

            while(1){};

    so you want your app to be low power for certain time and then busy loops indefinitely (not low power anymore). I am sure this is not what you want to do!!!??

    You are starting multiple SPI transfers without waiting for the previous to complete? is that what you intended?

Reply
  • Haven't used MCP4110 myself so I cannot answer anything specific to that sensor.

            while (!spi_xfer_done)
            {
               __WFE();
            }

    Waiting for a flag and using only __WFE could cause problems. To understand, read this thread. I see that the SPI example in the SDK is written this way, but I think it could be changed.

            while(1){};

    so you want your app to be low power for certain time and then busy loops indefinitely (not low power anymore). I am sure this is not what you want to do!!!??

    You are starting multiple SPI transfers without waiting for the previous to complete? is that what you intended?

Children
  • If I clear this __WFE line, the code still doesn't work. I think the problem will be in the slave. Please check MCP datasheet page 18. Data line and transfer are good, I don't know where is the problem. 

    I used while(1){}; line, because I want use just once SPI transfer. Later here will be sleep mode. 

    "You are starting multiple SPI transfers without waiting for the previous to complete? is that what you intended?"

    No, just I want use two slave. Sinus generator (slave 1), who get 90-104 line's data, and digital potentiometer (slave 2), who get 106,107 line's data. Singen data lines are ok, work well, but digpot no. I just looked at them separately.

Related