cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G4 Voltage reference problem

LLOLO.1
Associate II

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 5
LLOLO.1
Associate II

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

Imen.D
ST Employee

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".
Thanks
Imen
LLOLO.1
Associate II

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
Associate II

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

Imen.D
ST Employee

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".
Thanks
Imen