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

Posted

技术标签:

【中文标题】使用 STM32L422 上的内部参考电压测量模拟值【英文标题】:Measure analog value using Internal reference voltage on STM32L422 【发布时间】:2021-12-28 08:57:55 【问题描述】:

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

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 */


【问题讨论】:

【参考方案1】:

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

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

STM32L422 数据表说内部 Vref = 1.2 V

不要只阅读数据表参考手册

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

【讨论】:

我对 VREFINT_CAL 和 VREFINT_DATA 感到困惑。我在想 VREFINT_CAL 是来自 VREFINT 寄存器( 0x1FFF75AA -0x1FFF75AB )的值。如何获取 VREFINT_DATA。你能简单解释一下这个过程吗? 你需要测量它。 Vrefint 只是普通的 ADC 通道 需要使用 Vrefint 计算 VDDA。为此,我没有设置 ADCx_CCR 的 VREFEN 位。我已经检查了 CubeMX 中的 Vrefint 通道,它一定已经完成了这项工作!。我将通道设置为 ADC_CHANNEL_VREFINT,然后将电压连接到 Vref 引脚。

以上是关于使用 STM32L422 上的内部参考电压测量模拟值的主要内容,如果未能解决你的问题,请参考以下文章

STM32L476应用开发之二:模拟量数据采集

STM32ADC模数转换

STM32Cube STM32L053配置GPIO达到最低功耗详解含测量实际电流值

STM32Cube STM32L053配置GPIO达到最低功耗详解含测量实际电流值

STM32L1xx——ADC(中断/DMA)样例代码

STM32 ADC学习