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

how to drive spi CS line low for 32 bits.

Hi,

Can you please direct me to the document that explains about generating more than 8 bits of clock in SPI and keeping CS line low for that entire period.

Also, if i have to send two 16bit data, would i have to send them in lots of 8bit ? or i can send them as 16bits using nrf_drv_spi_transfer API?

I am modifying the SPI example found under SDK15/example/peripheral/spi.

And i have to achieve the sequence attached in the image. 

Thank you  

Parents Reply Children
  • I realized that first i should understand the SPI examples provided in the SDK thoroughly before customizing them.

    I am using nrf52832 DK as Master and flashing SPI example to it which is supposed to send a string " NORDIC " and then i am flashing SPIS example to my nrf52840 DK which should act as the slave then.  Now, though the transactions are getting completed in both the kits and LED's get toggled but i am not receiving the string "NORDIC" from my slave . What do i have to modify in the slave example to receive the string ?

    #include "sdk_config.h"
    #include "nrf_drv_spis.h"
    #include "nrf_gpio.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 SPIS_INSTANCE 1 /**< SPIS instance index. */
    static const nrf_drv_spis_t spis = NRF_DRV_SPIS_INSTANCE(SPIS_INSTANCE);/**< SPIS instance. */
    
    #define TEST_STRING "Nordic"
    static uint8_t       m_tx_buf[] = TEST_STRING;           /**< TX buffer. */
    static uint8_t       m_rx_buf[sizeof(TEST_STRING) + 1];    /**< RX buffer. */
    static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */
    
    static volatile bool spis_xfer_done; /**< Flag used to indicate that SPIS instance completed the transfer. */
    
    /**
     * @brief SPIS user event handler.
     *
     * @param event
     */
    void spis_event_handler(nrf_drv_spis_event_t event)
    {
        if (event.evt_type == NRF_DRV_SPIS_XFER_DONE)
        {
            spis_xfer_done = true;
            NRF_LOG_INFO(" Transfer completed. Received: %s",(uint32_t)m_rx_buf);
            printf("recieved : %s", m_rx_buf );
        }
    }
    
    int main(void)
    {
        // Enable the constant latency sub power mode to minimize the time it takes
        // for the SPIS peripheral to become active after the CSN line is asserted
        // (when the CPU is in sleep mode).
        NRF_POWER->TASKS_CONSTLAT = 1;
    
        bsp_board_init(BSP_INIT_LEDS);
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        NRF_LOG_INFO("SPIS example");
    
        nrf_drv_spis_config_t spis_config = NRF_DRV_SPIS_DEFAULT_CONFIG;
        spis_config.csn_pin               = APP_SPIS_CS_PIN;
        spis_config.miso_pin              = APP_SPIS_MISO_PIN;
        spis_config.mosi_pin              = APP_SPIS_MOSI_PIN;
        spis_config.sck_pin               = APP_SPIS_SCK_PIN;
    
        APP_ERROR_CHECK(nrf_drv_spis_init(&spis, &spis_config, spis_event_handler));
    
        while (1)
        {
            memset(m_rx_buf, 0, m_length);
            spis_xfer_done = false;
    
            APP_ERROR_CHECK(nrf_drv_spis_buffers_set(&spis, m_tx_buf, m_length, m_rx_buf, m_length));
    
            while (!spis_xfer_done)
            {
                __WFE();
            }
    
            NRF_LOG_FLUSH();
    
            bsp_board_led_invert(BSP_BOARD_LED_0);
        }
    }
    

  • Also, in the code attached, if my m_length = 4. Will an SPI transaction end after every 8bit transfer and CS line will go high again or will the transaction end after all the 4 bytes are sent ???? 

     while (1)
        {
            // Reset rx buffer and transfer done flag
            memset(m_rx_buf, 0, m_length);
            spi_xfer_done = false;
    
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, &start_write, m_length, m_rx_buf, m_length));
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, &config_addr, m_length, m_rx_buf, m_length));
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, &config_lowvalue, m_length, m_rx_buf, m_length));
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, &config_highvalue, 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(200)

  • Hi.

    The SPI Master and SPI Slave example in the SDK can be used without any modification and demonstrates sending the string "Nordic" in both directions. The only thing you do is to flash both boards with the example and hook them up as specified in the SPI Slave Example documentation.

    The length parameters defines the length of a transaction, yes. So if you set 4 for both Rx and Tx the transaction will be 4 bytes.

  • Thanks Einar, I did not realize it will be so difficult to understand an SPI implementation. Can you help me with this very specific short example : I want to write 0X0030 and then 0X5678 to slave.  In the attached code snippet, i am experiencing a very weird behavior. I have set m_length and rx_buffer to 2 as i am making a 16bit transaction. And i am receiving 0X0030 multiple times before i receive 0X5678. I will appreciate a lot if you could help me with this example .

    Thanks

    #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 "ashu"
    static uint16_t       m_tx_buf = 0b0011000000000000;           /**< TX buffer. */
    static uint16_t       m_tx_buf1 =0b0111100001010110;           /**< TX buffer. */
    static uint16_t       m_rx_buf[2];    /**< RX buffer. */
    static const uint8_t m_length = 2;        /**< 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_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.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;
    
            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();
    
             nrf_gpio_pin_set(BSP_BOARD_LED_0);
            nrf_delay_ms(200);
          
    
    
    
              memset(m_rx_buf, 0, m_length);
            spi_xfer_done = false;
    
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, &m_tx_buf1, m_length, m_rx_buf, m_length));
    
            while (!spi_xfer_done)
            {
                __WFE();
            }
    
            NRF_LOG_FLUSH();
    
            bsp_board_led_invert(BSP_BOARD_LED_1);
            nrf_delay_ms(200);
       
        }
    }
    

  • Hi,

    I do not see anything in your code that should explain repeating the first transaction. The only thing is that you do not explicitly wait for the one transaction to finish before you start another one, but the 200 ms delay should take care of it. If this was a problem (which I do not think) and you have not defined DEBUG for your project, then the NRF_ERROR_BUSY returned from nrf_drv_spi_transfer() would trigger a system reset, which in turn would lead to sending the initial data repeatedly.

    • Have you verified that the device is not resetting when you see this?
    • Do you use a project where DEBUG is defined (just select Debug in the Build Configuration dropdown if you are using SES)?
    • Can you upload a logic analyzer trace so that we can see what is happening on the SPI lines?
Related