2023-04-27 01:52 AM
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
Solved! Go to Solution.
2023-04-27 07:46 AM
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!
2023-04-27 02:09 AM
HAL_ADC_PollForConversion(hadc, 100) <--- try change 100 on HAL_MAX_DELAY and you will see if there is a difference
2023-04-27 02:46 AM
Thanks for the tip, but unfortunately this results in an infinite loop. At least EOC was not set even after 2 minutes.
2023-04-27 03:11 AM - edited 2023-11-20 06:58 AM
It's weird. I have nucleo F7, set 108 Mhz , 480 cycles and others like you and works without problems. Maybe share your code?
2023-04-27 03:20 AM
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);
}
}
2023-04-27 06:12 AM
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!
2023-04-27 07:46 AM
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!