2023-08-08 11:07 PM
Hello,
I am using STM32G041C8T6 controller and I am facing an issue with ADC even for a simplest conversion on ADC Channel 0. I am providing 2.12V on the Channel 0 (PA0) pin and the conversion result is always 4095. The signal comes from a voltage divider, tapped from the mid point of two 10K resistors put between 5V and GND. Infact the resistor towards the ground is a 10K NTC temperature sensor, so at 25*C the voltage is exactly 2.5V, and decreses with increasing temperature. I'm not using any DMA, interrupts, just polling as per the reference code for G0 series.
I am following the simplest conversion of 1 channel with the following initialization from CubeIDE:
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
/** 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 = ENABLE;
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_OVERWRITTEN;
hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_39CYCLES_5;
hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_39CYCLES_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_0;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
The main contains:
#define VDDA_APPLI 3300
uint16_t temp_val_adc;
uint16_t adc_converted_data[4];
/* Run the ADC calibration */
if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK)
{
/* Calibration Error */
while(1);
}
/* Start ADC conversion */
if (HAL_ADC_Start(&hadc1) != HAL_OK)
{
/* ADC conversion start error */
while(1);
}
/* Wait for the first ADC conversion to be completed (timeout unit: ms) */
if (HAL_ADC_PollForConversion(&hadc1, 2) != HAL_OK)
{
/* ADC conversion start error */
while(1);
}
while(1)
{
adc_converted_data[0] = HAL_ADC_GetValue(&hadc1); //adc_converted_data[0] always 4095.
/* Compute the voltage */
temp_val_adc = __LL_ADC_CALC_DATA_TO_VOLTAGE(VDDA_APPLI, adc_converted_data[0], hadc1.Init.Resolution );
HAL_Delay(500);
LED_RED_TOGGLE;
}
The APB is running on 16MHz (HCLK), SYSCLK is 64MHz. I have observed the same behavior on more than one board. Can anyone suggest what I'm missing, this code ran perfectly on F4 Disco boards, but now I'm baffled by it.
Thanks in advance for any support.
-Regards,
Munish
Solved! Go to Solution.
2023-08-09 03:35 AM
Are you using a 48 pin case? If so, the Vref+ pin must be connected to an external reference voltage or to VDDA.
2023-08-09 03:12 AM
Hello @munish4u911ex ,
Could you clarify what do you mean by "I have observed the same behavior on more than one board"? Is there any board the conversion give an expected result?
Best Regards,
Gwénolé
2023-08-09 03:35 AM
Are you using a 48 pin case? If so, the Vref+ pin must be connected to an external reference voltage or to VDDA.
2023-08-09 06:53 AM
Hello Gwénolé,
Thanks for your reply. I'm having 3 identical boards and problem is seen on two of them, although on third one, ADC result was as expected on the 1st channel but selecting another channel gave a value too low for the given voltage of 1.2V. Also the measured and converted temperature value was around 10 times of 25 degC. I tried lowering the clock frequency and increasing sampling time so that it is well within the limit of ADC specs.
2023-08-09 06:59 PM
Hello @ONadr.1 ,
Yes! That was indeed the case. I connected Vref+ to VDDA and everything works now. Honestly, at the time of designing, I couldnt find much information regarding this in the datasheet, and I had an impression thet Vref+ is an output. Although it mentions:
On packages without VREF+ pin, VREF+ is internally connected with VDD, and the internal voltage reference buffer must be kept disabled (refer to datasheets for package pinout description).
Could you please point out where this information is provided in the datasheet or RM explicitly for 48-pin package for future reference?
Thank you for your kind support.
-Regards,
Munish
2023-08-10 01:56 AM
I have already solved this problem once. The user manual is quite sparse on detailed information and if you don't know how to interpret it, it's easy to overlook. At certain settings, the VREF+ pin behaves as an input for an external reference voltage or is set as an output of a selected reference voltage. This is set by the FREFBUF register. More information about setting VREFBUF is in RM0444 part. 17.3.