Saturday 26 October 2019

microcontroller - STM32 ADC conversion using HAL


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;
}

}

Answer



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.


No comments:

Post a Comment

arduino - Can I use TI's cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...