This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS131A04: How to read channel data faster?

Part Number: ADS131A04

Hello! I am using MSP432 to communicate with ADS131A04 ADC using 32 bit words (M1 = 1), asynchronous interrupt mode (M0 = 1), without Hamming code validation (M2 = 0), with external reference voltages and 16.384MHz crystal, in high-resolution mode - 24 bits. I want to use the ADC at 10.24kHz data rate.

The problem is that I cannot read the channel data fast enough before new data is available. At 10.24kHz, I need to read in maximum ~100us. I have attached the following logic analyzer captures (they can be opened using the free Salae Logic Pro software; channel 4 is DRDY):

1. 1kHz data rate, 1MHz SPI clock - byte time is 8us, time between bytes is ~8us and word time ~314us;

2. 1kHz data rate, 4MHz SPI clock - byte time is 4us, time between bytes is ~10us and word time ~253us;

3. 1kHz data rate, 8MHz SPI clock - byte time is 1us, time between bytes is ~7us and word time ~170us;

4. 10.24kHz data rate, 8MHz SPI clock - byte time is 1us, time between bytes is ~7us and word time ~170us; you can see that DRDY changes before reading all data;

You can find attached an oscilloscope screen capture showing MISO at 1kHz data rate, 24MHz SPI clock. Those lines are the 20 bytes that compose the word and the transmission duration of a word is ~170us.

I need to have a word transmission time smaller than 100us to be able to read the next samples in time.

When reading channel data, the word has 20 bytes. I could use 24 bit words, gaining 5 bytes, but it is not enough. 24MHz is the maximum SPI clock MSP432 can provide and 25MHz is the maximum SPI clock accepted by the ADC.

This is my configuration:

#define ADS131A04_A_SYS_CFG_VALUE   0x60
#define ADS131A04_D_SYS_CFG_VALUE   0x3C
#define ADS131A04_CLK1_VALUE        0x02
#define ADS131A04_CLK2_VALUE        0x26 // 0x26 for 10.24kHz data rate, 0x20 for 1kHz data rate
#define ADS131A04_ADC_ENA_VALUE     0x00
#define ADS131A04_ADC1_VALUE        0x00
#define ADS131A04_ADC2_VALUE        0x00
#define ADS131A04_ADC3_VALUE        0x00
#define ADS131A04_ADC4_VALUE        0x00

What can I do to read the data faster? Is it a limitation of the MSP432 or of the ADC? There must be a solution because it wouldn't make sense to provide higher data rates without having the possibility to read the samples in time.

Captures.zip

  • Hi Cristian,

    In this case, the limitation is in the MSP430, not the ADS131A04. Looking at the LA plot for the 10.24kSPS capture, you spend 7.35uS idle between bytes and then 15.75uS idle between words so you might be able to speed things up a little in your interrupt service routine. If you'd like to post that portion of your code here, we'd be happy to take a look at it. You might also try posting a query to the MSP430 forum to see if they have any suggestions on speeding up the transfer between bytes.
  • Hi Tom,

    This is my code:

    for (i = 0; i < noSamples; i++)
        {
            while (adcSampleAvailable == false) // Wait for !DRDY
            {
                //MAP_PCM_gotoLPM0InterruptSafe();
                //MAP_Interrupt_enableMaster();
            }
            adcSampleAvailable = false;
    
            // Read samples
            rxData = ADS131A04_read(20); // STAT_1 x 4 bytes + 4 channels x 4 bytes
    
            *(readDataCh1 + i) = (*(rxData + 4) << 16) | (*(rxData + 5) << 8) | (*(rxData + 6));
            *(readDataCh2 + i) = (*(rxData + 8) << 16) | (*(rxData + 9) << 8) | (*(rxData + 10));
            *(readDataCh3 + i) = (*(rxData + 12) << 16) | (*(rxData + 13) << 8) | (*(rxData + 14));
            *(readDataCh4 + i) = (*(rxData + 16) << 16) | (*(rxData + 17) << 8) | (*(rxData + 18));
        }
    
    unsigned char* ADS131A04_read(unsigned char bytesNumber)
    {
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN4); // !ADC_SPI_CS = 0
    
        int byte = 0;
        int count = bytesNumber;
        if (bytesNumber > ADS131A04_MAX_RX_BYTES) count = ADS131A04_MAX_RX_BYTES;
    
        for(byte = 0; byte < count; byte++)
        {
            while (adcTxFlag == false)
            {
                //MAP_PCM_gotoLPM0InterruptSafe();
                //MAP_Interrupt_enableMaster();
            }
            adcTxFlag = false;
    
            MAP_SPI_transmitData(EUSCI_B0_BASE, 0x00); // Dummy write to clock out data
    
            while (adcRxFlag == false)
            {
                //MAP_PCM_gotoLPM0InterruptSafe();
                //MAP_Interrupt_enableMaster();
            }
            adcRxFlag = false;
    
            rxData[byte] = MAP_SPI_receiveData(EUSCI_B0_BASE);
        }
    
        MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P1, GPIO_PIN4); // !ADC_SPI_CS = 1
    
        return rxData;
    }
    
    void PORT4_IRQHandler(void)
    {
        uint32_t status;
        status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P4);
        MAP_GPIO_clearInterruptFlag(GPIO_PORT_P4, status);
        if(status & GPIO_PIN0) // ADC !DRDY
        {
            if (MAP_GPIO_getInputPinValue(GPIO_PORT_P4, GPIO_PIN0) == 0)
            {
                adcSampleAvailable = true;
                MAP_Interrupt_disableSleepOnIsrExit();
            }
        }
    }
    
    void EUSCIB0_IRQHandler(void)
    {
        unsigned int status;
        status = MAP_SPI_getEnabledInterruptStatus(EUSCI_B0_BASE);
        MAP_SPI_clearInterruptFlag(EUSCI_B0_BASE, status);
        if (status & EUSCI_B_SPI_TRANSMIT_INTERRUPT)
        {
            adcTxFlag = true;
        }
        if (status & EUSCI_B_SPI_RECEIVE_INTERRUPT)
        {
            adcRxFlag = true;
        }
        MAP_Interrupt_disableSleepOnIsrExit();
    }

  • Thank you for the advice. I managed to find a solution which I described in this post:
    e2e.ti.com/.../2313177
  • Cool!

    Thank you for letting us know!