Skip to main content
LLOLO.1
Associate III
March 30, 2020
Question

STM32G4 Voltage reference problem

  • March 30, 2020
  • 5 replies
  • 2643 views

Hi I am currently working on a project where I need to use internal Voltage reference as reference for ADCs inside STM32G4 Nucleo board (STM32G431KB). I can write to bits of VREFBUF registes (Confirmed by Debug Session). After enabling the VREF I wait for VRR bit of CSR register to set. However, it never does thus my code stucks in while loop.

You can see the code below.

#include "main.h"
#include "SysClock_Config.h"
 
 
void DummyDelay(int x)
{
	int temp = x;
	while(temp)
	{
		temp--;
	}
}
 
void Initialization(void)
{
 
	RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN | RCC_AHB2ENR_ADC12EN; //Enable GPIOA and ADC Clock
 
	GPIOA->MODER |= GPIO_MODER_MODER0; //Set PA0 as Analog
 
	VREFBUF->CSR |= (0b01<<VREFBUF_CSR_VRS_Pos); //Set Internal Reference as 2.5V
	VREFBUF->CSR &= ~(VREFBUF_CSR_HIZ); //Disable High-Impedance
	VREFBUF->CSR |= VREFBUF_CSR_ENVR; //Enable Voltage reference
	while(!(VREFBUF->CSR & VREFBUF_CSR_VRR)); //Wait until Reference Voltage Level is reached.
 
	ADC1->CR &= ~(ADC_CR_ADEN); //Disable ADC
	ADC12_COMMON->CCR |= (0b00<<ADC_CCR_CKMODE_Pos); //Select ADC clock Source in Peripheral
	ADC1->CR &= ~(ADC_CR_DEEPPWD); //Disable ADC Deep-Power-Down mode
	ADC1->CR |= ADC_CR_ADVREGEN; //Enable ADC Voltage Regulator
	DummyDelay(10000);
 
	ADC1->CFGR |= ADC_CFGR_CONT; //ADC continuous mode
	ADC1->CFGR &= ~(ADC_CFGR_RES); //12-bit ADC
	ADC1->SQR1 |= (0b0000 << ADC_SQR1_L_Pos) | (1 << ADC_SQR1_SQ1_Pos); // Only 1 conversion for ADC channel 1
	ADC1->DIFSEL &= ~(ADC_DIFSEL_DIFSEL_0); //Single Ended Input
	ADC1->CFGR |= ADC_CFGR_OVRMOD; //Enable Overrun mode *MIGHT NOT BE NECESSARY*
 
	ADC1->CR &= ~(ADC_CR_ADCALDIF); //Single Ended Mode Calibration
	ADC1->CR |= ADC_CR_ADCAL; //Start Calibration
	while(ADC1->CR & ADC_CR_ADCAL); //Wait Until Calibration Complete
 
	ADC1->ISR |= ADC_ISR_ADRDY; //Clear ADRDY Flag
	ADC1->CR |= ADC_CR_ADEN; //Enable ADC
	while(!(ADC1->ISR & ADC_ISR_ADRDY)); //Wait Until ADC Enables
 
 
}
 
 
 
 
int main(void)
{
 
 uint16_t ADC_Value;
 
 HAL_Init();
 SystemClock_Config();
 
 Initialization();
 
 ADC1->CR |= ADC_CR_ADSTART; //Start ADC Sampling/Conversion Sequence
 
 while (1)
 {
	 while(!(ADC1->ISR & ADC_ISR_EOC)); //Wait for End of Conversion
	 ADC_Value = ADC1->DR; //Save data to variable
 }
 
}
 
void Error_Handler(void)
{
 
}
 
void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
 
 /** Configure the main internal regulator output voltage
 */
 HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
 /** Initializes the CPU, AHB and APB busses clocks
 */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
 RCC_OscInitStruct.HSEState = RCC_HSE_ON;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
 RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4;
 RCC_OscInitStruct.PLL.PLLN = 50;
 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV5;
 RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
 RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 Error_Handler();
 }
 /** Initializes the CPU, AHB and APB busses clocks
 */
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
 |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)
 {
 Error_Handler();
 }
 /** Initializes the peripherals clocks
 */
 PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12;
 PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_PLL;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
 {
 Error_Handler();
 }
 
 
 SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk);
 
}

Do anyone knows the reason for this? I checked clocks and Voltage levels of VDD and AVDD pins, everything seems fine...

5 replies

LLOLO.1
LLOLO.1Author
Associate III
March 30, 2020

I realized even though STM32G431KB data sheet says it has VREF buffer inside, there is no option/menu for selecting VREFBUF in STM32CubeIDE.

Technical Moderator
March 30, 2020

Hello,

Please share your ioc file for check and precise which version of CubeMX/CubeIDE are you using.

Do you mean that you do not have the "VREFBUF mode" option as mentioned in the screenshot ?

0693W000000V1M5QAK.jpg

Best Regards,

Imen

"When your question is answered, please close this topic by clicking ""Accept as Solution"".ThanksImen"
LLOLO.1
LLOLO.1Author
Associate III
March 31, 2020

My version is 1.3.0 and Build: 5720_20200220_1053. Datasheet says that it does not have dedicated Vref+ pin in my package (32 pin) which is smallest. It is probably due to this. If I try larger package like 48 pin it has the VREFBUF option.

LLOLO.1
LLOLO.1Author
Associate III
March 31, 2020

Yes, I do not have the option VREFBUF Mode like you show in screenshot.

Technical Moderator
March 31, 2020

In fact, when the VREF+ pin is double-bonded with VDDA pin in a package, the voltage reference buffer is not available and must be kept disabled0693W000000V3NUQA0.png

"When your question is answered, please close this topic by clicking ""Accept as Solution"".ThanksImen"
swal
Associate
January 13, 2025

(Old thread, I know ;)


@Imen.D wrote:

In fact, when the VREF+ pin is double-bonded with VDDA pin in a package, the voltage reference buffer is not available and must be kept disabled


Does that mean VREF may not be used internally as well?

I want to use VREF as a reference with analog comparators on an STM32G431KBU3.

 

In CubeMX v6.13.0, there is no option to select VREF voltage:

swal_2-1736775207994.png

 

but there are options to select (fractions of) VRef with the comparators:

swal_1-1736775096749.png

 

Is it supposed to work (it does compile and link), when VREF is configured and enables using the HAL functions:

HAL_StatusTypeDef HAL_SYSCFG_EnableVREFBUF(void);
void HAL_SYSCFG_VREFBUF_VoltageScalingConfig(uint32_t VoltageScaling);?

 

Thanks

Stefan