cancel
Showing results for 
Search instead for 
Did you mean: 

Polling ADC on STM32F777IIK

Nevyn
Associate II

I'm having problems getting an ADC value from the STM32F777IIK chip we have embedded in one of our boards.

I have used a digital GPIO application and have confirmed that the ADC pin (PC0) is connected from the chip to the headers that is good.

I have use STM32Cube to generate a simple makefile application that reads the values from the ADC and then outputs the value read on one of the UARTs.

The ADC initialisation looks like this:

hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
  Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_10;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
  Error_Handler();
}

The code that reads the ADC is:

uint16_t uhADCxConvertedValue = 0;
if (HAL_ADC_Start(&hadc1) != HAL_OK)
{
  Error_Handler();
}
if (HAL_ADC_PollForConversion(&hadc1, 10) != HAL_OK)
{
  Error_Handler();
}
else
{
  uhADCxConvertedValue = HAL_ADC_GetValue(&hadc1);
}

I have a potentiometer connected to a 3.3V supply and the voltage is ready 2.04V (RMS) on the scope and when this is connected to the board I always get a reading of 3.29V (4095) on the ADC.

Interestingly, when I disconnect the pin from the voltage source I get a returned value of 1.64V (2047).

I have also tried 5 other ADCs on this chip and I am getting the same results.

I would appreciate it if someone could help me resolve this problem.

Thanks in advance,

Mark

7 REPLIES 7
Nevyn
Associate II

So a little update on where I currently am (basically still stuck).

After firming up one of the connections (3.3V to Vref), I am still not getting what I would expect as a correct value but I am getting either 0 or 4095 returned for the ADC reading. I currently have a potentiometer setup on breadboard and I am feeding 1.76V into PC0 and I would expect an ADC reading somewhere around 2048, instead I am getting 4095.

I have also tried a simple voltage divider using two 470R resistors and a capacitor connecting the analog input to ground as suggested by our EE.

I have combed the datasheet and I am sure that the clocks are within specification and I am using software triggered conversions performing one every 1s so speed should not be a problem.

Someone suggested to me that the system maybe set up as a comparator. The closest I can see to comparators being mentioned is the lower and upper thresholds. I have checked the registers in STM32CubeIDE and the threshold comparison is not enabled. So I think we can rule this out.

I have also tried 480 cycles for the conversion, this did not help.

Regards,

Mark

asbjorn.heid
Associate III

FWIW I tried your main code on my STM32F103, polling VREFINT, and got sensible results (1492, so 1.202).

Here's my setup code, generated by CubeMX

static void MX_ADC1_Init(void)
{
 
  /* USER CODE BEGIN ADC1_Init 0 */
 
  /* USER CODE END ADC1_Init 0 */
 
  ADC_ChannelConfTypeDef sConfig = {0};
 
  /* USER CODE BEGIN ADC1_Init 1 */
 
  /* USER CODE END ADC1_Init 1 */
  /** Common config 
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel 
  */
  sConfig.Channel = ADC_CHANNEL_VREFINT;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */
 
  /* USER CODE END ADC1_Init 2 */
 
}

And here's the main code:

  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
    volatile uint16_t uhADCxConvertedValue = 0;
    if (HAL_ADC_Start(&hadc1) != HAL_OK)
    {
      Error_Handler();
    }
    if (HAL_ADC_PollForConversion(&hadc1, 10) != HAL_OK)
    {
      Error_Handler();
    }
    else
    {
      uhADCxConvertedValue = HAL_ADC_GetValue(&hadc1);
    }
 
    HAL_Delay(500);
 
  }
  /* USER CODE END 3 */

I just watched the value in the debugger, didn't print to UART.

Nevyn
Associate II

Thank you for trying this out.

I have also tried a similar example on a Nucleo-767ZI board and I have managed to get this working on that, just not on a board with the 777II chip.

Today I have tried to make the clock settings match the settings on the Nucleo board and I have the chip using a HSE running at 25MHz and have modified the clock settings to bring the peripheral clocks in at 96MHz and 48MHz so the two boards match.

I think I have run out of software things to try. I have even stepped through some of the HAL code to see what it is doing and I think it looks good.

Thanks you once again for your time, I appreciate it.

Regards,

Mark

asbjorn.heid
Associate III

Unfortunately I don't have any F777 boards.

I think what I'd do next is use the Vrefint channel just to eliminate any GPIO pin issues, try using async clock rather than sync, and try using interrupt mode and manually read the results in the interrupt handler. Aka grasping at straws...

YAkse
Associate III

I did not read all the parts but when I use,

hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

I was not able to take consecutive readings(still dont know why), maybe your problem also occurs because of that. Try changing it to end of sequences one.

p.s : your problem looks different but I wanted to mention anyway

Nevyn
Associate II

We removed all external circuitry and switched to the internal reference voltage last night for exactly the reasons you mentioned. We wanted to remove the possibility of anything odd outside of the board itself from interfering.

I have the while loop starting the ADC, polling, getting the value and then stopping the ADC. This works with consecutive readings (well, it returns HAL_OK for the status of the HAL calls. I get 0V for every reading 🙂

Regards,

Mark

Nevyn
Associate II

Looks like we had a hardware design problem.

Currently waiting for some new boards from the fab house.

Thanks for all who looked at this and tried to help.

Regards,

Mark