使用 STM32L422 上的内部参考电压测量模拟值

Measure analog value using Internal reference voltage on STM32L422

我必须使用 STM32L422 中的内部参考电压测量 adc 值。根据数据表 STM32L422 内部参考电压为 1.2 V。我启用了 CubeMX 的内部 Vref。 模拟输入是 1V,但我得到 0.58V。这里有什么问题吗?

STM32L422 数据表说内部 Vref = 1.2 V。当我测量 Vref 引脚时,它是 0.53 V。 这里有什么问题吗?

对于1V输入,使用20K、10K分压器得到,对于3V,得到的数字和模拟值如下: 数字:1983,模拟值: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 */

}

STM32 ADC 的工作方式与您想象的有点不同,Vrefint 名称有点令人困惑。始终阅读 参考手册

Vrefint 不是 ADC 的参考电压。它只是连接其中一个通道。当你测量这个电压时,你可以知道你的 ADC 的 Vref(在你的情况下它是 Vdda)所以你使用的公式是错误的。

STM32L422 datasheet says that internal Vref = 1.2 V

不看数据表,只看参考手册

然后您需要测量您的 Vref (Vdda),然后您可以测量引脚上的电压。