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.

ADS131E08EVM-PDK: ADS131E08EVM-PDK using SPI + DMA Getting garbage data when read/write register.

Part Number: ADS131E08EVM-PDK
Other Parts Discussed in Thread: ADS131E08

Hello Support Team,

Currently, I am working on the ADS131E08EVM-PDK dev-kit with the STM32H745 discovery board.

Scenario 1.

- Using normal SPI transmit-receive function read/write operation working fine with ADS131E08 register.

Scenario 2.

- When I have configured the DMA for SPI and used the transmit-receive_DMA function for the read/write register from  ADS131E08  using the STM32H745 discovery board.

- Then getting some garbage value.

Any specific configuration is required for the STM32H745 discovery board?

Any example is available for SPI+DMA communication for this ADS131E08  EVK. It would be great for me.

Environment Details:

Hardware : ADS13xE08EVM Rev A ,  STM32H745 Discovery board.

IDE Setup : STM32 Cube Version: 1.8.0

  • Hello Harsiddh,

    Thank you for your post and welcome to our E2E forum!

    My suggestion would be to look closely at the SPI transactions between the ADS131E08 and the STM32H745 Discovery board using a logic analyzer. This would help to confirm that the SPI frames and signal timings match the data sheet timing requirements. It seems like the device is behaving normally when you are not using DMA, so we know the data collection is working when you slow things down in the normal SPI mode.

    When using DMA, are you continuing to monitor the DRDYn interrupt from the ADC? If you record the SPI transactions along with DRDYn, and you notice a DRDYn falling edge occurs in the middle of an SPI frame, this will explain why the data looks like garbage. The old data is immediately overwritten with new data after each DRDYn falling edge, and this is transferred directly to the output shift register and read on the DOUT pin, even if it occurs in the middle of an active SPI frame.

    Unfortunately, configuring the DMA on your Discovery board is outside the scope of our forum. You'll have to direct any questions regarding the Discovery board to STmicro.

    Best regards,

    Ryan

  • Hello Ryan,

    Thank you for your briefly answering my question.

    Currently, I am not reading any ADC channel data. So no scope for DRDYn PIN data only DOUT and DIN are mainly used now.

    1. Configuring the read/write register for the start-up sequence of ADS131E08.

    2. Also doing a power start sequence.

    First, send an ADS131E08_CMD_SDATAC (for stop continuous data ) and then read one config register using E08_CONFIG1_ADDRESS.

    Also, I have shared my code below please look into this.

    If you have any example source code for ADS131E08 driver code. Could you share it with me?

    It will bill very helpful for us.

    Note: We have validated the SPI+DMA code with two STM32H745 boards it's working fine.

    //////////////////////////////////////////////ADS131E08/////////////////////////////////////////////////////////////////////
    
    /*
     * Copyright 2021 Minchul Jun (mcjun37@naver.com).  All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions are met:
     *
     *   1. Redistributions of source code must retain the above copyright notice,
     *      this list of conditions and the following disclaimer.
     *
     *   2. Redistributions in binary form must reproduce the above copyright
     *      notice, this list of conditions and the following disclaimer in the
     *      documentation and/or other materials provided with the distribution.
     *
     * THIS SOFTWARE IS PROVIDED BY MINCHUL JUN ``AS IS'' AND ANY EXPRESS OR IMPLIED
     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     * EVENT SHALL MINCHUL JUN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     * The views and conclusions contained in the software and documentation are
     * those of the authors and should not be interpreted as representing official
     * policies, either expressed or implied, of Minchul Jun.
     *
     */
    
    #include "ADS131E08.h"
    #include "cmsis_os.h"
    #include "stdlib.h"
    #include "string.h"
    #include "stm32h7xx_it.h"
    #include "spi.h"
    #include "main.h"
    
    _adcConfE* adcConfE0 = NULL;
    _adcConfE* adcConfE1 = NULL;
    
    extern uint32_t failcnt;
    extern uint32_t successcnt;
    //extern uint8_t aTxBuffer[50];
    extern uint8_t aRxBuffer[50];
    enum {
      TRANSFER_WAIT,
      TRANSFER_COMPLETE,
      TRANSFER_ERROR
    };
    extern enum Trnsfer_state state;
    uint32_t TransferStat = TRANSFER_WAIT;
    void ADS131E08_control_start_signal(_signalState onOff);
    void ADS131E08_control_reset_signal(_signalState onOff);
    void ADS131E08_control_cs_signal(_adcType adcType, _signalState onOff);
    GPIO_PinState ADS131E08_read_cs_signal(_adcType adcType);
    HAL_StatusTypeDef ADS131E08_startup(_adcType adcType);
    HAL_StatusTypeDef ADS131E08_send_command(_adcConfE* adcConfE, uint16_t cmd, uint16_t addr, uint8_t regs, uint16_t regNo);
    void ADS131E08_set_default_register(_adcConfE* adcConfE);
    
    void ADS131E08_init(_adcType adcType, SPI_HandleTypeDef* hspi)
    {
    
        if(adcType == ADS131E08_ADC20)
        {
            adcConfE0                  = (_adcConfE*)malloc(sizeof(_adcConfE));
            memset(adcConfE0, 0, sizeof(_adcConfE));
            adcConfE0->type            = adcType;
            adcConfE0->stat            = ADS131E08_INIT;
            adcConfE0->hspi            = hspi;
            adcConfE0->nReset.port     = SPI1_NRESET_GPIO_Port;
            adcConfE0->nReset.pin      = SPI1_NRESET_Pin;
            adcConfE0->cs.port         = SPI1_CS0_GPIO_Port;
            adcConfE0->cs.pin          = SPI1_CS0_Pin;
            adcConfE0->nDrdy.port      = SPI1_INT_GPIO_Port;
            adcConfE0->nDrdy.pin       = SPI1_INT_Pin;
            adcConfE0->start.port      = SPI1_START_GPIO_Port;
            adcConfE0->start.pin       = SPI1_START_Pin;
            adcConfE0->bufLen          = E08_WORDS_IN_FRAME * E08_WORD_LENGTH + 1;      // 9 Words x 24 Bits = 216 Bits (27 Bytes) + 1 (command byte)
            adcConfE0->rxBuf           = (uint8_t*)malloc(adcConfE0->bufLen);
            memset(adcConfE0->rxBuf, 0, adcConfE0->bufLen);
            adcConfE0->txBuf           = (uint8_t*)malloc(adcConfE0->bufLen);
    
            ADS131E08_set_default_register(adcConfE0);
        }
    //    else if(adcType == ADS131E08_ADC21)
    //    {
    //        adcConfE1                  = (_adcConfE*)malloc(sizeof(_adcConfE));
    //        memset(adcConfE1, 0, sizeof(_adcConfE));
    //        adcConfE1->type            = adcType;
    //        adcConfE1->stat            = ADS131E08_INIT;
    //        adcConfE1->hspi            = hspi;
    //        adcConfE1->nReset.port     = SPI1_NRESET_GPIO_Port;
    //        adcConfE1->nReset.pin      = SPI1_NRESET_Pin;
    //        adcConfE1->cs.port         = SPI1_CS1_GPIO_Port;
    //        adcConfE1->cs.pin          = SPI1_CS1_Pin;
    //        adcConfE1->nDrdy.port      = SPI1_INT_GPIO_Port;
    //        adcConfE1->nDrdy.pin       = SPI1_INT_Pin;
    //        adcConfE1->start.port      = SPI1_START_GPIO_Port;
    //        adcConfE1->start.pin       = SPI1_START_Pin;
    //        adcConfE1->bufLen          = E08_WORDS_IN_FRAME * E08_WORD_LENGTH;      // 9 Words x 24 Bits
    //        adcConfE1->rxBuf           = (uint8_t*)malloc(adcConfE1->bufLen);
    //        memset(adcConfE1->rxBuf, 0, adcConfE1->bufLen);
    //        adcConfE1->txBuf           = (uint8_t*)malloc(adcConfE1->bufLen);
    //
    //        ADS131E08_set_default_register(adcConfE1);
    //    }
        else
        {
            // DO NOTHING
        }
    
        return;
    }
    
    SPI_HandleTypeDef* ADS131E08_is_spi_type(_adcType adcType)
    {
        if(adcType == ADS131E08_ADC20)
        {
            return adcConfE0->hspi;
        }
        else if(adcType == ADS131E08_ADC21)
        {
            return adcConfE1->hspi;
        }      
        else
        {
            return NULL;
        }
    }
    
    uint8_t* ADS131E08_is_rxbuf(_adcType adcType)
    {
        if(adcType == ADS131E08_ADC20)
        {
            return adcConfE0->rxBuf;
        }
        else if(adcType == ADS131E08_ADC21)
        {
            return adcConfE1->rxBuf;
        }     
        else
        {
            return NULL;
        }
    }
    
    _ADS131E08_stat ADS131E08_is_adc_status(_adcType adcType)
    {
        if(adcType == ADS131E08_ADC20)
        {
            return adcConfE0->stat;
        }
        else if(adcType == ADS131E08_ADC21)
        {
            return adcConfE1->stat;
        }    
        else
        {
            return 0;
        }
    }
    
    void ADS131E08_set_adc_status(_adcType adcType, _ADS131E08_stat stat)
    {
        if(adcType == ADS131E08_ADC20)
        {
            adcConfE0->stat  = stat;
        }
        else if(adcType == ADS131E08_ADC21)
        {
            adcConfE1->stat = stat;
        }
        else
        {
            // DO NOTHING
        }
        return;
    }
    
    uint8_t ADS131E08_is_buf_len(_adcType adcType)
    {
        if(adcType == ADS131E08_ADC20)
        {
            return adcConfE1->bufLen;
        }
        else if(adcType == ADS131E08_ADC21)
        {
            return adcConfE1->bufLen;
        }        
        else
        {
            return 0;
        }
    }
    
    HAL_StatusTypeDef ADS131E08_send_command(_adcConfE* adcConfE, uint16_t cmd, uint16_t addr, uint8_t regs, uint16_t regNo)
    {
        const uint16_t cmdLen = 2;        // Command byte length (2 Bytes)
        HAL_StatusTypeDef result = HAL_OK;
    
        memset(adcConfE->txBuf, 0, adcConfE->bufLen);
        switch(cmd)
        {
            case ADS131E08_CMD_WAKEUP:
            case ADS131E08_CMD_STANDBY:
            case ADS131E08_CMD_RESET:
            case ADS131E08_CMD_RDATAC:
            case ADS131E08_CMD_SDATAC:
            case ADS131E08_CMD_RDATA:
                adcConfE->txBuf[0] = ADS131E08_UPPER(cmd);
                adcConfE->txBuf[1] = ADS131E08_LOWER(cmd);
                adcConfE->txBuf[2] = 0;
                adcConfE->txBuf[3] = 0;
                adcConfE->command = cmd;
                adcConfE->regAddr = 0;
                break;
            case ADS131E08_CMD_RREG:    // ADS131E08_CMD_RREGS
                adcConfE->txBuf[0] = ADS131E08_UPPER(ADS131E08_REG_COMMAND(cmd,addr,regNo));
                adcConfE->txBuf[1] = ADS131E08_LOWER(ADS131E08_REG_COMMAND(cmd,addr,regNo));
                adcConfE->txBuf[2] = 0;
                adcConfE->txBuf[3] = 0;
                adcConfE->command = cmd;
                adcConfE->regAddr = addr;
                adcConfE->regs = regs;
                break;
            case ADS131E08_CMD_WREG:
                adcConfE->txBuf[0] = ADS131E08_UPPER(ADS131E08_REG_COMMAND(cmd,addr,regNo));
                adcConfE->txBuf[1] = ADS131E08_LOWER(ADS131E08_REG_COMMAND(cmd,addr,regNo));
                adcConfE->txBuf[2] = ADS131E08_UPPER(ADS131E08_REG_REGDATA(regs));
                adcConfE->txBuf[3] = ADS131E08_LOWER(ADS131E08_REG_REGDATA(regs));
                adcConfE->command = cmd;
                adcConfE->regAddr = addr;
                adcConfE->regs = regs;
                break;
            default:
                break;
        }
    
        // Wait until cs pin is reset to send data
        while(GPIO_PIN_RESET == ADS131E08_read_cs_signal(adcConfE->type))
        {}
    
        ADS131E08_control_cs_signal(adcConfE->type, RESET_SIGNAL);
        if(cmd == ADS131E08_CMD_RREG)        
        {
            result = HAL_SPI_TransmitReceive(adcConfE->hspi, adcConfE->txBuf, adcConfE->rxBuf, cmdLen, 10);
            memset(adcConfE->rxBuf, 0, adcConfE->bufLen);
            result = HAL_SPI_Receive(adcConfE->hspi, adcConfE->rxBuf, regNo, 500);        
    
            // Update Register Status
            adcConfE->sr.mp[adcConfE->regAddr] = adcConfE->rxBuf[0];
        }
        else if(cmd == ADS131E08_CMD_WREG)
        {
            result = HAL_SPI_TransmitReceive(adcConfE->hspi, adcConfE->txBuf, adcConfE->rxBuf, regNo + cmdLen, 10);
        }
        else if(cmd == ADS131E08_CMD_RDATA)
        {
            memset(adcConfE->rxBuf, 0, adcConfE->bufLen);
            result = HAL_SPI_TransmitReceive(adcConfE->hspi, adcConfE->txBuf, adcConfE->rxBuf, 28, 10);
        }
        else
        {
            result = HAL_SPI_TransmitReceive(adcConfE->hspi, adcConfE->txBuf, adcConfE->rxBuf, cmdLen, 10);
        }
        ADS131E08_control_cs_signal(adcConfE->type, SET_SIGNAL);
    
        return result;
    }
    
    uint32_t ADS131E08_convert_adc_data(const uint8_t* dataBuf)
    {
        uint32_t upperByte = 0;
        uint32_t middleByte = 0;
        uint32_t lowerByte = 0;
    
        // The output data extends to 32 bits with eight zeroes(0b00000000, 1Byte) added to the least significant bits when using the 32-bit device word length setting, datasheet 38p
        upperByte    = ((uint32_t)(dataBuf[0] << 16) & 0x00FF0000);
        middleByte   = ((uint32_t)(dataBuf[1] << 8) & 0x0000FF00);
        lowerByte    = ((uint32_t)(dataBuf[2] << 0) & 0x000000FF);
    
        return (upperByte | middleByte | lowerByte);
    }
    
    float ADS131E08_convert_to_mVolt(uint32_t reg)
    {
        const float unitFS = 5000.0f / 8388607.0f; // unit: mV (if unit is V, calculated value is out of 'float' range)
        const uint32_t boundaryValue = 0x7FFFFF; // threshold of positive value
        int signFlg = 0;        // +: 1, -: -1
    
        // negative value
        if (reg > boundaryValue)
        {
            reg = (0xFFFFFF - reg) + 1; // if value is 0xFFFFFF, register is -FS/2^23. so plus 1
            signFlg = -1;
        }
        // positive value
        else
        {
            signFlg = 1;
        }
    
        // convert register to mVolt
        return (unitFS * (float)reg * (float)signFlg);
    }
    
    void ADS131E08_parse_adc_data(_adcType adcType)
    {
        _ADS131E08_ch ch;
        uint8_t index;
        uint32_t temp;
        uint32_t sTemp;
        const uint8_t preBitCode = 0b1100;
        uint8_t recvPreBitCode;
        _adcConfE* adcConfE;
        uint8_t* buf;
    
        if(adcType == ADS131E08_ADC20)
        {
            adcConfE = adcConfE0;
        }
        else if(adcType == ADS131E08_ADC21)
        {
            adcConfE = adcConfE1;
        }
        else
        {
            // DO NOTHING
            return;
        }
    
        // Reading Back Packet
        // 24 Status Bits + 24 Bits per channel x 8 channels = 216 bits
    
        /* Status Word Content (24 bits)
        * ---------------------------------------------------------------------------------------------------------------------
        * | Bit 23 | Bit 22 | Bit 21 | Bit 20 | Bit 19 |  ....  | Bit 12 | Bit 11 |  ....  | Bit 04 | Bit 03 |  .... | Bit 00 |
        * ---------------------------------------------------------------------------------------------------------------------
        * |    1   |    1   |    0   |    0   |     FAULT_STATP[7:0]     |     FAULT_STATN[7:0]     |        GPIO[7:4]        |
        * ---------------------------------------------------------------------------------------------------------------------
        */
    
        // rxBuf[0] is response for command(RDATA), so status buf start at rxBuf[1]
        temp = ADS131E08_MERGE_BYTE(adcConfE->rxBuf[1], adcConfE->rxBuf[2], adcConfE->rxBuf[3]);
    
        recvPreBitCode = (uint8_t)((temp & 0x00F00000) >> 20);
    
        if(recvPreBitCode != preBitCode)
        {
            // DO NOTHING
        }
    
        // Shift 4 bits to remove pre bit code(0b1100)
        sTemp = temp << 4;
        // Update Status Register
        adcConfE->sr.mp[E08_FAULT_STATP_ADDRESS]    = ADS131E08_FETCH_UPPER(sTemp);
        adcConfE->sr.mp[E08_FAULT_STATN_ADDRESS]    = ADS131E08_FETCH_MIDDLE(sTemp);
        adcConfE->sr.mp[E08_GPIO_ADDRESS]           = ADS131E08_FETCH_LOWER(sTemp) & 0xF0;
    
        // data buf start at rxBuf[4]
        buf = &adcConfE->rxBuf[4];
    
        for(ch = ADC_CH1, index = 0; ch < NUMB_ADC_CH; ch++, index++)
        {
            adcConfE->chData[ch].r = ADS131E08_convert_adc_data(&buf[index * E08_WORD_LENGTH]);        
            adcConfE->chData[ch].v = ADS131E08_convert_to_mVolt(adcConfE->chData[ch].r);
        }
    }
    // ADC1 and ADC2 share a start signal.
    // Start signal is related to generate /DRDY signal
    void ADS131E08_control_start_signal(_signalState onOff)
    {
        if(onOff == SET_SIGNAL)
        {
           HAL_GPIO_WritePin(adcConfE0->start.port, adcConfE0->start.pin, GPIO_PIN_SET);
        }
        else if(onOff == RESET_SIGNAL)
        {
            HAL_GPIO_WritePin(adcConfE0->start.port, adcConfE0->start.pin, GPIO_PIN_RESET);
        }
        else
        {
            // Do Nothing
        }
    }
    
    void ADS131E08_receive_data(_adcType adcType)
    {
        _adcConfE* adcConfE = NULL;
        if(adcType == ADS131E08_ADC20)
        {
            adcConfE = adcConfE0;
        }
        else if(adcType == ADS131E08_ADC21)
        {
            adcConfE = adcConfE1;
        }
        else
        {
            // DO NOTHING
            return;
        }
    
        // Wait until cs pin is reset to send data
        while(GPIO_PIN_RESET == ADS131E08_read_cs_signal(adcConfE->type))
        {}
        ADS131E08_control_cs_signal(adcConfE->type, RESET_SIGNAL);
        HAL_SPI_Receive(adcConfE->hspi, adcConfE->rxBuf, adcConfE->bufLen, 50);
        ADS131E08_control_cs_signal(adcConfE->type, SET_SIGNAL);
    }
    
    // RDATA command is related to conversion data
    void ADS131E08_send_rdatac_cmd()
    {
        ADS131E08_send_command(adcConfE0, ADS131E08_CMD_RDATAC, 0, 0, 1);
        ADS131E08_send_command(adcConfE1, ADS131E08_CMD_RDATAC, 0, 0, 1);
    }
    
    // RDATA command is related to conversion data
    void ADS131E08_send_rdata_cmd(_adcType adcType)
    {
        if(adcType == ADS131E08_ADC20)
        {
            ADS131E08_send_command(adcConfE0, ADS131E08_CMD_RDATA, 0, 0, 1);
        }
        else if(adcType == ADS131E08_ADC21)
        {
            ADS131E08_send_command(adcConfE1, ADS131E08_CMD_RDATA, 0, 0, 1);
        }
    }
    
    
    void ADS131E08_control_reset_signal(_signalState onOff)
    {
        if(onOff == SET_SIGNAL)
        {
           HAL_GPIO_WritePin(adcConfE0->nReset.port, adcConfE0->nReset.pin, GPIO_PIN_SET);
        }
        else if(onOff == RESET_SIGNAL)
        {
            HAL_GPIO_WritePin(adcConfE0->nReset.port, adcConfE0->nReset.pin, GPIO_PIN_RESET);
        }
        else
        {
            // Do Nothing
        }
    }
    
    void ADS131E08_control_cs_signal(_adcType adcType, _signalState onOff)
    {
        if(onOff == SET_SIGNAL)
        {
            if(adcType == ADS131E08_ADC20)
            {
                HAL_GPIO_WritePin(adcConfE0->cs.port, adcConfE0->cs.pin, GPIO_PIN_SET);
            }
            else if(adcType == ADS131E08_ADC21)
            {
                HAL_GPIO_WritePin(adcConfE1->cs.port, adcConfE1->cs.pin, GPIO_PIN_SET);
            }
            else
            {
                // DO NOTHING
            }
    
        }
        else if(onOff == RESET_SIGNAL)
        {
            if(adcType == ADS131E08_ADC20)
            {
                HAL_GPIO_WritePin(adcConfE0->cs.port, adcConfE0->cs.pin, GPIO_PIN_RESET);
            }
            else if(adcType == ADS131E08_ADC21)
            {
                HAL_GPIO_WritePin(adcConfE1->cs.port, adcConfE1->cs.pin, GPIO_PIN_RESET);
            }
            else
            {
                // DO NOTHING
            }
        }
        else
        {
            // Do Nothing
        }
    }
    
    GPIO_PinState ADS131E08_read_cs_signal(_adcType adcType)
    {
        if(adcType == ADS131E08_ADC20)
        {
            return HAL_GPIO_ReadPin(adcConfE0->cs.port, adcConfE0->cs.pin);
        }
        else if(adcType == ADS131E08_ADC21)
        {
            return HAL_GPIO_ReadPin(adcConfE1->cs.port, adcConfE1->cs.pin);
        }
    
        return 0;
    }
    
    void ADS131E08_set_default_register(_adcConfE* adcConfE)
    {
        adcConfE->sr.mp[E08_ID_ADDRESS]              =   0x00;                                  /* NOTE: This a read-only register */
        adcConfE->sr.mp[E08_CONFIG1_ADDRESS]         =   E08_CONFIG1_DEFAULT;                   /* NOTE: REV_ID value is unknown until read */
        adcConfE->sr.mp[E08_CONFIG2_ADDRESS]         =   E08_CONFIG2_DEFAULT;
        adcConfE->sr.mp[E08_CONFIG3_ADDRESS]         =   E08_CONFIG3_DEFAULT;
        adcConfE->sr.mp[E08_FAULT_ADDRESS]           =   E08_FAULT_DEFAULT;
        adcConfE->sr.mp[E08_CH1SET_ADDRESS]          =   E08_CH1SET_DEFAULT;
        adcConfE->sr.mp[E08_CH2SET_ADDRESS]          =   E08_CH2SET_DEFAULT;
        adcConfE->sr.mp[E08_CH3SET_ADDRESS]          =   E08_CH3SET_DEFAULT;
        adcConfE->sr.mp[E08_CH4SET_ADDRESS]          =   E08_CH4SET_DEFAULT;
        adcConfE->sr.mp[E08_CH5SET_ADDRESS]          =   E08_CH5SET_DEFAULT;
        adcConfE->sr.mp[E08_CH6SET_ADDRESS]          =   E08_CH6SET_DEFAULT;
        adcConfE->sr.mp[E08_CH7SET_ADDRESS]          =   E08_CH7SET_DEFAULT;
        adcConfE->sr.mp[E08_CH8SET_ADDRESS]          =   E08_CH8SET_DEFAULT;
        adcConfE->sr.mp[E08_FAULT_STATP_ADDRESS]     =   E08_FAULT_STATP_DEFAULT;
        adcConfE->sr.mp[E08_FAULT_STATN_ADDRESS]     =   E08_FAULT_STATN_DEFAULT;
        adcConfE->sr.mp[E08_GPIO_ADDRESS]            =   E08_GPIO_DEFAULT;
    }
    
    void ADS131E08_initial_flow_at_power_up(_adcConfE* adcConfE)
    {
        int i;
        volatile uint8_t regs, addr;
    
        // Always send a SDATAC command first to stop continuous conversion and write register.
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_SDATAC, 0, 0, 1);
    
        ///////////////////////////////////////
        // Read ID Register
        ///////////////////////////////////////
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_RREG, E08_ID_ADDRESS, 0, 1);
    
        ///////////////////////////////////////
        // Write Configuration 1 Register
        ///////////////////////////////////////
        // Set register with default
        regs = E08_CONFIG1_DEFAULT;
    
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_WREG, E08_CONFIG1_ADDRESS, regs, 2);
        // Confirm whether written or not.
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_RREG, E08_CONFIG1_ADDRESS, 0, 1);
    
    
        ///////////////////////////////////////
        // Write Configuration 2 Register
        ///////////////////////////////////////
        // Set register with default
        regs = E08_CONFIG2_DEFAULT;
    
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_WREG, E08_CONFIG2_ADDRESS, regs, 2);
        // Confirm whether written or not.
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_RREG, E08_CONFIG2_ADDRESS, 0, 1);
    
        ///////////////////////////////////////
        // Write CHnSET Register
        ///////////////////////////////////////
        // Set input short to middle voltage (Input shorted to (AVDD + AVSS) / 2 (for offset or noisemeasurements))
        regs = E08_CH1SET_MUX_MASK & E08_CH1SET_MUX_INPUT_SHORT_TO_MID;
        addr = E08_CH1SET_ADDRESS;
        for(i = 0; i < NUMB_ADC_CH; i++, addr++)
        {
            ADS131E08_send_command(adcConfE, ADS131E08_CMD_WREG, addr, regs, 2);
            // Confirm whether written or not.
            ADS131E08_send_command(adcConfE, ADS131E08_CMD_RREG, addr, 0, 1);
        }
        // Activate Conversion
        ADS131E08_control_start_signal(SET_SIGNAL);
    
        // Send RDATAC command
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_RDATAC, 0, 0, 1);
    
        // Capture Data and Check Noise
        // Look for /DRDY and Issue 24 + n x 24 SCLKs
        for(i = 0; i < 1; i++)
        {
            //ADS131E08_wait_drdy_int(100);
            HAL_Delay(100);
            ADS131E08_control_cs_signal(adcConfE->type, RESET_SIGNAL);
            HAL_SPI_Receive(adcConfE->hspi, adcConfE->rxBuf, adcConfE->bufLen, 500);
            ADS131E08_control_cs_signal(adcConfE->type, SET_SIGNAL);
        }
    
        // Always send a SDATAC command first to stop continuous conversion and write register.
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_SDATAC, 0, 0, 1);
    
        ///////////////////////////////////////
        // Write Configuration 2 Register
        ///////////////////////////////////////
        // Set that test signal are generated internally (Activate a (1mV / 2.4V) Square-Wave Test Signal)
        regs = E08_CONFIG2_INT_TEST_MASK & E08_CONFIG2_INT_TEST_ENABLE;
    
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_WREG, E08_CONFIG2_ADDRESS, regs, 2);
        // Confirm whether written or not.
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_RREG, E08_CONFIG2_ADDRESS, 0, 1);
    
        ///////////////////////////////////////
        // Write CHnSET Register
        ///////////////////////////////////////
        // Set test signal enable on All Channels
        regs = E08_CH1SET_MUX_MASK & E08_CH1SET_MUX_TEST_SIGNAL;
        addr = E08_CH1SET_ADDRESS;
        for(i = 0; i < NUMB_ADC_CH; i++, addr++)
        {
            ADS131E08_send_command(adcConfE, ADS131E08_CMD_WREG, addr, regs, 2);
            // Confirm whether written or not.
            ADS131E08_send_command(adcConfE, ADS131E08_CMD_RREG, addr, 0, 1);
        }
    
        // Send RDATAC command
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_RDATAC, 0, 0, 1);
    
        // Capture Data and Test Signal
        // Look for /DRDY and Issue 24 + n x 24 SCLKs
        for(i = 0; i < 1; i++)
        {
            //ADS131E08_wait_drdy_int(100);
            HAL_Delay(100);
            ADS131E08_control_cs_signal(adcConfE->type, RESET_SIGNAL);
            HAL_SPI_Receive(adcConfE->hspi, adcConfE->rxBuf, adcConfE->bufLen, 500);
            ADS131E08_control_cs_signal(adcConfE->type, SET_SIGNAL);
        }
    
        // Always send a SDATAC command first to stop continuous conversion and write register.
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_SDATAC, 0, 0, 1);
    
        // Stop Conversion
        ADS131E08_control_start_signal(RESET_SIGNAL);    
    }
    
    HAL_StatusTypeDef ADS131E08_startup(_adcType adcType)
    {
        int i;
        volatile uint8_t addr;
        volatile uint8_t regs;
        _adcConfE* adcConfE;
        uint8_t cmdLen;
        cmdLen=4;
        uint16_t cmd;
        uint16_t regNo;
    
    
        if(adcType == ADS131E08_ADC20)
        {
            adcConfE = adcConfE0;
        }
        else if(adcType == ADS131E08_ADC21)
        {
            adcConfE = adcConfE1;
        }
        else
        {
            // DO NOTHING
            return HAL_ERROR;
        }
    
        HAL_Delay(5);
    
        regs = 0;
        cmd = ADS131E08_CMD_SDATAC;
        addr = 0;
        regNo = 1;
        printf("sendding Register write command data over SPI\n");
        adcConfE->txBuf[0] = ADS131E08_UPPER(cmd);
        adcConfE->txBuf[1] = ADS131E08_LOWER(cmd);
        adcConfE->txBuf[2] = 0;
        adcConfE->txBuf[3] = 0;
        adcConfE->command = cmd;
        adcConfE->regAddr = 0;
        TransferStat = TRANSFER_WAIT;
        if(HAL_SPI_TransmitReceive_DMA(&hspi2, adcConfE->txBuf, adcConfE->rxBuf, cmdLen) != HAL_OK)
        {
          /* Transfer error in transmission process */
          Error_Handler();
          printf("HAL_SPI_TrasmitReceive Error \n");
        }
          printf("Data sent waiting for tx satus\n\n");
        while (TransferStat == TRANSFER_WAIT)
        {
    
        }
        printf("Write Command Transfer Completed checking the case\n");
    
    
          //////////////////////////////Test SPI_DMA command with ADS131E08///////////////////////
          regs = E08_CONFIG1_DEFAULT;
          cmd = ADS131E08_CMD_WREG;
          addr = E08_CONFIG1_ADDRESS;
          regNo = 2;
          while (1)
          {
    
              printf("sendding Register write command data over SPI\n");
              adcConfE->txBuf[0] = ADS131E08_UPPER(ADS131E08_REG_COMMAND(cmd,addr,regNo));
              adcConfE->txBuf[1] = ADS131E08_LOWER(ADS131E08_REG_COMMAND(cmd,addr,regNo));
              adcConfE->txBuf[2] = ADS131E08_UPPER(ADS131E08_REG_REGDATA(regs));
              adcConfE->txBuf[3] = ADS131E08_LOWER(ADS131E08_REG_REGDATA(regs));
              adcConfE->command = cmd;
              adcConfE->regAddr = addr;
              adcConfE->regs = regs;
          if(HAL_SPI_TransmitReceive_DMA(&hspi2, adcConfE->txBuf, adcConfE->rxBuf, cmdLen) != HAL_OK)
           {
             /* Transfer error in transmission process */
             Error_Handler();
             printf("HAL_SPI_TrasmitReceive Error \n");
           }
              printf("Data sent waiting for tx satus\n\n");
           while (TransferStat == TRANSFER_WAIT)
           {
           }
            printf("Write Command Transfer Completed checking the case\n");
    
           /* Invalidate cache prior to access by CPU */
           SCB_InvalidateDCache_by_Addr ((uint32_t *)aRxBuffer, BUFFERSIZE);
    
           switch(TransferStat)
           {
             case TRANSFER_COMPLETE :
                 printf("Enter in TX complete case\n");
           /*##-4- Compare the sent and received buffers ##############################*/
               break;
             default :
                 printf("enter in deafult case\n");
               //Error_Handler();
               break;
           }
           HAL_Delay(1000);
    
           ADS131E08_send_command(adcConfE, ADS131E08_CMD_RREG, E08_CONFIG1_ADDRESS, 0, 1);
           printf("sendding Register Read command data over SPI\n");
           adcConfE->txBuf[0] = ADS131E08_UPPER(ADS131E08_REG_COMMAND(cmd,addr,regNo));
           adcConfE->txBuf[1] = ADS131E08_LOWER(ADS131E08_REG_COMMAND(cmd,addr,regNo));
           adcConfE->txBuf[2] = 0;
           adcConfE->txBuf[3] = 0;
           adcConfE->command = cmd;
           adcConfE->regAddr = addr;
           adcConfE->regs = regs;
           regs = E08_CONFIG1_DEFAULT;
           cmd = ADS131E08_CMD_RREG;
           addr = E08_CONFIG1_ADDRESS;
           regNo = 1;
           TransferStat = TRANSFER_WAIT;
           if(HAL_SPI_TransmitReceive_DMA(&hspi2, adcConfE->txBuf, adcConfE->rxBuf, cmdLen) != HAL_OK)
                  {
                    /* Transfer error in transmission process */
                    Error_Handler();
                    printf("HAL_SPI_TrasmitReceive Error \n");
                  }
                     printf("Data sent waiting for tx satus\n\n");
                  while (TransferStat == TRANSFER_WAIT)
                  {
                  }
                  printf("Read Command Transfer Completed checking the case\n");
    
                  /* Invalidate cache prior to access by CPU */
                  SCB_InvalidateDCache_by_Addr ((uint32_t *)aRxBuffer, BUFFERSIZE);
    
                  switch(TransferStat)
                  {
                    case TRANSFER_COMPLETE :
                        printf("Enter in TX complete case\n");
                  /*##-4- Compare the sent and received buffers ##############################*/
                      break;
                    default :
                        printf("enter in deafult case\n");
                      //Error_Handler();
                      break;
                  }
               TransferStat = TRANSFER_WAIT;
               if(HAL_SPI_TransmitReceive_DMA(&hspi2, adcConfE->txBuf,adcConfE->rxBuf, cmdLen) != HAL_OK)
                      {
                        /* Transfer error in transmission process */
                        Error_Handler();
                        printf("HAL_SPI_TrasmitReceive Error \n");
                      }
               while (TransferStat == TRANSFER_WAIT)
               {
               }
               printf("Register Read successfully  Completed checking the case\n");
               // Update Register Status
               adcConfE->sr.mp[adcConfE->regAddr] = adcConfE->rxBuf[0];
    
        }
    
    
    
        ADS131E08_initial_flow_at_power_up(adcConfE);
    
    //After this power starts we could send the Read/write command.
    
        // Always send an SDATAC command first to stop continuous conversion and write register.
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_SDATAC, 0, 0, 1);
    
        ///////////////////////////////////////
        // Write Configuration 1 Register
        ///////////////////////////////////////
        // Remove register value related with data rate
        regs = E08_CONFIG1_DEFAULT & (~E08_CONFIG1_DR_MASK);
        // Set Data rate to 1 kSPS
        regs |= E08_CONFIG1_DR_MASK & E08_DR_1KSPS;
    
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_WREG, E08_CONFIG1_ADDRESS, regs, 2);
        // Confirm whether written or not.
        HAL_Delay(5);
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_RREG, E08_CONFIG1_ADDRESS, 0, 1);
    
        if(adcConfE->sr.mp[E08_CONFIG1_ADDRESS] != regs)
        {
            return HAL_ERROR;
        }
        else
        {
            // DO NOTHING, Keep going
        }
    
        ///////////////////////////////////////
        // Write Configuration 2 Register
        ///////////////////////////////////////
        // Set register with default
        regs = E08_CONFIG2_DEFAULT;
    
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_WREG, E08_CONFIG2_ADDRESS, regs, 2);
        // Confirm whether written or not.
        ADS131E08_send_command(adcConfE, ADS131E08_CMD_RREG, E08_CONFIG2_ADDRESS, 0, 1);
    
        if(adcConfE->sr.mp[E08_CONFIG2_ADDRESS] != regs)
        {
            return HAL_ERROR;
        }
        else
        {
            // DO NOTHING, Keep going
        }
    
        ///////////////////////////////////////
        // Write CHnSET Register
        ///////////////////////////////////////
        // Set register with default
        regs = E08_CH1SET_DEFAULT;
        addr = E08_CH1SET_ADDRESS;
        for(i = 0; i < NUMB_ADC_CH; i++, addr++)
        {
            ADS131E08_send_command(adcConfE, ADS131E08_CMD_WREG, addr, regs, 2);
            // Confirm whether written or not.
            ADS131E08_send_command(adcConfE, ADS131E08_CMD_RREG, addr, 0, 1);
    
            if(adcConfE->sr.mp[addr] != regs)
            {
                return HAL_ERROR;
            }
            else
            {
                // DO NOTHING, Keep going
            }        
        }
    
        ADS131E08_set_adc_status(adcConfE->type, ADS131E08_NORMAL);
    
        return HAL_OK;
    }
    
    void ADS131E08_send_rdatac_command()
    {
        // Send RDATAC command to ADC20, ADC21 simultaneously.
        ADS131E08_send_command(adcConfE0, ADS131E08_CMD_RDATAC, 0, 0, 1);
        ADS131E08_send_command(adcConfE1, ADS131E08_CMD_RDATAC, 0, 0, 1);
    }
    
    void ADS131E08_initialize_signal()
    {
        // Generate Reset Pulse
        ADS131E08_control_reset_signal(SET_SIGNAL);
        ADS131E08_control_start_signal(RESET_SIGNAL);
        ADS131E08_control_reset_signal(RESET_SIGNAL);
        HAL_Delay(5);
        ADS131E08_control_reset_signal(SET_SIGNAL);
        // Initialize Chip Select signal
        ADS131E08_control_cs_signal(ADS131E08_ADC20, SET_SIGNAL);
        //ADS131E08_control_cs_signal(ADS131E08_ADC21, SET_SIGNAL);
    }
    
    //////////////////////////////////END//////////////////////////////////////////////////////////////////////////////////////////////////////

  • Hi Harsiddh,

    Can then please share a logic analyzer capture of the SPI communication (i.e. CSn, SCLK, DIN, and DOUT)? It would be helpful to see what you mean by "garbage" register data.

    Regarding the power supply sequencing, we simply suggest that the host controller reset the ADC after both AVDD and DVDD supplies have ramped. This can be accomplished via the RESET SPI command or the RESETn pin. This will ensure that the internal programmed bit settings are read correctly at start-up and place the device in a known good state of operation. 

    We are not able to support code reviews at this time. However, I can point you to our ADS131E08EVM-PDK software, which includes the firmware used for the DSP controller. You are welcome to refer to it if that helps you in your development.

    You can download the EVM software here:

    https://www.ti.com/tool/ADS131E08EVM-PDK#order-start-development

    Best regards,

    Ryan

  • Hello Reyan

    Thank you for giving a satisfied answer for my reply.

    --->Can then please share a logic analyzer capture of the SPI communication?

    1) I have attached all waveform which is captured by DSO.
    - With normal SPI communication with ADS131E08EVM-PDK
    - With SPI + DMA enable communication with ADS131E08EVM-PDK.


    Scenario 1: For normal SPI configuration communication happening on both ends.
              - STM32H745 discovery sending the actual data which is verified by DSO outputs.
              - Also receive the data from ADS131E08EVM-PDK which is also verified by DSO outputs.
              
              
    Scenario 2: For SPI+DMA configuration with ADS131E08EVM-PDK.
              - Data sending properly from the STM32H745 side which is verified by DSO outputs.
              - Receiving the same data for SPI+DMA successfully.
            

    SPI+DMA getting garbage data issue was resolved.



    Currently, I am facing an issue with DRDY interrupt PIN.
    I have followed the below sequence if something is wrong please correct it.
    initial flow at power up
    -> Reset the ADC through PIN
    -> send SDATAC command
    -> set CONFIG1(0x91) register
    -> set CONFIG2(0xE0) register
    -> set channel register with 0x07
    -> set START signal.
    -> send RDATAC command
    -> wait for 20 tck
    -> Receive the data
    -> send SDATAC command
    -> set CONFIG2 Register with test signal generated internally
    -> reset the START signal
    -> send SDATAC command
    -> test signal enable for all channel
    -> send RDATAC command
    -> Receive the data
    -> send SDATAC command
    -> reset the START signal.

    ADC start-up flow
    -> send SDATAC command
    -> set CONFIG1(0x91) register
    -> set CONFIG2(0xE0) register
    -> set Channel register

    According to the above sequence not getting called DRDY interrupt signal from ADS131E08 also verified with DSO outputs.

    I have started the START signal after the  ADC start-up flow.

    Anything is required for the CONFIG register side as well as the command side please mention it.
    If any configuration is missed at my side give the correct data and sequence.


    Below I have written my all config register address value and default set value details which is set into ADS131E08EVM-PDK.

    1) /* Register 0x01 (CONFIG1) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * |     1     |  DAISY_IN |   CLK_EN  |      1    |      0    |               DR[2:0]             |
     * -------------------------------------------------------------------------------------------------
     */
    
        /* CONFIG1 register address */
        #define E08_CONFIG1_ADDRESS                                                    ((uint8_t) 0x01)
    
        /* CONFIG1 default (reset) value */
        #define E08_CONFIG1_DEFAULT                                                    ((uint8_t) 0x91)
    
    2)/* Register 0x02 (CONFIG2) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * |     1     |     1     |     1     |  INT_TEST |     0     |  TEST_AMP |     TEST_FREQ[1:0]    |
     * -------------------------------------------------------------------------------------------------
     */
    
        /* CONFIG2 register address */
        #define E08_CONFIG2_ADDRESS                                                    ((uint8_t) 0x02)
    
        /* CONFIG2 default (reset) value */
        #define E08_CONFIG2_DEFAULT                                                    ((uint8_t) 0xE0)
        
    3)/* Register 0x03 (CONFIG3) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * | PDB_REFBUF|     1     |  VREF_4V  |     0     | OPAMP_REF | PDB_OPAMP |     0     |     0     |
     * -------------------------------------------------------------------------------------------------
     */
    
        /* CONFIG3 register address */
        #define E08_CONFIG3_ADDRESS                                                    ((uint8_t) 0x03)
    
        /* CONFIG3 default (reset) value */
        #define E08_CONFIG3_DEFAULT                                                    ((uint8_t) 0x40)
    
    4)/* Register 0x04 (FAULT) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * |            COMP_TH[2:0]           |     0     |     0     |     0     |     0     |     0     |
     * -------------------------------------------------------------------------------------------------
     */
    
        /* FAULT register address */
        #define E08_FAULT_ADDRESS                                                    ((uint8_t) 0x04)
    
        /* FAULT default (reset) value */
        #define E08_FAULT_DEFAULT                                                    ((uint8_t) 0x00)
    
        /* FAULT register field masks */
        #define E08_FAULT_MASK                                                        ((uint8_t) 0xE0)
    
    5)/* Register 0x12 (FAULT_STATP) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * | IN8P_FAULT| IN7P_FAULT| IN6P_FAULT| IN5P_FAULT| IN4P_FAULT| IN3P_FAULT| IN2P_FAULT| IN1P_FAULT|
     * -------------------------------------------------------------------------------------------------
     */
    
        /* FAULT_STATP register address */
        #define E08_FAULT_STATP_ADDRESS                                                ((uint8_t) 0x12)
    
        /* FAULT_STATP default (reset) value */
        #define E08_FAULT_STATP_DEFAULT                                                ((uint8_t) 0x00)
        
    6)/* Register 0x13 (FAULT_STATN) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * | IN8_NFAULT| IN7N_FAULT| IN6N_FAULT| IN5N_FAULT| IN4N_FAULT| IN3N_FAULT| IN2N_FAULT| IN1N_FAULT|
     * -------------------------------------------------------------------------------------------------
     */
    
        /* FAULT_STATN register address */
        #define E08_FAULT_STATN_ADDRESS                                                ((uint8_t) 0x13)
    
        /* FAULT_STATN default (reset) value */
        #define E08_FAULT_STATN_DEFAULT                                                ((uint8_t) 0x00)
    
    7)/* Register 0x14 (GPIO) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * |                   GPIOD[7:4]                  |                   GPIOC[4:1]                  |
     * -------------------------------------------------------------------------------------------------
     */
    
        /* GPIO register address */
        #define E08_GPIO_ADDRESS                                                    ((uint8_t) 0x14)
    
        /* GPIO default (reset) value */
        #define E08_GPIO_DEFAULT                                                    ((uint8_t) 0x0F)


    Above all register configuration any mismatch according to datasheet please correct it.

    Below I have put the DSO output for SPI and SPI+DMA Read ID command response from the ADS131E08.

    Image : SPI_READ_ID_COMMAND_RESPOND

    (3) Data and (2) CLK

    Image: SPI_DMA_READ_ID_COMMAND_RESPOND

    (3) CLK and (2) Data

    Thanks In Advance

  • SPI+DMA getting garbage data issue was resolved.

    Hello Harsiddh,

    I'm glad you resolved the data collection issue. The ID register read images look correct with and without DMA.

    What is it that you still need help with?

    Regards,

    Ryan

  • Hello Ryan,

    Thank you for your quick and marvelous reply.

    Currently, I am facing an issue with ADC131E08's DRDY interrupt PIN.
    In that, I have configured the below pin settings.
    1) START pin - Output PIN
    2) SPI1_INT - External Interrupt PIN - On Rising Edge
    3) SPI1_NRESET - Output PIN - Reset the ADC
    4) SPI1_CS0 - Output PIN - Chip select

    I have followed the below sequence if something is wrong please correct it.
    initial flow at power up
    -> Reset the ADC through PIN
    -> send SDATAC command
    -> set CONFIG1(0x91) register
    -> set CONFIG2(0xE0) register
    -> set channel register with 0x07
    -> set START signal.
    -> send RDATAC command
    -> wait for 20 tck
    -> Receive the data
    -> send SDATAC command
    -> set CONFIG2 Register with test signal generated internally
    -> reset the START signal
    -> send SDATAC command
    -> test signal enable for all channel
    -> send RDATAC command
    -> Receive the data
    -> send SDATAC command
    -> reset the START signal.

    ADC start-up flow
    -> send SDATAC command
    -> set CONFIG1(0x91) register
    -> set CONFIG2(0xE0) register
    -> set Channel register

    Last step
    -> Set the START PIN for ADC conversion
    I have started the START signal after the  ADC start-up flow.

    According to the above sequence not getting called DRDY interrupt signal from ADS131E08 also verified with DSO outputs(DRDY PIN always Pulled high).

    Anything is required for the CONFIG register side as well as the command side please mention it.
    If any configuration is missed at my side give the correct data and sequence.

    Below I have written my CONFIG registers default values.
    1) /* Register 0x01 (CONFIG1) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * |     1     |  DAISY_IN |   CLK_EN  |      1    |      0    |               DR[2:0]             |
     * -------------------------------------------------------------------------------------------------
     */
    
        /* CONFIG1 register address */
        #define E08_CONFIG1_ADDRESS                                                    ((uint8_t) 0x01)
    
        /* CONFIG1 default (reset) value */
        #define E08_CONFIG1_DEFAULT                                                    ((uint8_t) 0x91)
    
    2)/* Register 0x02 (CONFIG2) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * |     1     |     1     |     1     |  INT_TEST |     0     |  TEST_AMP |     TEST_FREQ[1:0]    |
     * -------------------------------------------------------------------------------------------------
     */
    
        /* CONFIG2 register address */
        #define E08_CONFIG2_ADDRESS                                                    ((uint8_t) 0x02)
    
        /* CONFIG2 default (reset) value */
        #define E08_CONFIG2_DEFAULT                                                    ((uint8_t) 0xE0)
        
    3)/* Register 0x03 (CONFIG3) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * | PDB_REFBUF|     1     |  VREF_4V  |     0     | OPAMP_REF | PDB_OPAMP |     0     |     0     |
     * -------------------------------------------------------------------------------------------------
     */
    
        /* CONFIG3 register address */
        #define E08_CONFIG3_ADDRESS                                                    ((uint8_t) 0x03)
    
        /* CONFIG3 default (reset) value */
        #define E08_CONFIG3_DEFAULT                                                    ((uint8_t) 0x40)
    
    4)/* Register 0x04 (FAULT) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * |            COMP_TH[2:0]           |     0     |     0     |     0     |     0     |     0     |
     * -------------------------------------------------------------------------------------------------
     */
    
        /* FAULT register address */
        #define E08_FAULT_ADDRESS                                                    ((uint8_t) 0x04)
    
        /* FAULT default (reset) value */
        #define E08_FAULT_DEFAULT                                                    ((uint8_t) 0x00)
    
        /* FAULT register field masks */
        #define E08_FAULT_MASK                                                        ((uint8_t) 0xE0)
    
    5)/* Register 0x12 (FAULT_STATP) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * | IN8P_FAULT| IN7P_FAULT| IN6P_FAULT| IN5P_FAULT| IN4P_FAULT| IN3P_FAULT| IN2P_FAULT| IN1P_FAULT|
     * -------------------------------------------------------------------------------------------------
     */
    
        /* FAULT_STATP register address */
        #define E08_FAULT_STATP_ADDRESS                                                ((uint8_t) 0x12)
    
        /* FAULT_STATP default (reset) value */
        #define E08_FAULT_STATP_DEFAULT                                                ((uint8_t) 0x00)
        
    6)/* Register 0x13 (FAULT_STATN) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * | IN8_NFAULT| IN7N_FAULT| IN6N_FAULT| IN5N_FAULT| IN4N_FAULT| IN3N_FAULT| IN2N_FAULT| IN1N_FAULT|
     * -------------------------------------------------------------------------------------------------
     */
    
        /* FAULT_STATN register address */
        #define E08_FAULT_STATN_ADDRESS                                                ((uint8_t) 0x13)
    
        /* FAULT_STATN default (reset) value */
        #define E08_FAULT_STATN_DEFAULT                                                ((uint8_t) 0x00)
    
    7)/* Register 0x14 (GPIO) definition
     * -------------------------------------------------------------------------------------------------
     * |   Bit 7   |   Bit 6   |   Bit 5   |   Bit 4   |   Bit 3   |   Bit 2   |   Bit 1   |   Bit 0   |
     * -------------------------------------------------------------------------------------------------
     * |                   GPIOD[7:4]                  |                   GPIOC[4:1]                  |
     * -------------------------------------------------------------------------------------------------
     */
    
        /* GPIO register address */
        #define E08_GPIO_ADDRESS                                                    ((uint8_t) 0x14)
    
        /* GPIO default (reset) value */
        #define E08_GPIO_DEFAULT                                                    ((uint8_t) 0x0F)


    Thanks In Advance

  • Hello Harsiddh,

    For future posts, please use the Insert -> Code feature when pasting in code snip-its into the body of the post. These makes the thread more readable for other users.

    DRDYn should be configured as a falling edge interrupt. The rising edge of DRDYn varies depending on when or if the conversion data is read back from the device.

    One comment about your procedure - you do not need to toggle the START pin when you want to make a change to the register configuration and collect more data. Each time you write to the CHnSET registers, the digital filter will reset internally and provide valid data after the specified settling time (i.e. 3 conversion periods for a sinc3 filter). The START pin or command only control the delta-sigma modulators, which you can allow to convert continuously, even while writing to the device registers.

    Regards,

    Ryan

  • Hello Ryan,

    Thanks a million for the above reply very helpful for understanding the purpose of DRDY interrupt and START pin state set/reset.

    My ADS131E08 setup is working with the STM32H745 discovery board and getting samples at a 16ksps data rate.

    Currently, I am working on converting the ADC sample data into voltage form.

    I have also written logic for converting the ADC raw data into appropriate voltage.

    Below I have attached my code just go through it and let me know if it is the correct method or not.

    // Reading Back Packet
         Here I am reading the total of 28 bytes in the "adcConfE->rxBuf[]" buffer.



        1) First 24-bit parsed into "status_bit" variable which is 32-bit
           - Merging the first three byte adcConfE->rxBuf[1], adcConfE->rxBuf[2], adcConfE->rxBuf[3];
           - Then store into "status_bit"

        2) Recovering the Pre bit code from  "status_bit"

        if(check whether the pre-bit code matched or not)
        {
            // DO NOTHING
        }
        then remove the prebit code status_bit_test = status_bit << 4;
        3) Fetching the Fault_statp_address, Fault_statn_address , GPIO_Address register value  into appropriate index into the register array
          
                reg[E08_FAULT_STATP_ADDRESS]    = ADS131E08_UPPER_BYTE(status_bit_test);
                reg[E08_FAULT_STATN_ADDRESS]    = ADS131E08_FETCH_MIDDLE_BYTE(status_bit_test);
                reg[E08_GPIO_ADDRESS]           = ADS131E08_FETCH_LOWER_BYTE(status_bit_test) & 0xF0;

        4) store the ADC channel data starting address
                adc_buf = rxBuf[4];
        5) The output data extends to 32 bits with added to the least significant bits when using the 32-bit device word length setting, datasheet
            
        6) Covering the significant data into mVolt
            Defined one float constant and boundary value using this value ADC mvolt final conversion done.
            According boundary value decided whether the value is signed or unsigned.
            float constant = 2400.0f / 8388607.0f;

    boundary_constatnt  = 0x7FFFFF;
            Then reg array value multiplies with float constant and signFlg value then stored into the appropriate channel index into an array.

    Currently, Following the above step, I got the output at ADC channel-1 value at different voltages.

    Please verify the converted mVoltage readings below Table.1

    Let me know if it is correct and from my side if any bit is missed or conversion happens the wrong way please help me to figure it out.

    Vref = 2.4 Volt (Internal)
    Volt (Input) Milli Volt (ADC Reading )
    0.0
    918.710022
    1293.730103
    -412.498901
    1087.500977
    712.501221
    -224.998871
    1087.501221
    150.00087
    150.00116
    1462.501343
    0.5
    -1293.789062
    -1256.266724
    -2174.999023
    -862.498962
    2325.001465
    -1537.499023
    -1649.999023
    -562.498901
    1800.001343
    -1162.499023

                   Table 1
            
        


         

  • I work on one project where I really want to know the ADC reading and accuracy and based on that I have to take further decisions.

    I am really waiting for your reply to my queries.

    Your reply is really helping full for me.

    Your earlier replay is highly appreciatable.