9
\$\begingroup\$

I am trying to learn how to use "new" HAL library from stm32.
When I try to do simple ADC conversion it works just one time, but then it stops converting. I suppose End of conversion flag does not get set. I am using STM32f429I Discovery board, which has STM32f429ZI on board.
Note that I know about sprintf being bad practice and making adc with interrupt is better, I know that, please don't point it out, this is not relevant to the question, I am just testing HAL here.
So the question is why EOC flag is not set or what could I do to make it work? Googling is not helping much since very few good materials about HAL out there.

Here is the code:

__IO uint16_t ADCValue=0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);

int main(void)
{
  char str[15];

  /* Various initializations */

  HAL_ADC_Start(&hadc1);
  while (1)
  {

        if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
        {
            ADCValue = HAL_ADC_GetValue(&hadc1);
            sprintf(str, "%d", ADCValue);
            BSP_LCD_DisplayStringAt(130,30, (uint8_t*)str, LEFT_MODE);
        }

  }

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    ADCValue = HAL_ADC_GetValue(&hadc1);
}

I also created the project with CubeMX, adc configuration is the following: enter image description here

EDIT 1
I tried to debug everything and it seems that program gets stuck into checking for EOC flag - it sees that it is not shown and therefore issues timer waiting for EOC to show up(but it never gets set) Here is the code where it gets stuck in debugger:

/* Check End of conversion flag */
  while(!(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC)))
  {
    /* Check for the Timeout */
    if(Timeout != HAL_MAX_DELAY)
    {
      if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
      {
        hadc->State= HAL_ADC_STATE_TIMEOUT;
        /* Process unlocked */
        __HAL_UNLOCK(hadc);
        return HAL_TIMEOUT;
      }
    }
\$\endgroup\$
6
\$\begingroup\$

In your original code, set the End of Conversion Selection to disabled.

 hadc1.Init.EOCSelection = DISABLE;

It turned out that #define ADC_EOC_SEQ_CONV ((uint32_t)0x00000000) value is equal to DISABLE. So actually the EOCSelection should be configured as: enter image description here
to be able to poll the ADC multiple times.

Then you can read the ADC continously without stopping and starting the ADC:

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    ConfigureADC();

    HAL_ADC_Start(&hadc1);
    while(1)
    {
        if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
        {
            ADCValue = HAL_ADC_GetValue(&hadc1);
        }
    }
}

This way it worked fine for me.

Since HAL is a quite new library there are not a lot of resources to be find but not impossible. I learned a lot from this tutorial, it demonstrates all possible ADC useage step by step; from simple polling, to using interrupts and DMA.

\$\endgroup\$
  • \$\begingroup\$ hm... disabling EOCSelection makes it work, but from the definition of it it says - Specifies whether the EOC flag is set at the end of single channel conversion or at the end of all conversions. Disabling this should not help by definition.. but it helps.... confusing. Do you know why exactly disabling this makes it work? thanks for the answer anyway \$\endgroup\$ – ScienceSamovar Nov 26 '15 at 23:13
  • \$\begingroup\$ I am just learning HAL too, so I do not know the reason yet. It is just an experience. I found that HAL can be consfuing so many times. \$\endgroup\$ – Bence Kaulics Nov 26 '15 at 23:25
  • \$\begingroup\$ I have checked the define values and #define ADC_EOC_SEQ_CONV ((uint32_t)0x00000000) which is same as disabled, so disabled is actually ADC_EOC_SEQ_CONV. \$\endgroup\$ – Bence Kaulics Nov 26 '15 at 23:43
  • 1
    \$\begingroup\$ oh, ok, so it is not literally disabled. It makes sense, previously it was ADC_EOC_SINGLE_CONV which probably means just that - it converts just one time, and ADC_EOC_SEQ_CONV is continuous conversion. One more mystery solved :) Thanks! \$\endgroup\$ – ScienceSamovar Nov 26 '15 at 23:49
  • \$\begingroup\$ Yes, that should be the case. :) \$\endgroup\$ – Bence Kaulics Nov 26 '15 at 23:55
2
\$\begingroup\$

Hm... I found couple of tutorials that used HAL_ADC_Stop(&hadc1) to end the convertion... I was looking at these tutorials before and thought that this is rather barbaric way, seems it disables ADC completely, so I though there should be different method. But it seems, that this actually works well.
Be welcome to post answer if there is more elegant way of doing this, since I think using HAL_ADC_Stop() is pretty awful, but can be used for learning purposes.

while (1)
  {
        HAL_ADC_Start(&hadc1);
        if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
        {
            ADCValue = HAL_ADC_GetValue(&hadc1);
                        sprintf(str, "%d", ADCValue);
                        BSP_LCD_DisplayStringAt(130,30, (uint8_t*)str, LEFT_MODE);
        }
        HAL_ADC_Stop(&hadc1);

  }
\$\endgroup\$
2
\$\begingroup\$

I would like to add that for my setup (nucleo-h743) it was not enough to set:

hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;

I also had to enable the overrun setting as well:

hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;

Without this the HAL_ADC_PollForConversion was still blocking. I do not fully understand why this was necessary but it does allow me to poll in continuous mode.

\$\endgroup\$
0
\$\begingroup\$

This works for me, hope it will help:

if (HAL_ADC_Start(&hadc) != HAL_OK)
{
    /* Start Conversation Error */
    // Error_Handler();
}
if (HAL_ADC_PollForConversion(&hadc, 500) != HAL_OK)
{
    /* End Of Conversion flag not set on time */
    // Error_Handler();
    ADCValue=-1;
}
else
{
    /* ADC conversion completed */
    /*##-5- Get the converted value of regular channel ########################*/
    ADCValue = HAL_ADC_GetValue(&hadc);
}
HAL_ADC_Stop(&hadc);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.