cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F730xx ADC: EOC never set when reading VREFINT

rengl
Associate II

Hello,

we want to read VREFINT to make our ADC measurements more accurate.

But the EOC bit is never set when selecting the ADC_CHANNEL_VREFINT channel.

PCLK2 is at 108MHz but ADC prescaler and sampling cycles are at max. so we assume there is no problem with the min. 10us sampling time.

The code below works for normal channels.

void MX_ADC1_Init(void)
{
    hadc1.Instance = ADC1;
    hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;
    hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
    hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    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;
    if (HAL_ADC_Init(&hadc1) != HAL_OK)
        Error_Handler();
}
 
uint8_t MX_ADC_Read(ADC_HandleTypeDef *hadc, uint32_t channel, uint32_t *val)
{
    ADC_ChannelConfTypeDef sConfig = {};
    sConfig.Channel = channel;
    sConfig.Rank = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    sConfig.Offset = 0;
 
    if (!hadc)
        return 0;
 
    if (!val)
        return 0;
 
    if (HAL_ADC_ConfigChannel(hadc, &sConfig) != HAL_OK)
        return 0;
 
    if (HAL_ADC_Start(hadc) != HAL_OK)
        return 0;
 
    if (HAL_ADC_PollForConversion(hadc, 100) != HAL_OK)
        return 0;
 
    *val = HAL_ADC_GetValue(hadc);
 
    HAL_ADC_Stop(hadc);
 
    return 1;
}

Here how we call MX_ADC_Read.

uint32_t val;
if (!MX_ADC_Read(&hadc1, ADC_CHANNEL_VREFINT, &val))
    Error_Handler();

Any idea what the problem could be?

Thanks

rengl

1 ACCEPTED SOLUTION

Accepted Solutions
rengl
Associate II

Now it works!

I have found two errors:

1. __HAL_RCC_ADC1_CLK_ENABLE() was not called. So ADC1 never worked with my posted code, I confused that with ADC3

2. There was a wrong configuration in SystemClock_Config() because the code was ported from an STM32F722 which used some other peripherals. This somehow never caused problems until now

Thanks again for your help!

View solution in original post

6 REPLIES 6
Kamil Duljas
Senior III

HAL_ADC_PollForConversion(hadc, 100) <--- try change 100 on HAL_MAX_DELAY and you will see if there is a difference

Dudo
rengl
Associate II

Thanks for the tip, but unfortunately this results in an infinite loop. At least EOC was not set even after 2 minutes.

Kamil Duljas
Senior III

It's weird. I have nucleo F7, set 108 Mhz , 480 cycles and others like you and works without problems. Maybe share your code?


_legacyfs_online_stmicro_images_0693W00000bixHvQAI.png

Dudo
LCE
Principal

Maybe try to enable DiscontinuousConvMode

hadc1.Init.DiscontinuousConvMode = ENABLE;

And always reset sConfig:

ADC_ChannelConfTypeDef sConfig = { 0 };

I have it running on STM32F767, but in sequence mode with DMA:

uint8_t ADC1InitStartDma(void)
{
	/* 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_DIV8;
	hadc1.Init.Resolution 				= ADC_RESOLUTION_12B;
	hadc1.Init.DataAlign 				= ADC_DATAALIGN_RIGHT;
	hadc1.Init.ScanConvMode 			= ADC_SCAN_ENABLE;
	hadc1.Init.ContinuousConvMode 		= ENABLE;
	hadc1.Init.DiscontinuousConvMode 	= DISABLE;
	hadc1.Init.ExternalTrigConvEdge 	= ADC_EXTERNALTRIGCONVEDGE_NONE;
	hadc1.Init.ExternalTrigConv 		= ADC_SOFTWARE_START;
	hadc1.Init.NbrOfConversion 			= ADC_CHNL_MAX;
	hadc1.Init.DMAContinuousRequests 	= ENABLE;
	hadc1.Init.EOCSelection 			= ADC_EOC_SEQ_CONV;
 
	if( HAL_ADC_Init(&hadc1) != HAL_OK ) Error_Handler_FL(__FILE__, __LINE__);
 
	/* ADC1 DMA Init */
	hdma_adc1.Instance 				= DMA2_Stream0;
 
	hdma_adc1.Init.Channel 			= DMA_CHANNEL_0;
	hdma_adc1.Init.Direction 			= DMA_PERIPH_TO_MEMORY;
	hdma_adc1.Init.PeriphInc 			= DMA_PINC_DISABLE;
	hdma_adc1.Init.MemInc 				= DMA_MINC_ENABLE;
	hdma_adc1.Init.PeriphDataAlignment 	= DMA_PDATAALIGN_HALFWORD;
	hdma_adc1.Init.MemDataAlignment 	= DMA_MDATAALIGN_HALFWORD;
	hdma_adc1.Init.Mode 				= DMA_CIRCULAR;
	hdma_adc1.Init.Priority 			= DMA_PRIORITY_LOW;
	hdma_adc1.Init.FIFOMode 			= DMA_FIFOMODE_ENABLE;
	hdma_adc1.Init.FIFOThreshold 		= DMA_FIFO_THRESHOLD_FULL;
	hdma_adc1.Init.MemBurst 			= DMA_MBURST_SINGLE;
	hdma_adc1.Init.PeriphBurst 			= DMA_PBURST_SINGLE;
 
	if( HAL_DMA_Init(&hdma_adc1) != HAL_OK ) Error_Handler_FL(__FILE__, __LINE__);
 
	__HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);
 
	/* set in dma.c for easier priority ordering */
	HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 9, 0);
	HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
 
	return HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC1DmaBuffer, ADC_DMA_BUF_SIZE);
}
 
 
 
