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

Reading from slave chip (ADS1293) through SPI

Hi everyone!

I'm trying to read a register from the ADS1293 chip by using SPI but have been stuck for a good two days. The very basic code I have is right below:

#define SPI_INSTANCE   0

static uint8_t tx;
static uint8_t rx;

static const nrf_drv_spi_t m_spi_master_0 = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);

void ADS_init( void )
{
    nrf_drv_spi_config_t const spi_config =
    {
        .sck_pin        = 27,
        .mosi_pin       = 6,
        .miso_pin       = 42,
        .ss_pin         = 44,
        .irq_priority   = APP_IRQ_PRIORITY_LOW,
        .orc            = 0xFF,
        .frequency      = NRF_DRV_SPI_FREQ_4M,
        .mode           = NRF_DRV_SPI_MODE_0,
        .bit_order      = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST, 
    };
    ret_code_t err_code = nrf_drv_spi_init(&m_spi_master_0, &spi_config, NULL, NULL);
    //SEGGER_RTT_printf(0, nrf_strerror_get(err_code));
     
}

uint8_t Read_reg(uint8_t addr)
{ 
  tx = ADS1293_READ_BIT | addr;
  ret_code_t err_code = nrf_drv_spi_transfer(&m_spi_master_0, &tx, 1, &rx, 1);
  SEGGER_RTT_printf(0, nrf_strerror_get(err_code));
  return rx;
}

There are two things I'm not 100% sure about:

1) If the pins I'm using are correct. Is there any way to make sure that the pins I'm using are correct that is simpler than managing to read the register on the ADS? Here's how they are connected:

 NRF      ADS
P0.19 -> SDO
P0.20 -> SDI
P0.04 -> SCLK
P0.03 -> CSB

2) If the way I'm using nrf_drv_spi_transfer is correct for the ADS. If I understand correctly what's on page 37 in their documentation I should send in 8 bits and will receive 8 bits and I do this by sending in the uint8_t tx (address but set the first bit to 1) and uint8_t rx. 

When I do this I get the NRF_SUCCESS code but the data received is 0x00 and is supposed to be 0x02 for the register I'm trying. I'm really new to this so I have really no idea what I should be doing right now.

Parents
  • Hi

    It seems like you've mixed up the SPI pin configuration, as you should refer to the pin configuration chapter when configuring pins, and not the pin assignments. The sck_pin, mosi_pin, miso_pin, and ss_pin configured like this for the setup you're describing.

            .sck_pin        = 4,
            .mosi_pin       = 20,
            .miso_pin       = 19,
            .ss_pin         = 3,

    Best regards,

    Simon

  • Still haven't been able to solve it, the last function in the callstack is the following: 

    Any ideas?

  • Are you still using the code you posted above?

    uint8_t Read_reg(uint8_t addr)
    { 
      tx = ADS1293_READ_BIT | addr;
      ret_code_t err_code = nrf_drv_spi_transfer(&m_spi_master_0, &tx, 1, &rx, 1);
      SEGGER_RTT_printf(0, nrf_strerror_get(err_code));
      return rx;
    }

    That will not work, as that code only reads and writes a single byte and so you never get to the registers ..

    This is an example for the ADS1291/2:

    // Scratch pad comms buffers, used for reading all AFE registers - want to preserve these for debugging
    static uint8_t mTxBuf[] = {ADS_CMND_RREG, NUMBER_OF_ADS_REGISTERS-1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    static uint8_t mRxBuf[sizeof(mTxBuf)];
    static const uint8_t mRxTxBufLength = sizeof(mTxBuf);
    STATIC_ASSERT(sizeof(mAFE_RegisterActualSettings)+2 == sizeof(mTxBuf)/sizeof(mTxBuf[0]));
    
    #define AFE_HARDWARE_VERSION 0x53 // ADS1292
    
    /**
     * @brief SPI command to read AFE registers
     * @param none
     */
    static void ReadAfeRegisters(void)
    {
        uint32_t spiAttempCount, mAfeSpiErrorCount = 0;
    
        for (spiAttempCount=0; spiAttempCount < AFE_MAX_ATTEMPTS; spiAttempCount++)
        {
            memset(mRxBuf, '?', mRxTxBufLength);
            mAfePacketTransferComplete = false;
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&mAfeSpiInstance, mTxBuf, mRxTxBufLength, mRxBuf, mRxTxBufLength));
            // Hard delay per byte to transmit
            nrf_delay_us(mRxTxBufLength*AFE_SPI_PER_BYTE_uSECS);
            // Check for ADS1292 Id
            if (mAfePacketTransferComplete && (mRxBuf[2] == AFE_HARDWARE_VERSION))
            {
                // Correct Id for this AFE, post the results skipping cmd code & length bytes
                //memcpy(&mAFE_RegisterActualSettings, &mRxBuf[2], sizeof(mAFE_RegisterActualSettings));
                break;
            }
            else
            {
                mAfeSpiErrorCount++;
                // Extra hard delay per byte to transmit
                nrf_delay_us(mRxTxBufLength*AFE_SPI_PER_BYTE_uSECS);
            }
        }
        // Post the results (may be bad) skipping cmd code & length bytes
        memcpy(&mAFE_RegisterActualSettings, &mRxBuf[2], sizeof(mAFE_RegisterActualSettings));
    }
    

    My point isn't to use this code, but instead that there is nothing useful in the first returned byte and so a command requesting a single byte transfer isn't going to be useful. The first byte of the synchronous SPI transfer says what data should be returned on 2nd and successive bytes ..

