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.

ADS8332: Configuration and Reading CFR register (daisy-chain)

Part Number: ADS8332

Hello,

I use a MCU which communicates with two ADS8332's (daisy-chain) over SPI, whereby the MCU is the master and both ADC's are slaves.  The function below shows the configuration of the CFR register. Both input parameters (ADS833x_CFR_Reg1 and ADS833x_CFR_Reg2) correspond to the bits which I want to write in the register:

void ADS833x_init(uint16_t ADS833x_CFR_Reg1, uint16_t ADS833x_CFR_Reg2)      // Initialize ADS833x
{
    uint16_t Reg_Word1;
    uint16_t Reg_Word2;

    uint16_t ADS833x_Write_Com = 0xE000;
    uint16_t ADS833x_Read_Com = 0xC000;
    uint16_t ADS833x_Buf[BUF_SIZE];
    
    for (int i =0; i<BUF_SIZE;i++){
        ADS833x_Buf[i]=0;
    }

    Reg_Word1 = ADS833x_Write_Com + ADS833x_CFR_Reg1;
    Reg_Word2 = ADS833x_Write_Com + ADS833x_CFR_Reg2;

// clear CS1
    GPIO_PinOutClear(gpioPortB,6);
    USART_TxDouble(USART2,Reg_Word1);

// wait until transmission is over
    while (!(USART2->STATUS & USART_STATUS_TXC));
    GPIO_PinOutSet(gpioPortB,6);

    while(GPIO_PinOutGet(gpioPortB,6) != 1);

// the same procedure for CS2
    GPIO_PinOutClear(gpioPortB,0);
    USART_TxDouble(USART2,Reg_Word2);
    while (!(USART2->STATUS & USART_STATUS_TXC));
    GPIO_PinOutSet(gpioPortB,0);

    while(GPIO_PinOutGet(gpioPortB,0) != 1);

// Read out CFR register
    GPIO_PinOutClear(gpioPortB,6),GPIO_PinOutClear(gpioPortB,0);

    USART_TxDouble(USART2,ADS833x_Read_Com);
    while (!(USART2->STATUS & USART_STATUS_TXC));
    ADS833x_Buf[0] = (uint16_t)USART2->RXDOUBLE;

    USART_TxDouble(USART2,ADS833x_Read_Com);
    while (!(USART2->STATUS & USART_STATUS_TXC));
    ADS833x_Buf[1] = (uint16_t)USART2->RXDOUBLE;

    GPIO_PinOutSet(gpioPortB,0),GPIO_PinOutSet(gpioPortB,6);


    ADS833x_Buf[2] = ADS833x_Buf[0] & 0x0FFF;
    ADS833x_Buf[3] = ADS833x_Buf[1] & 0x0FFF;


    if ((ADS833x_CFR_Reg1 != ADS833x_Buf[2])||(ADS833x_CFR_Reg2 != ADS833x_Buf[3])){
        error( );
    }

}

Currently, the readout values of both CFR registers do not correspond to  ADS833x_CFR_Reg1 and ADS833x_CFR_Reg2 which is why my programm ends in the error loop. Therefore, I assume that writing in the CFR register was not succesfully. Are there any solutions for my problem? Thank you!!

Kind regards,

