cancel
Showing results for 
Search instead for 
Did you mean: 

Trouble with ADC on STM32G071G8U6 using HAL from STM32CubeMX

LZale.1
Associate

Hello all,

I've been having trouble with the ADC system on the STM32G071G8U6.  I'm using the STM32CubeMX to generate initialization code.  I have 5 external A/D inputs and it appears I am not getting readings anywhere near the real values, so I have switched to trying to just read the internal reference.  I hope that if I can get the internal reference or the temperature to read correctly, I'll be able to solve the problems with the external inputs.

My VDD is provided from a 2.5 volt LDO.  Looking at it with a DVOM, that looks accurate.

I am running the A/D at 12 bit resolution and my clcok prescaler is Synchronous clock mode divided by 2.  I have the sampling time set to the maximum available in Cube, 160.5 cycles.

I have a polling routine running every 1 second that reads all 5 external and all 3 internal channels.

I set the VREFEN and TSEN bits in the ADC CCR register at the end of init and leave them enabled.

I realize there may be board related problems with the external inputs.  However, even when I just try to read the internal inputs, the internal reference or the temperature, I see 0, 1, or 2 A/D counts.  

My periodic readings look like this, with some expected noise in the readings.  The value on the left is a timestamp, followed by the channel name, followed by the channel value in square braces, followed by the raw A/D value:


[ 1.007] ADC polling:
[ 1.014] Internal Temp Raw ADC[B0001000] =0
[ 1.016] Internal Vref Raw ADC[B4002000] =2
[ 1.017] Internal Vbat Raw ADC[B8004000] =1983

I would expect the internal temperature channel and the internal Vref channel to be the easiest to debug.  I assume there's some step I am missing...

The Cube generated ADC1 init routine is as follows:

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_DIV2;
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_160CYCLES_5;
hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_1CYCLE_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_VREFINT;
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 */

}

After all HAL initializations are completed, I run my ADC init routine:

void ADC_Init(void)
{
SET_BIT(ADC->CCR, ADC_CCR_VREFEN); 
SET_BIT(ADC->CCR, ADC_CCR_TSEN); 
HAL_ADCEx_Calibration_Start(&hadc1);
last_polling_tick = HAL_GetTick();
}

And then my actual readings are taken with this code:

uint32_t ADC_ReadChannel (uint32_t channel)
{
ADC_ChannelConfTypeDef sConfig = {0};
HAL_StatusTypeDef status;
uint32_t raw_adc = 4096;

// Configure the desired channel
sConfig.Channel = channel;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1; // Adjust as needed
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

// Do the reading
status = HAL_ADC_Start(&hadc1);

if (status == HAL_OK)
{
status = HAL_ADC_PollForConversion(&hadc1, ADC_TIMEOUT_mS);
}

if (status == HAL_OK)
{
raw_adc = HAL_ADC_GetValue(&hadc1);
}

HAL_ADC_Stop(&hadc1);

PRINT_APP_DBG_NO_TIME(" Raw ADC[%08lX] =%i\r", channel, raw_adc);

return (raw_adc);
}

I can't see what I'm missing that's causing the ADC_CHANNEL_VREFINT and ADC_CHANNEL_TEMPSENSOR values to always be near 0...

0 REPLIES 0