使用 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 上的内部参考电压测量模拟值的主要内容,如果未能解决你的问题,请参考以下文章
STM32Cube STM32L053配置GPIO达到最低功耗详解含测量实际电流值