Skip to main content
Patrick Morwald
Associate III
March 20, 2018
Question

STM32F4 ADC Scan conversion is not working.

  • March 20, 2018
  • 8 replies
  • 2072 views
Posted on March 20, 2018 at 16:09

Hi,

i have an ADC where i want to read multiple channels sequentially and than use this data. I read them every second or so, so i want to start the reading manually each time. But when its started it should read all the assigned channels. 

Unfortunately, with the configuration below, it only seems to read the first channel and not going through the sequence of channels. This is my initialization code:

ADC_ChannelConfTypeDef sConfig;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)

*/

hadc2.Instance = ADC2;

hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;

hadc2.Init.Resolution = ADC_RESOLUTION_12B;

hadc2.Init.ScanConvMode = ENABLE;

hadc2.Init.ContinuousConvMode = DISABLE;

hadc2.Init.DiscontinuousConvMode = DISABLE;

hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;

hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc2.Init.NbrOfConversion = 2;

hadc2.Init.DMAContinuousRequests = DISABLE;

hadc2.Init.EOCSelection = ADC_EOC_SEQ_CONV;

if (HAL_ADC_Init(&hadc2) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.

*/

sConfig.Channel = ADC_CHANNEL_12;

sConfig.Rank = 1;

sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;

if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.

*/

sConfig.Channel = ADC_CHANNEL_13;

sConfig.Rank = 2;

if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

And this is my loop where i call a reading and the callback function:

while (1)

{

HAL_ADC_Start_IT(&hadc2);

HAL_Delay(4000);

}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef * hadc){

if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC))

{

// ADC_raw[0] = HAL_ADC_GetValue(hadc);

if (indexer < 2){

ADC_raw[indexer] = HAL_ADC_GetValue(hadc);

indexer++;

}

else {

vdd_a = ((float)ADC_raw[0] * 3.3) / 4095;

}

}

}

Please help.

#adc-scan-continuous #adc #stm32f4
This topic has been closed for replies.

8 replies

Tesla DeLorean
Guru
March 20, 2018
Posted on March 20, 2018 at 16:47

Scan mode would typically use DMA into an array, I've posted clear and simple SPL examples of this, the HAL is a circuitous fuster cluck, but might be some workable examples under the code trees.

Normally you'd use a TIM to directly trigger the ADC at 1Hz, and review both samples in the DMA TC interrupt.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Patrick Morwald
Associate III
March 20, 2018
Posted on March 20, 2018 at 17:13

Hi, thanks for the answer. I dont want to use a TC interrupt, since this 1s interval is just an example. In reality i have a high level software module that initiates the measurements.

I measure two channels at rather low frequency so i am not sure if DMA is necessary? If you say the scan function is not easily achievable with HAL (maybe HAL has missing features here..) what would be the easiest solution to do it (no polling though)

Regards,

Patrick

Tesla DeLorean
Guru
March 20, 2018
Posted on March 20, 2018 at 17:58

ST's multiple sample methodology is heavily predicated on the use of DMA, due to the potentially rapid rate of sample delivery, and the ability to get out of sequence in the overrun case. The module does not output any rank data, it just cycles. Many people have wasted a lot of time on the EOC approach. The DMA TC is the equivalent to EOC-on-ALL, if you can spin on ADC EOC you can spin on DMA TC. Or use the IRQ, or call-backs that they initiate.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Bill Dempsey
Associate III
March 21, 2018
Posted on March 21, 2018 at 04:43

I do something very similar to what you are doing but I start off from a timer vs software (your method should be fine...)

After the sequence runs I get an interrupt and retrigger and go again from the main code.   Look at my conv complete routine -- that is where I flag the restart for the main code.  

Here are the only lines that appear different. 

hadc2.Init.DiscontinuousConvMode = ENABLE;

adc2.Init.NbrOfDiscConversion   = 1;

hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)

{

/* Get the converted value of regular channel */

adcStatus[loopct] = AdcHandle->Instance->SR;

if(adcStatus[loopct] & 0x20)

{

HAL_ADC_ErrorCallback(AdcHandle);

return;

}

adcCapture[loopct] = HAL_ADC_GetValue(AdcHandle);

loopct++; intCount++;

if(loopct >= ADC_NUM_CHAN)

{

loopct=0;

}

restartADC = true;

}

New.Fish
Associate III
August 27, 2018

The F4 examples only has one ADC channel, what will happen if has multiply channel.

In Scan Mode, for multiply channel, there is only one ADC_SR register, one ADC_DR register, if EOC interrupt occurs, how can read each channel's converted data?

HAL_ADC_GetValue(hadc) only return the channel with "sConfig.Rank = 1" ?