2020-03-30 01:20 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.
#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...
2020-03-30 05:21 AM
I realized even though STM32G431KB data sheet says it has VREF buffer inside, there is no option/menu for selecting VREFBUF in STM32CubeIDE.
2020-03-30 02:42 PM
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 ?
Best Regards,
Imen
2020-03-30 11:15 PM
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.
2020-03-30 11:16 PM
Yes, I do not have the option VREFBUF Mode like you show in screenshot.
2020-03-31 02:07 AM
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