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

NRFX SPIM write and read

Hi team,

I want to make simple communication between NRF52840 dongle and mcp2517 CAN FD contoller using SPI. I do not understand, how to send and read values to and from registers. Same SPI communication works well between dongles.

I set the register value

// Defined register values for MCP
#define cINSTRUCTION_WRITE	     0x02

Set the SPI instance index and flag 

/**< SPI instance index. */
static const nrfx_spim_t spi = NRFX_SPIM_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */

/**< Flag used to indicate that SPI instance completed the transfer. */
static volatile bool spi_xfer_done; 

Created two buffers for transfer and receive and set transfer length

static uint8_t          m_tx_buf[5];
//static uint8_t        cINSTRUCTION_WRITE_m_rx_buf[5];  /**< RX buffer. */
static uint8_t          m_rx_buf[5];  /**< RX buffer. */
static const uint8_t    m_length = sizeof(m_tx_buf);        /**< Transfer length. */

SPIM event handler function 

void spim_event_handler(nrfx_spim_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));
    }
    */
}

In the main function I set function for starting the SPI data transfer with DCX control with SPI config

 nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_tx_buf, m_length, m_rx_buf, m_length);

nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
    spi_config.frequency      = NRF_SPIM_FREQ_1M;
    spi_config.ss_pin         = NRFX_SPIM_SS_PIN;
    spi_config.miso_pin       = NRFX_SPIM_MISO_PIN;
    spi_config.mosi_pin       = NRFX_SPIM_MOSI_PIN;
    spi_config.sck_pin        = NRFX_SPIM_SCK_PIN;
    spi_config.dcx_pin        = NRFX_SPIM_DCX_PIN;
    spi_config.use_hw_ss      = true;
    spi_config.ss_active_high = false;
    APP_ERROR_CHECK(nrfx_spim_init(&spi, &spi_config, spim_event_handler, NULL));

And in the while loop I should start writing and reading registers.  Here I start to face with the problems. How I can  prepare tx_buf with values and how to start send values and read it from register? 

Sorry about huge misunderstanding, but I need to make things clear. 

