使用 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),然后您可以测量引脚上的电压。
我必须使用 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),然后您可以测量引脚上的电压。