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.

ADS8867: ADS8867 GPIO/SPI mode can not get correct adc value

Part Number: ADS8867
Other Parts Discussed in Thread: ADS8166, ADS8866

Hi,I have some problems when developing with ADS8867.I can not get the correct ADC value in GPIO mode and SPI mode.

1/In GPIO mode.

Solution 1.

GPIO configuration:

DIN:Output Push Pull Mode, Max speed 50M,High

CONVEST:Output Push Pull Mode, Max speed 50M

SCLK:Output Push Pull Mode, Max speed 50M

DOUT:Input Mode,Floating input

void bsp_adc_ads8867_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStructure.Pin = ADC_ADS867_PIN_SCK | ADC_ADS867_PIN_CNV;
    HAL_GPIO_Init(ADC_ADS867_GPIO_PORT, &GPIO_InitStructure);
	
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStructure.Pull = GPIO_PULLDOWN;
    GPIO_InitStructure.Pin = ADC_ADS867_PIN_SDO;
    HAL_GPIO_Init(ADC_ADS867_GPIO_PORT, &GPIO_InitStructure);

    TCNV(0);//CONVEST Low
    TSCK(0);//SCLK Low
}

uint16_t bsp_adc_ads8867_read(void)
{
    uint8_t i;
    uint16_t temp = 0;
    GPIO_InitTypeDef GPIO_InitStructure;

    TCNV(0);//CONVEST Low
    ADC_ADS867_CONV_LOW_DELAY();//CONVEST Low delay about 16ns
    TCNV(1);//CONVEST High and enter a conversion phase.
    ADC_ADS867_CONV_HIGH_DELAY();//CONVEST High delay about 6000ns or 12000ns
    TCNV(0);//CONVEST Low

    for(i=0;i<16;i++)
    {
        temp <<= 1;
        TSCK(1);//SCLK High
        ADC_ADS867_SCLK_HIGH_DELAY();//SCLK High delay 48ns. F(SCLK)< 16MHz.
        TSCK(0);//SCLK Low
		
	if(TSDO==1)//Read DOUT
	{
            temp |= 0x0001;
	}
	ADC_ADS867_SCLK_LOW_DELAY();//SCLK Low delay 48ns.F(SCLK)< 16MHz.
    }	
    return temp;
}

The bsp_adc_ads8867_read() function called in timer 2 isr function,the period of timer 2 is 1ms.

If the CONVEST High delay about 6000ns,I can not get the correct ADC Value,all the ADC value are zero.

If the CONVEST High delay about 12000ns,I can get the correct ADC Value,but the ADC value is zero sometimes.

I view the timing diagram on the oscilloscope,It seems only the falling edge of SCLK,the data is vaild and start output.

So I change the code as below,but still can not solve the problem.

Solution 2.

uint16_t bsp_adc_ads8867_read(void)
{
    uint8_t i;
    uint16_t temp = 0;
	
    TCNV(0);//CONVST Low
    ADC_ADS867_CONV_LOW_DELAY();//CONVST Low delay about 16ns
    TCNV(1);//CONVST High
    ADC_ADS867_CONV_HIGH_DELAY();//CONVST High delay about 12000ns
	
    /***** Falling for data start output******/
    TSCK(1);//SCLK High
    ADC_ADS867_SCLK_HIGH_DELAY();//SCLK High delay about 48ns.f(SCLK) < 16MHz.
   /***** Falling for data start output******/

    TCNV(0);//SCLK Low 
    ADC_ADS867_CONV_LOW_DELAY();//SCLK Low about 48ns. f(SCLK) < 16MHz.
	
    /***** Falling for data start output******/
    TSCK(0);
    ADC_ADS867_SCLK_LOW_DELAY();
    /***** Falling for data start output******/
	
    for(i=0;i<16;i++)
    {
	temp <<= 1;	
	TSCK(1);//SCLK Low
	if(TSDO==1)//Read DOUT
	{
	    temp |= 0x0001;
	}
	ADC_ADS867_SCLK_HIGH_DELAY();//SCLK High delay about 48ns.f(SCLK) < 16MHz.	
	TSCK(0);//SCLK Low
        ADC_ADS867_SCLK_LOW_DELAY();//SCLK Low delay about 48ns.f(SCLK) < 16MHz.
    }
    return temp;
}

This solution I can get the correct ADC Value,but the ADC value is zero sometimes.

I wonder if I miss anything in GPIO mode?

2/SPI Mode