Parents
  • Hi,

    I'm not sure I understand your questions. You can assign values to tx_buf as normal, for instance like this:

    m_tx_buf[0] = 0x01;
    m_tx_buf[1] = 0x02;
    m_tx_buf[2] = 0x03;
    m_tx_buf[3] = 0x04;
    m_tx_buf[4] = 0x05;

    In your code, you have already created a transfer description struck, xfer_desc, which points to the TX/RX buffers and their length. You can pass this to the function nrfx_spim_xfer/nrfx_spim_xfer_dcx to start the transfer. 

    Best regards,
    Jørgen

  • Thank you for your answer, Jorgen.

    I looked more closely to Nrfx spim and spi demo programs on the SDK, and I tried to switch to SPIM master example and I'm trying to create SPI communication on it. When I try to read register, I got the same value every time. Is the first byte transferred is the register address ? Or I'm wrong? How to add some value to send and how to read that value? According to MCP2517 API, for test purposes I need to write some data to CiFLTOBJ register (address - 0x1F0) and after that I need to read the same register.

    My current code (with USB CDC):

    
    #include "C:\Users\user1\Desktop\main.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. */
    
    
    /* Buffer for MCP2517 config */
    //cREGADDR_CiFLTOBJ 
    static uint8_t          m_config_buf1[] = {((uint8_t)0x1F0)}; 
    
    
    /* send value buf */
    static uint8_t          m_tx_rx_buf1[] = {0x2};
    
    
    /* Rx buffer */
    static uint8_t          m_rx_buf1[sizeof(m_tx_rx_buf1) + 1];    
    
    
    /*Rx buf length*/
    static const uint8_t    m_length_rx = sizeof(m_tx_rx_buf1);       
    
    
    
    
    
    void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                           void *                    p_context)
    {
        spi_xfer_done = true;
    }
    
    
    
    
    static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                        app_usbd_cdc_acm_user_event_t event);
    
    
    
    /**
     * @brief CDC_ACM class instance
     * */
    APP_USBD_CDC_ACM_GLOBAL_DEF(m_app_cdc_acm,
                                cdc_acm_user_ev_handler,
                                CDC_ACM_COMM_INTERFACE,
                                CDC_ACM_DATA_INTERFACE,
                                CDC_ACM_COMM_EPIN,
                                CDC_ACM_DATA_EPIN,
                                CDC_ACM_DATA_EPOUT,
                                APP_USBD_CDC_COMM_PROTOCOL_AT_V250
    );
    
    #define READ_SIZE 1
    
    static char m_rx_buffer[READ_SIZE];
    static char m_tx_buffer[NRF_DRV_USBD_EPSIZE];
    static char m_tx_buffer1[NRF_DRV_USBD_EPSIZE];
    static bool m_send_flag = 0;
    
    
    static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                        app_usbd_cdc_acm_user_event_t event)
    {
        app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst);
    
        switch (event)
        {
            case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:
            {
                bsp_board_led_on(LED_CDC_ACM_OPEN);
    
                /*Setup first transfer*/
                ret_code_t ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                                       m_rx_buffer,
                                                       READ_SIZE);
                UNUSED_VARIABLE(ret);
                break;
            }
            case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE:
                bsp_board_led_off(LED_CDC_ACM_OPEN);
                break;
            case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:
                bsp_board_led_invert(LED_CDC_ACM_TX);
                break;
            case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
            {
                ret_code_t ret;
    //            NRF_LOG_INFO("Bytes waiting: %d", app_usbd_cdc_acm_bytes_stored(p_cdc_acm));
                app_usbd_cdc_acm_bytes_stored(p_cdc_acm);
                do
                {
                    /*Get amount of data transfered*/
                    size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
    //                NRF_LOG_INFO("RX: size: %lu char: %c", size, m_rx_buffer[0]);
    
                    /* Fetch data until internal buffer is empty */
                    ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                                m_rx_buffer,
                                                READ_SIZE);
                } while (ret == NRF_SUCCESS);
    
                memcpy(m_tx_buffer,m_rx_buffer,READ_SIZE);
                app_usbd_cdc_acm_write(&m_app_cdc_acm, m_tx_buffer, READ_SIZE); //
    
                bsp_board_led_invert(LED_CDC_ACM_RX);
                break;
            }
            default:
                break;
        }
    }
    
    static void usbd_user_ev_handler(app_usbd_event_type_t event)
    {
        switch (event)
        {
            case APP_USBD_EVT_DRV_SUSPEND:
                bsp_board_led_off(LED_USB_RESUME);
                break;
            case APP_USBD_EVT_DRV_RESUME:
                bsp_board_led_on(LED_USB_RESUME);
                break;
            case APP_USBD_EVT_STARTED:
                break;
            case APP_USBD_EVT_STOPPED:
                app_usbd_disable();
                bsp_board_leds_off();
                break;
            case APP_USBD_EVT_POWER_DETECTED:
    //            NRF_LOG_INFO("USB power detected");
    
                if (!nrf_drv_usbd_is_enabled())
                {
                    app_usbd_enable();
                }
                break;
            case APP_USBD_EVT_POWER_REMOVED:
    //            NRF_LOG_INFO("USB power removed");
                app_usbd_stop();
                break;
            case APP_USBD_EVT_POWER_READY:
    //            NRF_LOG_INFO("USB ready");
                app_usbd_start();
                break;
            default:
                break;
        }
    }
    /// end for USB CDC
    
    
    int main(void)
    {
    
    
    ret_code_t ret;
      static const app_usbd_config_t usbd_config = {
          .ev_state_proc = usbd_user_ev_handler
      };
    
        bsp_board_init(BSP_INIT_LEDS);
        ///start clock set mandatory for USB CDC
        nrf_drv_clock_init(); // for HF 32MHz external X-tal
        nrf_drv_clock_lfclk_request(NULL); // for LF 32.768kHz external X-tal
        while(!nrf_drv_clock_lfclk_is_running()) {
          // Just waiting 
     }
        /// end clock set
        app_usbd_serial_num_generate();
        ret = app_usbd_init(&usbd_config);
        APP_ERROR_CHECK(ret);
    
    
        app_usbd_class_inst_t const * class_cdc_acm = app_usbd_cdc_acm_class_inst_get(&m_app_cdc_acm);
        ret = app_usbd_class_append(class_cdc_acm);
        APP_ERROR_CHECK(ret);
    
      if (USBD_POWER_DETECTION) {
          ret = app_usbd_power_events_enable();
          APP_ERROR_CHECK(ret);
      }
      else {
          app_usbd_enable();
          app_usbd_start();
      }
    
    
    
        nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
        //spi_config.ss_pin   = SPI_SS_PIN;
        spi_config.ss_pin   = NRF_DRV_SPI_PIN_NOT_USED;
        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));
    
    
        // Now enable a pin to work as the chip select
        nrf_gpio_cfg_output(SPI_SS_PIN);
        nrf_gpio_pin_set(SPI_SS_PIN);
    
    
        // Specify blocking operation
        APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
    
    
    
        while (1)
        {
    
        uint16_t address;
        uint16_t random_reiksme = rand();
        char tx[20];
        char rx[3];
        
        static int  frame_counter;               // USB CDC buferis
        static int  frame_counter1;              // USB CDC buferis
    
    
      // Reset rx buffer and transfer done flag
            memset(m_rx_buf1, 0, m_length_rx);
    
            spi_xfer_done = false;
    
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_config_buf1, sizeof(m_config_buf1), NULL, NULL));
            nrf_delay_ms(20);
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_rx_buf1, m_length_rx, m_rx_buf1, m_length_rx));
    
        while (spi_xfer_done)
          {
             app_usbd_event_queue_process();
             bsp_board_led_invert(BSP_BOARD_LED_3);
    
        sprintf(tx,"%d",m_rx_buf1);
    
        size_t size = sprintf(m_tx_buffer,tx,frame_counter);
        size_t size1 = sprintf(m_tx_buffer,"\n\r",frame_counter1);
        ret = app_usbd_cdc_acm_write(&m_app_cdc_acm, m_tx_buffer, size);
    
        bsp_board_led_invert(BSP_BOARD_LED_0);
        nrf_delay_ms(100);
    
    
            nrf_gpio_pin_clear(SPI_SS_PIN);
            }
        }
    }
    

