sujan_014
sujan_014

Reputation: 536

Measure analog value using Internal reference voltage on STM32L422

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

Upvotes: 0

Views: 5756

Answers (1)

0___________
0___________

Reputation: 67602

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

Upvotes: 2

Related Questions