Sebastian

  • Hi Sebastian,

    - Please provide a couple of oscilloscope plot showing the daisy chain frame timing for CS#1, SCLK, SDI, SDO#1 as the device is being configured.  Place the oscilloscope probes in close proximity to the ADC I/O pins.  Is SDI being updated on the rsing edge or falling edge of SCLK?

    - - Please provide an schematic or diagram showing the daisy-chain connections.  Is the MCU reading SDO on the rising or falling SCLK edge?

    Thanks and Regards,

    Luis

  • Hi Luis,

    thanks for your fast reply. Regarding your notes:

    - The attached window shows the results of the logic analyser:

    Channel1: CS#2

    Channel2: CONVST

    Channel3: EOC/INT

    Channel4: SDI

    Channel5: SDO

    Channel6: SCLK

    Channel7: CS#1

    Reference Voltage: 1.65V

    SDI is being updated on rising edge of SCLK

    One cycle:

    Reading CFR:

    -- Schematic diagramm of the daisy-chain connection:

    The MCU is reading SDO on the rising SCLK edge.

    Thanks and Regards,

    Sebastian

  • Ohh, the output images of the logic analyser were not transmitted succesfully (for channel discription see the notes above).

    CFR Configuration and CFR Reading:

    Only reading CFR:

    Additionally my SPI configuration on the MCU (USART2 is the relevant SPI connection):

    void SPI_setup(uint8_t spiNumber, uint8_t location, bool master)
    {
        USART_TypeDef *spi;

        /* Determining USART */
        switch (spiNumber)
        {
        case 0:
            spi = USART0;
            break;
        case 1:
            spi = USART1;
            break;
        case 2:
            spi = USART2;
            break;
        default:
            return;
        }



        /* Setting baudrate */
        spi->CLKDIV = 128 * (SPI_PERCLK_FREQUENCY / 12000000-2);     //SPI2_BAUDRATE - 2);

        /* Configure SPI */
        /* Using synchronous (SPI) mode*/
        spi->CTRL = USART_CTRL_SYNC | USART_CTRL_MSBF;
        /* SPI Mode 0*/
        spi->CTRL |= USART_CTRL_CLKPOL_IDLELOW;
        spi->CTRL |= USART_CTRL_CLKPHA_SAMPLELEADING;
        /* Clearing old transfers/receptions, and disabling interrupts */
        spi->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
        spi->IEN = 0;
        /* Enabling pins and setting location */
        spi->ROUTE = USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_CLKPEN | (location << 8); // removed CLK so that delay can be added to tx func



        /* Set GPIO config to slave */
        GPIO_Mode_TypeDef gpioModeMosi = gpioModeInput;
        GPIO_Mode_TypeDef gpioModeMiso = gpioModePushPull;
        GPIO_Mode_TypeDef gpioModeCs   = gpioModeInput;
        GPIO_Mode_TypeDef gpioModeClk  = gpioModeInput;
        GPIO_Mode_TypeDef gpioModeCs1   = gpioModeInput;
        GPIO_Mode_TypeDef gpioModeCs2   = gpioModeInput;
        GPIO_Mode_TypeDef gpioModeConv   = gpioModeInput;
        GPIO_Mode_TypeDef gpioModeEOC = gpioModePushPull;


        /* Set to master and to control the CS line */
        if (master)
        {
            /* Enabling Master, TX and RX */
            spi->CMD   = USART_CMD_MASTEREN | USART_CMD_TXEN | USART_CMD_RXEN;
            //spi->CTRL |= USART_CTRL_AUTOCS;

            /* Set GPIO config to master */
            gpioModeMosi = gpioModePushPull;
            gpioModeMiso = gpioModeInput;
            gpioModeClk  = gpioModePushPull;
            gpioModeCs1   = gpioModePushPull;
            gpioModeCs2   = gpioModePushPull;
            gpioModeConv   = gpioModePushPull;
            gpioModeEOC = gpioModeInput;
        }
        else
        {
            /* Enabling TX and RX */
            spi->CMD = USART_CMD_TXEN | USART_CMD_RXEN;
        }

        /* Clear previous interrupts */
        spi->IFC = _USART_IFC_MASK;

        /* IO configuration */
        switch(spiNumber)
        {
        case 0: switch(location)
        {
        case 0: /* IO configuration (USART 0, Location #0) */
            GPIO_PinModeSet(gpioPortE, 10, gpioModeMosi, 0); /* MOSI */
            GPIO_PinModeSet(gpioPortE, 11, gpioModeMiso, 0); /* MISO */
            GPIO_PinModeSet(gpioPortE, 13, gpioModeCs,   0); /* CS */
            GPIO_PinModeSet(gpioPortE, 12, gpioModeClk,  0); /* Clock */
            break;
        case 1: /* IO configuration (USART 0, Location #1) */
            GPIO_PinModeSet(gpioPortE, 7, gpioModeMosi, 0);  /* MOSI */
            GPIO_PinModeSet(gpioPortE, 6, gpioModeMiso, 0);  /* MISO */
            GPIO_PinModeSet(gpioPortE, 4, gpioModeCs,   0);  /* CS */
            GPIO_PinModeSet(gpioPortE, 5, gpioModeClk,  0);  /* Clock */
            break;
        case 2: /* IO configuration (USART 0, Location #2) */
            GPIO_PinModeSet(gpioPortC, 11, gpioModeMosi, 0); /* MOSI */
            GPIO_PinModeSet(gpioPortC, 10, gpioModeMiso, 0); /* MISO */
            GPIO_PinModeSet(gpioPortC,  8, gpioModeCs,   0); /* CS */
            GPIO_PinModeSet(gpioPortC,  9, gpioModeClk,  0); /* Clock */
            break;
        default: break;
        }
        break;
        case 1: switch(location)
        {
        case 0: /* IO configuration (USART 1, Location #0) */
            GPIO_PinModeSet(gpioPortC, 0, gpioModeMosi, 0);  /* MOSI */
            GPIO_PinModeSet(gpioPortC, 1, gpioModeMiso, 0);  /* MISO */
            GPIO_PinModeSet(gpioPortB, 8, gpioModeCs,   0);  /* CS */
            GPIO_PinModeSet(gpioPortB, 7, gpioModeClk,  0);  /* Clock */
            break;
        case 1: /* IO configuration (USART 1, Location #1) */
            GPIO_PinModeSet(gpioPortD, 0, gpioModeMosi, 0);  /* MOSI */
            GPIO_PinModeSet(gpioPortD, 1, gpioModeMiso, 0);  /* MISO */
            GPIO_PinModeSet(gpioPortD, 3, gpioModeCs,   0);  /* CS */
            GPIO_PinModeSet(gpioPortD, 2, gpioModeClk,  0);  /* Clock */
            break;
        default: break;
        }
        break;
        case 2: switch(location)
        {
        case 0: /* IO configuration (USART 2, Location #0) */
            GPIO_PinModeSet(gpioPortC, 2, gpioModeMosi, 0);  /* MOSI */
            GPIO_PinModeSet(gpioPortC, 3, gpioModeMiso, 0);  /* MISO */
            GPIO_PinModeSet(gpioPortC, 5, gpioModeCs,   0);  /* CS */
            GPIO_PinModeSet(gpioPortC, 4, gpioModeClk,  0);  /* Clock */
            break;
        case 1: /* IO configuration (USART 2, Location #1) */
            GPIO_PinModeSet(gpioPortB, 3, gpioModeMosi, 0);  /* MOSI */
            GPIO_PinModeSet(gpioPortB, 4, gpioModeMiso, 0);  /* MISO */
            GPIO_PinModeSet(gpioPortB, 6, gpioModeCs1,   0);  /* CS1 */
            GPIO_PinModeSet(gpioPortB, 0, gpioModeCs2,   0);  /* CS2 */
            GPIO_PinModeSet(gpioPortB, 5, gpioModeClk,  0);  /* Clock */
            GPIO_PinModeSet(gpioPortB, 1, gpioModeConv,  0);  /* Conv */
            GPIO_PinModeSet(gpioPortB, 2, gpioModeEOC,  0);  /* EOC */

            GPIO_PinOutSet(gpioPortB, 6);
            GPIO_PinOutSet(gpioPortB, 0);
            GPIO_PinOutSet(gpioPortB,1);
            break;
        default: break;
        }
        break;
        default: break;
        }
    }

  • Hi Sebastian,


    The ADS8332 is able to support SPI settings CPOL=1, CPHA=0 ; however,  one caveat is that the MCU needs to be fast enough to sample SDO within 5ns of the SCLK falling edge.
    When using using CPOL=1, CPHA=0,  the master captures MISO data on SCLK falling edges, and MOSI data is output on falling edge.

    Please see timing diagram below, where tD1 is 5ns minimum:


    It appears, looking at the code and at  plots provided that you are using CPOL=0 CPHA=1. Could you try using CPOL=1, CPHA=0?

    Which MCU are you using?  Can you please confirm the SCLK frequency?

    Please note some MCU's are not fast enough to read SDO within 5ns of the SCLK  falling edge and may require a longer SDO delay time.

    Thanks and Best Regards,

    Luis

    Luis

  • Hi Luis,

    Below you can see the timing diagram of my MCU (EFM32WG380F256):

    Unfortunately I can test using CPOL=1, CPHA=0 not until Tuesday. However, what do you mean with "confirm the SCLK frequency"? The SCLK frequency corresponds to:

    /* Setting baudrate */
        spi->CLKDIV = 128 * (SPI_PERCLK_FREQUENCY / 12000000-2);    

    with SPI_PERCLK_FREQUENCY = 48000000 Hz.

    Thank you und Best Regards,

    Sebastian

  • Hi Sebastian,

    Thank you for the MCU timing information; it appears it should be able to meet ADS8332 timing spec.

    Please change settings to CPOL=1, CPHA=0 and let us know if this resolves the issue. If the issue persist, kindly provide new scope plots with the new settings of SCLK, SDI, SDO, CS, CONVST when writing/reading CFR.

    Thank you and Kind Regards,
    Luis

  • Hi Luis,

    below you can see the timing diagram with the changed settings to CPOL=1, CPHA=0 which does not resolve the issue, although the master captures MISO and MOSI on the SCLK falling edges. Further on I have tested all possible settings without success. I would be very thankful for more input and advices. 

    After the configuration of my CFR register (and skipping the error) I want to read out Channel 1 of adc#1 and adc#2 (on both a sinus signal is connected for testing). The code and time diagrams are provided below. The resultant data are not in accordance with the sinus signal. I would appreciate if you have some advices regarding this issue as well. 

    void startADC(int16_t ADS833x_Result[number_channels][SIZE], int cycle){

        uint16_t LoopCount = 0;    // Count times through idle loop
        uint16_t Channel_Number = 0;

        //uint16_t ADS833x_CFR_Reg1 = 0b011011111101;
        //uint16_t ADS833x_CFR_Reg2 = 0b011011011101;

        for(LoopCount=0;LoopCount<=Channel_Number;LoopCount++)
        {
            
            uint16_t tempBuffer[2];
            for (int i =0; i<2;i++){
                tempBuffer[i]=0;
            }

            TIMER_Enable(TIMER1,false);
            TIMER_CounterSet(TIMER1,0);
            TIMER_Enable(TIMER1,true);
            GPIO_PinOutClear(gpioPortB,1);
            // Timing of minimum 40 ns
            while(TIMER1->CNT<3){
                ;
            }
            TIMER_Enable(TIMER1,false);
            GPIO_PinOutSet(gpioPortB,1);

            while(GPIO_PinOutGet(gpioPortB,1) != 1){
                ;
            }
            ADS833x_ReadRegister(&tempBuffer[0],0b1101<<12);


            ADS833x_Result[LoopCount][cycle] = tempBuffer[0];
            ADS833x_Result[LoopCount+8][cycle] = tempBuffer[1];
        }
        //ADS833x_init(ADS833x_CFR_Reg1,ADS833x_CFR_Reg2);

    }

    void ADS833x_ReadRegister(uint16_t dataBuffer[2], uint16_t command)     // Read CFR register
    {


        GPIO_PinOutClear(gpioPortB,6),GPIO_PinOutClear(gpioPortB,0);

        USART_TxDouble(USART2,command);

        while (!(USART2->STATUS & USART_STATUS_TXBL)){}
        USART_RxDouble(USART2);
        dataBuffer[0] = (uint16_t)USART2->RXDOUBLE;

        USART_TxDouble(USART2,command);

        while (!(USART2->STATUS & USART_STATUS_TXBL)){}
        USART_RxDouble(USART2);
        dataBuffer[0] = (uint16_t)USART2->RXDOUBLE;

        GPIO_PinOutSet(gpioPortB,6), GPIO_PinOutSet(gpioPortB,0);
    }




    void ADS833x_Channel_Select(uint16_t Data, uint16_t cs)
    {
        Data = Data << 12;
        if (cs){
            GPIO_PinOutClear(gpioPortB,0);
            USART_TxDouble(USART2,Data);
            GPIO_PinOutSet(gpioPortB,0);
        }
        else{
            GPIO_PinOutClear(gpioPortB,6);
            USART_TxDouble(USART2,Data);
            GPIO_PinOutSet(gpioPortB,6);
        }
    }

    Reading data:

    Thank you and Kind Regards,

    Sebastian

  • Hi Luis,

    I have cut the line between SDO (adc#1) -> CDI (adc#2) and checked the given voltage on both sides. At the CDI line I have measured a voltage of 3.3V (reference voltage). I assume that the configuration of CFR is not successfully which is why the CDI pin seems to be an output instead of an input and is permanent high. Further on this is also confirmed by the fact that changing D7 or any other bit does not results in alterations in my timing diagram. Below you can see my CFR SDI bits:

    uint16_t ADS833x_CFR_Reg1 = 0b011011111101;
    uint16_t ADS833x_CFR_Reg2 = 0b011011011101;

    However, I think it is a fundamental issue. Differs the electrical wiring in daisy chain modus towards a single ADC with exception of the SPI pins?

    Thank you and Kind Regards,
    Sebastian
  • Hi Sebastian,


    Yes, as you have mentioned, I don't believe the CFR is getting set.  The CDI pin is by default an output indicating EOC,  active low during the conversion period and high when the device is not converting.  This pin will  turn into an input after configuring ADC#2 with CFR D5=0 (Daisy Chain mode). 

    I will setup this configuration in the bench, connecting the devices in Daisy chain mode.  I will provide zoomed-in oscilloscope plots of the two write CFR transactions programming ADC#1 and ADC #2 with the register settings; and then another set of transactions to read the CFR settings.


    Please allow a couple of business days.


    Thank you and Best Regards,

    Luis

  • Hi Luis,

    thank you very much for your support. I am excited about your results.

    Kind Regards,

    Sebastian

  • Hi Luis,

    I have solved the problem. It was up to the number of bits which I have sent over the SPI lines (16 bit instead of 8 bit (with MSB and LSB)). Further on shifting the incoming bits is little bit strange, but it works and I get the right value out of the CFR register.

    void ADS833x_init(uint16_t ADS833x_CFR_Reg1, uint16_t ADS833x_CFR_Reg2) // Initialize ADS833x
    {
    uint16_t Reg_Word1;
    uint16_t Reg_Word2;

    uint16_t ADS833x_Write_Com = 0xE000;
    uint16_t ADS833x_Read_Com = 0xC000;
    uint16_t ADS833x_Buf[BUF_SIZE];
    for (int i =0; i<BUF_SIZE;i++){
    ADS833x_Buf[i]=0;
    }

    Reg_Word1 = ADS833x_Write_Com + ADS833x_CFR_Reg1;
    Reg_Word2 = ADS833x_Write_Com + ADS833x_CFR_Reg2;

    uint16_t Reg_Word1MSB = Reg_Word1 >> 8;
    uint16_t Reg_Word1LSB = Reg_Word1 & 0xFF;
    uint16_t Reg_Word2MSB = Reg_Word2 >> 8;
    uint16_t Reg_Word2LSB = Reg_Word2 & 0xFF;
    uint16_t Read_MSB = ADS833x_Read_Com >> 8;
    uint16_t Read_LSB = ADS833x_Read_Com & 0xFF;


    GPIO_PinOutClear(gpioPortB,6);
    USART_SpiTransfer(USART2,Reg_Word1MSB);
    USART_SpiTransfer(USART2,Reg_Word1LSB);
    GPIO_PinOutSet(gpioPortB,6);

    GPIO_PinOutClear(gpioPortB,0);
    USART_SpiTransfer(USART2,Reg_Word2MSB);
    USART_SpiTransfer(USART2,Reg_Word2LSB);
    GPIO_PinOutSet(gpioPortB,0);


    GPIO_PinOutClear(gpioPortB,6),GPIO_PinOutClear(gpioPortB,0);
    ADS833x_Buf[2] = USART_SpiTransfer(USART2,Read_MSB);
    ADS833x_Buf[3] = USART_SpiTransfer(USART2,Read_LSB);
    ADS833x_Buf[0] = USART_SpiTransfer(USART2,0);
    ADS833x_Buf[1] = USART_SpiTransfer(USART2,0);

    GPIO_PinOutSet(gpioPortB,6),GPIO_PinOutSet(gpioPortB,0);

    ADS833x_Buf[4] = ((ADS833x_Buf[0]<<7)|0x00FF)&((ADS833x_Buf[1]>>1)|0xFF80);
    ADS833x_Buf[5] = ((ADS833x_Buf[2]<<7)|0x00FF)&((ADS833x_Buf[3]>>1)|0xFF80);
    ADS833x_Buf[6] = ADS833x_Buf[4] & 0x0FFF;
    ADS833x_Buf[7] = ADS833x_Buf[5] & 0x0FFF;

    if ((ADS833x_CFR_Reg1 != ADS833x_Buf[6])||(ADS833x_CFR_Reg2 != ADS833x_Buf[7]))error( );

    }

    Thank you and Kind Regards,

    Sebastian
  • HI Sebastian,

    Thank you for the update and letting us know that the problem was resolved.

    Kind Regards,

    Luis