0

I have to measure adc value using internal reference voltage in STM32L422. According to datasheet STM32L422 internal reference voltage is 1.2 V. I enabled internal Vref from CubeMX. Analog input is 1V but I get 0.58 V. what is the problem here anyone ?

STM32L422 datasheet says that internal Vref = 1.2 V. When I measured Vref pin, it was 0.53 V. What is wrong over here ?

For 1 V input which is obtained using 20K, 10K voltage divider, for 3V, digital and analog values obtained are are follows: Digital: 1983, Analog value: 0.581099

#define VREFINT_ADDR      0x1FFF75AA      // VREF voltage
#define VREFINT         (*((uint16_t *) VREFINT_ADDR))

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_SPI1_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  MX_TIM6_Init();
  MX_RTC_Init();

  /* USER CODE BEGIN 2 */

  printf("System Booting On! \n");

  printf("VREFINT: %ud\n", VREFINT);
  printf("ADC Calibration! \n");
  while(HAL_ADCEx_Calibration_Start(&hadc1,0) != HAL_OK);

  printf("Battery Voltage Check ...\n");

  HAL_Delay(100);   // 1000ms OK => 100ms OK
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1,100);
  ADC_Val=HAL_ADC_GetValue(&hadc1);
  HAL_ADC_Stop(&hadc1);
  
  float Result = (float)((1.200 * ADC_Val) / 4095);

  printf("****************************************************************\n");
  printf("Digital: %d, Analog value : %f\r\n", ADC_Val, Result);
  printf("****************************************************************\n");
    
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    ;     
  }
  /* USER CODE END 3 */
}

void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV8;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure the ADC multi-mode
  */
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_12;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_92CYCLES_5;
//    sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

enter image description here

enter image description here

1 Answer 1

2

STM32 ADC works a bit different way than you think and the Vrefint name is a bit confusing. Always read the Reference Manual.

Vrefint is not the reference voltage for ADC. It is simply connected one of the channels. When you measure this voltage you can know your Vref for ADC (in your case it is Vdda) So the formula you use is wrong.

STM32L422 datasheet says that internal Vref = 1.2 V

Do not read the datasheet only Reference Manual

enter image description here

Then you need to measure your Vref (Vdda) and rthen you can measure your voltage on the pin.

enter image description here

Sign up to request clarification or add additional context in comments.

3 Comments

I am confused on VREFINT_CAL and VREFINT_DATA. I am thinking that VREFINT_CAL is the value from VREFINT register ( 0x1FFF75AA -0x1FFF75AB ). How can I acquire VREFINT_DATA. Could you explain me the process in short ?
You need to measure it. Vrefint is just normal ADC channel
Using Vrefint to calculate VDDA is what is needed. To do that, I did not set the VREFEN bit of ADCx_CCR. I had checked the Vrefint channel in CubeMX which must have done the job !. And I set the channel to ADC_CHANNEL_VREFINT and I got the voltage connected to Vref pin.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.