Author Topic: STM32G4 Voltage reference problem  (Read 2809 times)

0 Members and 1 Guest are viewing this topic.

Offline syntax333Topic starter

  • Regular Contributor
  • *
  • Posts: 158
  • Country: 00
STM32G4 Voltage reference problem
« on: March 30, 2020, 09:22:45 am »
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.

Code: [Select]

#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...
 

Offline AlexD

  • Newbie
  • Posts: 3
  • Country: at
Re: STM32G4 Voltage reference problem
« Reply #1 on: April 02, 2020, 03:50:38 pm »
Hi,
I believe this is, because the VREFBUF cannot be used on that specific chip. The Datasheet (not the Reference manual) says: "The VREF+ pin is double-bonded with VDDA on some packages. In these packages the
internal voltage reference buffer is not available.". That would mean, there is no analog switch for the reference voltage that selects between the VREFBUF and an VDDA as the reference.
I'm not 100% sure about that, because the peripheral table in the Datasheet says the K devices (32pin LQFP packages) do have a voltage reference buffer. But since that chip has no VREF+ Pin, it has to be bonded to VDDA internally.
 
The following users thanked this post: syntax333


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf