2023-08-03 04:20 PM
The issue I am having is as follows on the STM32G051C8T6. We are using the internal RTC with Vbat pin. On this MCU Vbat can be internally configured to be read by the ADC by diving by 3 Bridge. We have ADC Setup, I am making sure we perform the ADC Calibration before performing any conversions and I get ADC Values of either 4095 or 2047 with no in between. Even with the Vbat pin pulled low to ground or floating we get a reading of 2047. I have played around with setting the sample times slower as well with no change.
Below is function used to initialize ADC
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
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.LowPowerAutoPowerOff = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
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.SamplingTimeCommon1 = ADC_SAMPLETIME_79CYCLES_5;
hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_12CYCLES_5;
hadc1.Init.OversamplingMode = DISABLE;
hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_VBAT;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
And my Polling Code
curMsCnt=HAL_GetTick();
if(curMsCnt - prevMSCount > 5000){
prevMSCount = curMsCnt;
ADC-> CCR |= ADC_CCR_VBATEN;
HAL_ADC_Start(&hadc1);
// Start ADC conversion
if (HAL_ADC_PollForConversion(&hadc1, 1000) == HAL_OK) // Wait for conversion to complete
{
adcValue = HAL_ADC_GetValue(&hadc1); // Read ADC value
// Calculate voltage from ADC value
VbatVoltage = ((float)adcValue / 4095.0) * 3.0 * 1000;
// Do something with the voltage value
}
HAL_Delay(500);
ADC-> CCR &= ~ADC_CCR_VBATEN;
HAL_ADC_Stop(&hadc1);
}
2023-08-04 02:37 AM
When you measure the Vref or internal temperature sensor values, are the values correct? This will verify that the ADC is working.
2023-08-04 08:27 AM
We have tried measuring on all the other external ADC Channels as well and they are not reading properly either
2023-08-04 09:16 AM - edited 2023-08-04 09:17 AM
Read out and check/post content of ADC registers.
Are all VDD/VSS pins connected, including VDDA/VSSA? What's the *measured* voltage on VDDA and VREF+ pins (if there's a separete VREF+ on the package you are using)?
What hardware are you using? If it's your own board, you may want to try first on a "known good" board such as Nucleo or Disco.
JW
2023-08-04 09:55 AM
Hi VDD/VDDA and VSS/VSSA are connected and this is our own Board. My hardware guy did not connect Pin 5 which is VRef +. Is this required or can we use the internal Voltage Reference on this package?
2023-08-04 10:40 AM
Actually now I connected VRef to Vdd and I get an accurate reading with the battery in. However with no battery I read about 600mV on the low end and no lower even though I am performing the calibration. Confirmed there is no voltage on the pin in the floating state. Any tips on how to fix this last bit?
Thanks,
2023-08-04 11:24 AM
>. My hardware guy did not connect Pin 5 which is VRef +. Is this required or can we use the internal Voltage Reference on this package?
You can use the internal voltage reference, see VREFBUF chapter in RM. However, even that requires to have VREF+ connected, in this case to a quite specific capacitor combination, see Datasheet.
JW
2023-08-07 10:34 AM
VbatVoltage = ((float)adcValue / 4095.0) * 3.0 * 1000;
First, the divisor must be by 4096. Second, the 4095.0 and 3.0 constants are of a double type and all the processing is done with a double type. Use the f suffix, for the constants to be of a float type.