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  

  • 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?
  • Thanks, Einar,

    Surprisingly, it worked after removing the explicit wait. But my peripheral is not responding to any command. I am supposed to send a write command like in this attached sequence .  

    I am sending a 32 bit tx_buffer with m_length = 1 . Do you

    static uint32_t       m_tx_buf = 0b00000000001100000101011001111000;           /**< TX buffer. */
    
    
    
    static uint32_t       m_rx_buf[1];    /**< RX buffer. */
    static const uint8_t m_length = 4;        /**< 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;
        spi_config.mode = NRF_DRV_SPI_MODE_2;
        APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
    
        NRF_LOG_INFO("SPI example started.");
    
            // send 30H
            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));
            NRF_LOG_FLUSH();
            nrf_delay_ms(200);
     
    }
    
    find any issue in my code snippet before I talk to the IC manufacturer ?

  • Hi,

    I do not see any problems with this code. I think we need two things in order to understand more:

    • Datasheet of the SPI slave (what is it?) so that we can check if you have set the correct SPI mode.
    • Logic analyzer trace of the SPI lines so that we can see what is actually going on.
  • Hi Einar,

    Thanks for helping me with this. PFA the datasheet and an image where you can read about the modes. I assume, it says the data will be shifted on SDI using SPI mode 2 and on SDO using SPI mode 3. isn't that right? So once I write the data on SDI line, would i have to uninitialize the SPI first to configure it to mode 3 or can i directly change the mode ? 

    Also, find attached the trace of SCK and MOSI SPI lines.

    Can you figure out whats going wrong?

    Appreciate it!!

    Atmel-46004-SE-M90E36A-Datasheet.pdf

Related