Reply
  • Thank you for your answer, Jorgen.

    I looked more closely to Nrfx spim and spi demo programs on the SDK, and I tried to switch to SPIM master example and I'm trying to create SPI communication on it. When I try to read register, I got the same value every time. Is the first byte transferred is the register address ? Or I'm wrong? How to add some value to send and how to read that value? According to MCP2517 API, for test purposes I need to write some data to CiFLTOBJ register (address - 0x1F0) and after that I need to read the same register.

    My current code (with USB CDC):

    
    #include "C:\Users\user1\Desktop\main.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. */
    
    
    /* Buffer for MCP2517 config */
    //cREGADDR_CiFLTOBJ 
    static uint8_t          m_config_buf1[] = {((uint8_t)0x1F0)}; 
    
    
    /* send value buf */
    static uint8_t          m_tx_rx_buf1[] = {0x2};
    
    
    /* Rx buffer */
    static uint8_t          m_rx_buf1[sizeof(m_tx_rx_buf1) + 1];    
    
    
    /*Rx buf length*/
    static const uint8_t    m_length_rx = sizeof(m_tx_rx_buf1);       
    
    
    
    
    
    void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                           void *                    p_context)
    {
        spi_xfer_done = true;
    }
    
    
    
    
    static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                        app_usbd_cdc_acm_user_event_t event);
    
    
    
    /**
     * @brief CDC_ACM class instance
     * */
    APP_USBD_CDC_ACM_GLOBAL_DEF(m_app_cdc_acm,
                                cdc_acm_user_ev_handler,
                                CDC_ACM_COMM_INTERFACE,
                                CDC_ACM_DATA_INTERFACE,
                                CDC_ACM_COMM_EPIN,
                                CDC_ACM_DATA_EPIN,
                                CDC_ACM_DATA_EPOUT,
                                APP_USBD_CDC_COMM_PROTOCOL_AT_V250
    );
    
    #define READ_SIZE 1
    
    static char m_rx_buffer[READ_SIZE];
    static char m_tx_buffer[NRF_DRV_USBD_EPSIZE];
    static char m_tx_buffer1[NRF_DRV_USBD_EPSIZE];
    static bool m_send_flag = 0;
    
    
    static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                        app_usbd_cdc_acm_user_event_t event)
    {
        app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst);
    
        switch (event)
        {
            case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:
            {
                bsp_board_led_on(LED_CDC_ACM_OPEN);
    
                /*Setup first transfer*/
                ret_code_t ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                                       m_rx_buffer,
                                                       READ_SIZE);
                UNUSED_VARIABLE(ret);
                break;
            }
            case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE:
                bsp_board_led_off(LED_CDC_ACM_OPEN);
                break;
            case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:
                bsp_board_led_invert(LED_CDC_ACM_TX);
                break;
            case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
            {
                ret_code_t ret;
    //            NRF_LOG_INFO("Bytes waiting: %d", app_usbd_cdc_acm_bytes_stored(p_cdc_acm));
                app_usbd_cdc_acm_bytes_stored(p_cdc_acm);
                do
                {
                    /*Get amount of data transfered*/
                    size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
    //                NRF_LOG_INFO("RX: size: %lu char: %c", size, m_rx_buffer[0]);
    
                    /* Fetch data until internal buffer is empty */
                    ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                                m_rx_buffer,
                                                READ_SIZE);
                } while (ret == NRF_SUCCESS);
    
                memcpy(m_tx_buffer,m_rx_buffer,READ_SIZE);
                app_usbd_cdc_acm_write(&m_app_cdc_acm, m_tx_buffer, READ_SIZE); //
    
                bsp_board_led_invert(LED_CDC_ACM_RX);
                break;
            }
            default:
                break;
        }
    }
    
    static void usbd_user_ev_handler(app_usbd_event_type_t event)
    {
        switch (event)
        {
            case APP_USBD_EVT_DRV_SUSPEND:
                bsp_board_led_off(LED_USB_RESUME);
                break;
            case APP_USBD_EVT_DRV_RESUME:
                bsp_board_led_on(LED_USB_RESUME);
                break;
            case APP_USBD_EVT_STARTED:
                break;
            case APP_USBD_EVT_STOPPED:
                app_usbd_disable();
                bsp_board_leds_off();
                break;
            case APP_USBD_EVT_POWER_DETECTED:
    //            NRF_LOG_INFO("USB power detected");
    
                if (!nrf_drv_usbd_is_enabled())
                {
                    app_usbd_enable();
                }
                break;
            case APP_USBD_EVT_POWER_REMOVED:
    //            NRF_LOG_INFO("USB power removed");
                app_usbd_stop();
                break;
            case APP_USBD_EVT_POWER_READY:
    //            NRF_LOG_INFO("USB ready");
                app_usbd_start();
                break;
            default:
                break;
        }
    }
    /// end for USB CDC
    
    
    int main(void)
    {
    
    
    ret_code_t ret;
      static const app_usbd_config_t usbd_config = {
          .ev_state_proc = usbd_user_ev_handler
      };
    
        bsp_board_init(BSP_INIT_LEDS);
        ///start clock set mandatory for USB CDC
        nrf_drv_clock_init(); // for HF 32MHz external X-tal
        nrf_drv_clock_lfclk_request(NULL); // for LF 32.768kHz external X-tal
        while(!nrf_drv_clock_lfclk_is_running()) {
          // Just waiting 
     }
        /// end clock set
        app_usbd_serial_num_generate();
        ret = app_usbd_init(&usbd_config);
        APP_ERROR_CHECK(ret);
    
    
        app_usbd_class_inst_t const * class_cdc_acm = app_usbd_cdc_acm_class_inst_get(&m_app_cdc_acm);
        ret = app_usbd_class_append(class_cdc_acm);
        APP_ERROR_CHECK(ret);
    
      if (USBD_POWER_DETECTION) {
          ret = app_usbd_power_events_enable();
          APP_ERROR_CHECK(ret);
      }
      else {
          app_usbd_enable();
          app_usbd_start();
      }
    
    
    
        nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
        //spi_config.ss_pin   = SPI_SS_PIN;
        spi_config.ss_pin   = NRF_DRV_SPI_PIN_NOT_USED;
        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));
    
    
        // Now enable a pin to work as the chip select
        nrf_gpio_cfg_output(SPI_SS_PIN);
        nrf_gpio_pin_set(SPI_SS_PIN);
    
    
        // Specify blocking operation
        APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
    
    
    
        while (1)
        {
    
        uint16_t address;
        uint16_t random_reiksme = rand();
        char tx[20];
        char rx[3];
        
        static int  frame_counter;               // USB CDC buferis
        static int  frame_counter1;              // USB CDC buferis
    
    
      // Reset rx buffer and transfer done flag
            memset(m_rx_buf1, 0, m_length_rx);
    
            spi_xfer_done = false;
    
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_config_buf1, sizeof(m_config_buf1), NULL, NULL));
            nrf_delay_ms(20);
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_rx_buf1, m_length_rx, m_rx_buf1, m_length_rx));
    
        while (spi_xfer_done)
          {
             app_usbd_event_queue_process();
             bsp_board_led_invert(BSP_BOARD_LED_3);
    
        sprintf(tx,"%d",m_rx_buf1);
    
        size_t size = sprintf(m_tx_buffer,tx,frame_counter);
        size_t size1 = sprintf(m_tx_buffer,"\n\r",frame_counter1);
        ret = app_usbd_cdc_acm_write(&m_app_cdc_acm, m_tx_buffer, size);
    
        bsp_board_led_invert(BSP_BOARD_LED_0);
        nrf_delay_ms(100);
    
    
            nrf_gpio_pin_clear(SPI_SS_PIN);
            }
        }
    }
    

Children
No Data
Related