/* DMA ISR */
void DMA2_Stream0_IRQHandler(void)
{
	HAL_DMA_IRQHandler(hadc1.DMA_Handle);
}
 
 
/**
  * @brief ADC1 channel struct init
  * @param None
  * @retval None
  */
void ADC1_channel_init(void)
{
	uint8_t i = 0;
	GPIO_InitTypeDef GPIO_InitStruct = { 0 };
	ADC_ChannelConfTypeDef sConfig = { 0 };
 
	sADC1chnls[0].channel 		= ADC_CHANNEL_VREFINT;
	sADC1chnls[0].iopin 		= ADC_CHNL_NO_GPIO;
	sADC1chnls[0].ioport 		= 0;
	sADC1chnls[0].multiplier 	= ADC_MULT_VREFI;
	sADC1chnls[0].u16Min 		= PWR_CHK_ADC_VREFI_LO;
	sADC1chnls[0].u16Max 		= PWR_CHK_ADC_VREFI_HI;
 
	sADC1chnls[1].channel 		= ADC_CHANNEL_TEMPSENSOR;
	sADC1chnls[1].iopin 		= ADC_CHNL_NO_GPIO;
	sADC1chnls[1].ioport 		= 0;
	sADC1chnls[1].multiplier 	= ADC_MULT_TEMPI;
	sADC1chnls[1].u16Min 		= PWR_CHK_ADC_TEMPI_LO;
	sADC1chnls[1].u16Max 		= PWR_CHK_ADC_TEMPI_HI;
 
 
	for( i = 0; i < ADC_CHNL_MAX; i++ )
	{
	/* GPIO */
		if( sADC1chnls[i].iopin != ADC_CHNL_NO_GPIO )
		{
			GPIO_InitStruct.Pin 	= sADC1chnls[i].iopin;
			GPIO_InitStruct.Mode 	= GPIO_MODE_ANALOG;
			GPIO_InitStruct.Pull 	= GPIO_NOPULL;
			HAL_GPIO_Init(sADC1chnls[i].ioport, &GPIO_InitStruct);
		}
 
	/* ADC channel */
		sConfig.Channel 		= sADC1chnls[i].channel;
		sConfig.Rank 			= i + ADC_REGULAR_RANK_1;
		sConfig.SamplingTime 	= ADC_SAMPLETIME_480CYCLES;	//ADC_SAMPLETIME_56CYCLES;
		sConfig.Offset 			= 0;
		if( HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK ) uart_printf("#ERR: HAL_ADC_ConfigChannel() sADC1chnls[%u]\n\r", i);
	}
}
 

rengl
Associate II

I have enabled DiscontinuousConvMode and reset the sConfig every time, but unfortunately no success.

I can't share the source code here.

But I created a minimal example with CubeMX similar to @Kamil Duljas​ and with this it works.

I will now compare the two projects and get back to you if I find the cause of the problem.

Thank you for your help!

rengl
Associate II

Now it works!

I have found two errors:

1. __HAL_RCC_ADC1_CLK_ENABLE() was not called. So ADC1 never worked with my posted code, I confused that with ADC3

2. There was a wrong configuration in SystemClock_Config() because the code was ported from an STM32F722 which used some other peripherals. This somehow never caused problems until now

Thanks again for your help!