static void MX_SPI2_Init(void)
{
    /* SPI1 parameter configuration*/
    hspi2.Instance = SPI2;
    hspi2.Init.Mode = SPI_MODE_MASTER;
    hspi2.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
    hspi2.Init.DataSize = SPI_DATASIZE_16BIT;
    //hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
    hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
    //hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
    //hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
    hspi2.Init.NSS = SPI_NSS_SOFT;
    //hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
    hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;//SPI = 8M
    hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
    hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi2.Init.CRCPolynomial = 7;
    if (HAL_SPI_Init(&hspi2) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }
}

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  
  #if 1//FOR_AD_SPI
  if(hspi->Instance==SPI2)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI2_CLK_ENABLE();
  
    /**SPI2 GPIO Configuration    
    PB12     ------> SPI2_NSS
    PB13     ------> SPI2_SCK
    PB14     ------> SPI2_MISO
    PB15     ------> SPI2_MOSI 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_15;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_14;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN SPI1_MspInit 1 */

  /* USER CODE END SPI1_MspInit 1 */
  }
  #endif

}
void bsp_adc_ads8867_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStructure.Pin =  ADC_ADS867_PIN_CNV | ADC_ADS867_PIN_DIN;
    HAL_GPIO_Init(ADC_ADS867_GPIO_PORT, &GPIO_InitStructure);

    TCNV(0);
    TDIN(1);
}

uint16_t bsp_adc_ads8867_read(void)
{
    uint8_t i;
    uint16_t temp = 0;
    GPIO_InitTypeDef GPIO_InitStructure;

	
   HAL_StatusTypeDef err_code = HAL_OK;
   uint8_t data[2];

   TCNV(0);
   ADC_ADS867_CONV_LOW_DELAY();
   TCNV(1);
   ADC_ADS867_CONV_HIGH_DELAY();
   TCNV(0);

   err_code = HAL_SPI_Receive(&hspi2, data, 1, 1000);//SPI receive
   if(err_code != HAL_OK)
   {
        DEBUG_BY_LUOGF_PRINTF(0,"[%d][%s][err_code = %d]\r\n",__LINE__,__FUNCTION__,err_code);
   }
   temp = (uint16_t)((data[0]<<8)|(data[1]<<0));
   return temp;
}

The bsp_adc_ads8867_read() function called in timer 2 isr function,the period of timer 2 is 1ms.

In SPI mode 0 and SPI mode 3, the ADC Value is not correct and ADC value is not equal to zero.

I wonder if I miss anything in SPI mode?

