SPI write and read Multiple bytes.

Hi All,

         I am using nrf52840 in my project and working on sdk 17.0.2. I have an SPI based IC MAX3421E connected to my device. I am able to read and write single bytes through SPI code. But I am having issues with reading and writing multiple bytes. I am not getting proper response when I try to read or write multiple bytes. The sample code from the library and the converted ones are attached below:-

Sample code from MAX3421 library:-

//SAMPLE CODE FROM MAX3421 LIBRARY


BYTE SPI_wr( BYTE data )
{
    SSPBUF = data;              // write byte to SSP2BUF register
    while( !SSPSTATbits.BF );   // wait until bus cycle completes
    return ( SSPBUF );          //
}

/* Single host register write   */
void MAXreg_wr(BYTE reg, BYTE val)
{
    Select_MAX3421E;
    SPI_wr ( reg + 2 ); //set WR bit and send register number
    SPI_wr ( val );
    Deselect_MAX3421E;
}


/* multiple-byte write */
/* returns a pointer to a memory position after last written */
char* MAXbytes_wr( BYTE reg, BYTE nbytes, char* data )
{
    Select_MAX3421E;    //assert SS
    SPI_wr ( reg + 2 ); //set W/R bit and select register   
    while( nbytes ) {                
        SPI_wr( *data );    // send the next data byte
        data++;             // advance the pointer
        nbytes--;
    }
    Deselect_MAX3421E;  //deassert SS
    return( data );
}



/* Single host register read        */
BYTE MAXreg_rd( BYTE reg )    
{
 BYTE tmp;
    Select_MAX3421E;
    SPI_wr ( reg );         //send register number
    tmp = SPI_wr ( 0x00 );  //send empty byte, read register contents
    Deselect_MAX3421E; 
    return (tmp);
}



/* multiple-bytes register read                             */
/* returns a pointer to a memory position after last read   */
char* MAXbytes_rd ( BYTE reg, BYTE nbytes, char* data )
{
    Select_MAX3421E;    //assert SS
    SPI_wr ( reg );     //send register number
    while( nbytes ) {
        *data = SPI_wr ( 0x00 );    //send empty byte, read register contents
        data++;
        nbytes--;
    }
    Deselect_MAX3421E;  //deassert SS
    return( data );   
}

The above code has been converted to NRF library format.

void max3421eRegWr(uint8_t reg, uint8_t data)
{
    SPIWriteLength = 2; 
    SPIReadLength = 0; 
    
    spi_tx_buf[0] = reg + 0x02 ; 
    spi_tx_buf[1] = data; 
	
    spi_xfer_done = false;
    nrf_gpio_pin_clear(SPI_SS_PIN);
	
    nrf_drv_spi_transfer(&m_spi, spi_tx_buf, SPIWriteLength, spi_rx_buf, SPIReadLength);
    while(spi_xfer_done == false){}; // this flag will be set to true in the spi interrupt handler function
	
    nrf_gpio_pin_set(SPI_SS_PIN);
    vTaskDelay(1000);
}			 


uint8_t max3421eRegRd(uint8_t reg)
{
    spi_tx_buf[0] = reg;
    spi_tx_buf[1] = 0x00;
        
    spi_xfer_done = false;

    nrf_gpio_pin_clear(SPI_SS_PIN);

    nrf_drv_spi_transfer(&m_spi, spi_tx_buf, 2, spi_rx_buf, 2);
    while(spi_xfer_done == false){};

    nrf_gpio_pin_set(SPI_SS_PIN);

    return spi_rx_buf[1];
}

char* MAXbytes_rd ( uint8_t reg, uint8_t nbytes, char* data )
{
    spi_tx_buf[0] = reg;

    nrf_gpio_pin_clear(SPI_SS_PIN);

    nrf_drv_spi_transfer(&m_spi, spi_tx_buf, 1, spi_rx_buf, 0);

    spi_tx_buf[0] = 0x00;

    while( nbytes ) {
    *data = nrf_drv_spi_transfer(&m_spi, spi_tx_buf, 1, spi_rx_buf, 0);
        data++;
        nbytes--;
    }
        nrf_gpio_pin_set(SPI_SS_PIN);
    return( data );   
}

uint8_t dataOut[80];

void  max3421e_writebytes(uint8_t reg, uint8_t nbytes, char* data)
{
      nrf_gpio_pin_clear(SPI_SS_PIN);

      dataOut[0] = reg+0x02;			
      nrf_drv_spi_transfer(&m_spi, dataOut, SPIWriteLength+1, spi_rx_buf, SPIReadLength);

    while( nbytes ) {                
        //SPI_wr( *data );    // send the next data byte
        nrf_drv_spi_transfer(&m_spi, data, 1, spi_rx_buf, 0);
        data++;             // advance the pointer
        nbytes--;
    }

    nrf_gpio_pin_set(SPI_SS_PIN);

}

I feel something is wrong with my "max3421e_writebytes" and "MAXbytes_rd" function. Need some help on this.

Thanks & Regards,

Snehal

Parents
  • Hi,

    You should make sure to check the error codes returned from functions like nrf_drv_spi_transfer(), in your functions you do not do this. It also looks like you have misunderstood the return value from this function in MAXbytes_rd(), it only returns an error code, not the data received by the SPI. Normally, the SPI driver is non-blocking, which means that you have to wait for a transfer to complete before starting a new one, for instance by waiting for the spi_xfer_done flag like you have in one of the functions. 

    It should be sufficient to call nrf_drv_spi_transfer() once with the requested number of TX and RX bytes. Note that RX and TX buffer will be filled at the same time, meaning that if you want to receive a number of bytes after all data in the TX buffer have been clocked out, you need to set the RX length to TX length + number of expected RX bytes, the bytes clocked into the RX buffer while clocking out TX buffer can be ignored.

    Best regards,
    Jørgen

  • Hi Jorgen,

                   Yes I misunderstood. you are right, the error code was returned instead of data. I modified the code in following way but still it doesnt seem to work. Gives me a warning on nrf_drv_spi_transfer line.

    char* MAXbytes_rd ( uint8_t reg, uint8_t nbytes, char* data )
    {

    spi_tx_buf[0] = reg;
    spi_tx_buf[1] = 0x00;

    nrf_gpio_pin_clear(SPI_SS_PIN);

    while( nbytes ) {
      nrf_drv_spi_transfer(&m_spi, spi_tx_buf, 2, &data, nbytes);
      data++;
      nbytes--;
    }
    nrf_gpio_pin_set(SPI_SS_PIN);


    return( data );

    }

    Is still something wrong here?

    Regards,

    Snehal

Reply
  • Hi Jorgen,

                   Yes I misunderstood. you are right, the error code was returned instead of data. I modified the code in following way but still it doesnt seem to work. Gives me a warning on nrf_drv_spi_transfer line.

    char* MAXbytes_rd ( uint8_t reg, uint8_t nbytes, char* data )
    {

    spi_tx_buf[0] = reg;
    spi_tx_buf[1] = 0x00;

    nrf_gpio_pin_clear(SPI_SS_PIN);

    while( nbytes ) {
      nrf_drv_spi_transfer(&m_spi, spi_tx_buf, 2, &data, nbytes);
      data++;
      nbytes--;
    }
    nrf_gpio_pin_set(SPI_SS_PIN);


    return( data );

    }

    Is still something wrong here?

    Regards,

    Snehal

Children
No Data
Related