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

Using the SPI example to communicate with a CR95HF

Good evening all, I'm trying to get my DK52 communicating with a CR95HF (this is a NFC controller with serial and SPI control interfaces), I'm using a breakout board - BM019
The CR95 requires a setup sequence to select the SPI interface image description

So far I'm using the SPI example from SDK 14, I have modified it to toggle the IRQ_IN pin I'm using pin30) on initialization, I then attempt to send 0x55 to the CR95 (this is a Echo command - I'm expecting 0x55 back). However I seem to get back 0x06 (the first two loops) then nothing for any additional requests)

I have tried removing my initialization toggle, when I do this I don't get anything back on any of the loops)

Here's my modified code.

#define SPI_INSTANCE  0
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  
static volatile bool spi_xfer_done; 

//#define TEST_STRING "Nordic"
//static uint8_t       m_tx_buf[] = TEST_STRING;      
static uint8_t       m_rx_buf[2];  //sizeof(TEST_STRING) + 1];   
static const uint8_t m_length = 1; //sizeof(m_tx_buf);        

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));
    }
}

uint8_t hexdata = 0x55;

int main(void)
{
    bsp_board_leds_init();

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();
    nrf_gpio_cfg_output(30);
    nrf_gpio_cfg_output(29);
    nrf_gpio_pin_set(30);
    nrf_delay_ms(3000);
    NRF_LOG_INFO("SPI example.");

    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;
    
   nrf_gpio_pin_clear(30);
    nrf_delay_us(100) ;        // BM019 into SPI
    nrf_gpio_pin_set(30);
    nrf_delay_ms(10) ;
    APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
    nrf_delay_ms(1000);
    
    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, &hexdata, 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(1000);
    }
}

and my output.

<info> app: SPI example.
<info> app: Transfer completed.
<info> app:  Received:
<info> app:  06                     |.       
<info> app: Transfer completed.
<info> app:  Received:
<info> app:  06                     |.       
<info> app: Transfer completed.
<info> app: Transfer completed.
<info> app: Transfer completed.
<info> app: Transfer completed.

I have tried so many thing I'm starting to lose my mind on what I've done! (2 days now!!!) I think i'm initializing it but not 100% sure. I get that this might be a bit out of scope on the Nordic site but I'm thinking this is more a SDK issue!

  • Hi,

    Please have a look at the timing diagrams of the SPI/SPIM peripheral of the nRF52832. When you start a transfer, both TX and RX buffer will be filled on every clocking of the SPI bus. In your code, you have set the length of RX buffer to 1, meaning this buffer will be filled while you transfer the control code to the peripheral (CR95). From the datasheet of CR95, you can see that the response will be sent after the control byte is received. You need to increase the RX buffer to the size of the expected TX+RX bytes, in your test case 2, and ignore the first received byte:

    static const uint8_t m_rx_length = m_length + 1;
    static uint8_t       m_rx_buf[m_rx_length];
    ...
    void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                           void *                    p_context)
    {
        ...
        if (m_rx_buf[1] != 0)
        ...
    }
    
    ...
    int main(void)
    {
        ...
        while (1)
        {
            ...
            memset(m_rx_buf, 0, m_rx_length);
            ...
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, &hexdata, m_length, m_rx_buf, m_rx_length));
            ...
        }
    }
    

    Best regards,

    Jørgen

  • Hi Jørgen, Thanks for your answer. I have tried many buffer sizes - I realise the code I quoted ad the wrong value. As you suggest I changed the values - I added this to my declarations:

    static const uint8_t m_rx_length = 2;
    

    I changed my spi transfer call to this:

    APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, &hexdata, m_length, m_rx_buf, m_rx_length));
    

    So my rx buffer size (and m_rx_length) are '2'. This is my output:

    <info> app: SPI example.
    <info> app: Transfer completed.
    <info> app:  Received:
    <info> app:  06 06 01               |...     
    <info> app: Transfer completed.
    <info> app: Transfer completed.
    <info> app: Transfer completed.
    <info> app: Transfer completed.
    

    As you can see.. another 06! and nothing (or 0x00) on subsequent calls... confusion reigns :(

  • Have you tried removing the checking of the first byte in the callback handler (if (m_rx_buf[0] != 0))? You are checking the first byte, but this might actually be 0, as this will depend on what the peripheral clocks out. You seems to be getting multiple transfers where the buffer does not contain 06 in the first byte, but you are not printing the proceding bytes with your code.

  • Yup... had tried before.. I added this tho the event handler (above the if statement)

    NRF_LOG_INFO("Not checked>");
    NRF_LOG_HEXDUMP_INFO(m_rx_buf, strlen((const char *)m_rx_buf));
    

    My output now looks like this:

    <info> app: SPI example.
    <info> app: Transfer completed.
    <info> app: Not checked>
    <info> app:  06 06 01               |...     
    <info> app:  Received:
    <info> app:  06 06 01               |...     
    <info> app: Transfer completed.
    <info> app: Not checked>
    <info> app:                         |        
    <info> app: Transfer completed.
    <info> app: Not checked>
    <info> app:                         |        
    <info> app: Transfer completed.
    
  • Could you test with this spi_event_handler?

    void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                           void *                    p_context)
    {
        spi_xfer_done = true;
        NRF_LOG_INFO("Transfer completed.");
        NRF_LOG_INFO(" Received:");
        NRF_LOG_HEXDUMP_INFO(p_event->data.done.p_rx_buffer, p_event->data.done.rx_length);
    }
    
Related