Best regards.

  • Hello,

    Welcome to the TI e2e Community.

    Which mode are you operating the device in; 3-wire or 4-wire?  Looking through your code, it appears that you are operating in 3-wire /CS mode; is DIN permanently held HIGH?

    You should duplicate the waveforms shown in Figure 46 of the datasheet.  The Conversion starts on the rising edge of CONVST.  After this rising edge, with CONVST high, you need to wait for the conversion to complete, t-conv-max= 8800nS.  After this delay, you can pull CONVST low and then clock the data out of the device.  The ADS8166 launches D15 on the falling edge of CONVST and the rest of the bits on the falling edge of SCLK.  If you capture (read) data on the falling edge of SCLK, the ADC will hold the current value for 3nS minimum.

    Please send a scope picture of the 4 waveforms, CONVST, DIN, SCLK, and DOUT showing a full transfer frame.  I will take a look at it to see if everything is correct.

    Regards,
    Keith Nicholas
    Precision ADC Applications

  • Hello,

    Keith Nicholas.

    1/GPIO mode.

    The DIN is high at GPIO mode, 3-wire /CS mode.

    CONVEST:green

    SCLK:yellow

    DOUT:blue

    picture1.f(sample) = 30kHz<100Khz

    pictrue2.f(SCLK) <16MHz

    pictrue3.D15 detail.

    In GPIO mode, if i read the D15 after the falling edge delay 16ns, the D15 always be 0(the sampling voltage can guarantee the MSB is 1),the D14~D0 is ok.

    In gpio mode soultion 1,I read adc data on the falling edge of SCLK(16 SCLK in total).

    In gpio mode soultion 2,I design a falling edge and read adc on the rising edge of SCLK(17 SCLK in total). 

    Both soultion 1 and soultion 2 can read the correct adc value(except sometimes the adc value is zero,D15~D0 are 0).that is the reason  i think only the falling edge of SCLK,the data is vaild and start output(can be captrued).That is different from what the data sheet said.

    I am not sure if i am right?

    The adc data always be 0 sometimes ,keep 0 in next sampling.and only can be solved by power off, so i think the power causes that problem.we can reproduce the problem when the power is low voltage.

    2/SPI mode

    I can not get the correct adc value in spi mode 0 and mode 3.

    The different between spi mode 3 and gpio mode solution 2 is that the default SCLK voltage is high in spi mode 3,but the default SCLK voltage is low in gpio mode solution 2.

    picture 4,f(sampling) = 60KHz <100KHz

    pictrue 5. f(SCLK) = 8MHz < 16Mhz

    picture 6.D15 detail.

    If i miss anything in spi mode? I will use spi mode in release version of firmware.Thanks for your attention.

    Thanks.

  • Hello,

    The waveforms look correct for 3-wire /CS mode.  In picture 3, you can see that the MSB data is launched on the falling edge of CONVST, going from a hi-Z state to a low (0).  Also, picture 3 shows that the ADC launches the other data on the falling edge of SCLK.

    Picture 4 confirms that CONVST is high for 12uS, which is greater than the minimum required time of 8.8uS.  Also, as long as you delay more than 12.3nS after CONVST falling edge, then the MSB data bit will be valid.

    You can use the falling edge of SCLK to capture data as long as the setup and hold times are met by your MCU.  The current data bit will remain valid for 3nS after the falling edge of SCLK, and the next data bit will be valid 13.4nS after the SCLK falling edge.

    For your SPI mode, the SCLK can idle high and you can capture data on the falling edge of SCLK as long as the hold time of 3nS meets your MCU requirements.

    Regarding the device locking up and reading all zeros, this is likely due to an electrical overstress event, where the ABS Max specs have been exceeded.  This could be an overvoltage on the power supply pins, the reference pins, or any of the digital or analog inputs.  If the voltage causes more than 10mA of current to flow, then the device could be permanently damaged.  If less than 10mA flows, then typically a power cycle will correct the problem and return the ADC to normal operation.

    If you can send me a schematic showing the input amplifier, reference, ADS8867 and power connections, I will take a look to see if there is anything that could explain the device lock up.

    Regards,
    Keith

  • Hello,Keith.

    Thanks for your attention.

    I made a mistake on the data format.In ADS8867 data sheet page 15, it says the device output is in twos compliment format.

    The ADS8867 DOUT output data is signed 16 bits, in my hardware design ,the AINP pin connect to sampling voltage, the AINN pin connect to GND, so the MSB is 0.As you and data sheet said,It works well in GPIO mode and spi mode 0 now.

    If the AINN = 0V and the AINP = sampling voltage, the adc value is between 0 and 32767, so i only use 15 bits to sampling voltage. If i want use 16 bits to sampling voltage, how to design?

    picture 1, The hardware design for ads8867.

    The VREF = 4.096V, the AVDD and DVDD connect to the 3.3V net.The AINP can not be more than the VREF in normal situation, and i will design voltage limit for AINP in next version to protect the ads8867.

    For all the ads8867 adc value is 0 in my situation, it seems not the over voltage of the input signal cause the problem.I want to know if the unstable voltage of AVDD and DVDD or low voltage can cause the problem?

    Thanks for your attention.

  • Hello,

    I am glad you are now getting correct readings from the device!

    In order to get the full 16b, you will need to add a single ended to differential driver.  The following Analog Engineer's circuit shows how to do this.  Since you are using VREF=4.096V, you will want the Vcm voltage in the below drawing to be 2.048V, or 1/2*VREF.  An input voltage of 0V will result in a negative full scale reading, or -32768d.  An input voltage of 2.048V will result  in a 0 reading, and 4.096V will be 32767d.

    http://www.ti.com/lit/an/sbaa265/sbaa265.pdf

    Regarding the lock-up of the device, if AVDD or DVDD exceed the ABS Max spec, then this certainly could cause the device to stop working.  If the voltage drops below 2.7V, but not all the way to 0V, it could cause the internal reset to not work correctly.  In this case, you would need to do a full power cycle where AVDD and DVDD fall all the way to 0V, and then power back up.

    Since you want a single ended input, you may want to consider the ADS8866.  It is pin to pin and supports a single ended input.

    Regards,
    Keith

  • Hello,

    Thanks for your attention,I will try to use ADS8866 if i the 15 bits resolution is not fit my design.