Reply
  • Are you still using the code you posted above?

    uint8_t Read_reg(uint8_t addr)
    { 
      tx = ADS1293_READ_BIT | addr;
      ret_code_t err_code = nrf_drv_spi_transfer(&m_spi_master_0, &tx, 1, &rx, 1);
      SEGGER_RTT_printf(0, nrf_strerror_get(err_code));
      return rx;
    }

    That will not work, as that code only reads and writes a single byte and so you never get to the registers ..

    This is an example for the ADS1291/2:

    // Scratch pad comms buffers, used for reading all AFE registers - want to preserve these for debugging
    static uint8_t mTxBuf[] = {ADS_CMND_RREG, NUMBER_OF_ADS_REGISTERS-1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    static uint8_t mRxBuf[sizeof(mTxBuf)];
    static const uint8_t mRxTxBufLength = sizeof(mTxBuf);
    STATIC_ASSERT(sizeof(mAFE_RegisterActualSettings)+2 == sizeof(mTxBuf)/sizeof(mTxBuf[0]));
    
    #define AFE_HARDWARE_VERSION 0x53 // ADS1292
    
    /**
     * @brief SPI command to read AFE registers
     * @param none
     */
    static void ReadAfeRegisters(void)
    {
        uint32_t spiAttempCount, mAfeSpiErrorCount = 0;
    
        for (spiAttempCount=0; spiAttempCount < AFE_MAX_ATTEMPTS; spiAttempCount++)
        {
            memset(mRxBuf, '?', mRxTxBufLength);
            mAfePacketTransferComplete = false;
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&mAfeSpiInstance, mTxBuf, mRxTxBufLength, mRxBuf, mRxTxBufLength));
            // Hard delay per byte to transmit
            nrf_delay_us(mRxTxBufLength*AFE_SPI_PER_BYTE_uSECS);
            // Check for ADS1292 Id
            if (mAfePacketTransferComplete && (mRxBuf[2] == AFE_HARDWARE_VERSION))
            {
                // Correct Id for this AFE, post the results skipping cmd code & length bytes
                //memcpy(&mAFE_RegisterActualSettings, &mRxBuf[2], sizeof(mAFE_RegisterActualSettings));
                break;
            }
            else
            {
                mAfeSpiErrorCount++;
                // Extra hard delay per byte to transmit
                nrf_delay_us(mRxTxBufLength*AFE_SPI_PER_BYTE_uSECS);
            }
        }
        // Post the results (may be bad) skipping cmd code & length bytes
        memcpy(&mAFE_RegisterActualSettings, &mRxBuf[2], sizeof(mAFE_RegisterActualSettings));
    }
    

    My point isn't to use this code, but instead that there is nothing useful in the first returned byte and so a command requesting a single byte transfer isn't going to be useful. The first byte of the synchronous SPI transfer says what data should be returned on 2nd and successive bytes ..

Children
Related