cancel
Showing results for 
Search instead for 
Did you mean: 

Multi channel ADC with DMA in circular mode using CubeMX and HAL, how do I use the half transfer complete and transfer complete callbacks?

Taylor Welsh
Associate II
Posted on June 29, 2018 at 03:03

I am using the STM32F091. I have been trying to use the ADC with DMA in circular mode writing to a large array for use as a sort of double buffer by shifting the first half of the values out on the half transfer complete callback the the other half on the transfer complete callback. However the documentation is super vague on what these callbacks are called and how they should be used.

Anybody know what these callbacks are called? How would I use them in my main to run code on a 

half transfer and transfer complete interrupt?

 
5 REPLIES 5
Posted on June 29, 2018 at 04:05

STM32Cube_FW_F0_V1.9.0\Projects\STM32F072RB-Nucleo\Examples\ADC\ADC_AnalogWatchdog\Src\main.c

/**

  * @brief  Conversion complete callback in non blocking mode

  * @param  AdcHandle : ADC handle

  * @note   This example shows a simple way to report end of conversion

  *         and get conversion result. You can add your own implementation.

  * @retval None

  */

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *AdcHandle)

{

}

/**

  * @brief  Conversion DMA half-transfer callback in non blocking mode

  * @param  hadc: ADC handle

  * @retval None

  */

void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)

{

}

STM32Cube_FW_F0_V1.9.0\Projects\STM32F072RB-Nucleo\Examples\ADC\ADC_AnalogWatchdog\Src\stm32f0xx_it.c

/**

* @brief  This function handles DMA interrupt request.

* @param  None

* @retval None

*/

void ADCx_DMA_IRQHandler(void)

{

  HAL_DMA_IRQHandler(AdcHandle.DMA_Handle);

}

>>How would I use them in my main to run code on a 

half transfer and transfer complete interrupt?

 

Honestly you'd want to do the work in the callback itself (memcpy ?), but if you want to do something in main(), have the callback flag via a 'volatile int'

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Taylor Welsh
Associate II
Posted on June 29, 2018 at 04:29

Do the 

HAL_ADC_ConvCpltCallback & 

HAL_ADC_ConvHalfCpltCallback trigger on the end of conversion/sequence flag or are they tied to the DMA transfer? 

What I am after, one way or another, is something that triggers when my buffer is half full/full. To keep overhead down that will likely be after 200 or more adc conversion sequences (of 8 channels so 1600 samples or more in the buffer). 

What I don't want is something that triggers after every conversion sequence (8 samples in buffer), I could probably make this work but I'd rather not have to deal with that overhead.

you're right it makes more sense to do the work in the callback.   

Posted on June 29, 2018 at 05:00

>>Do the 

HAL_ADC_ConvCpltCallback & 

HAL_ADC_ConvHalfCpltCallback trigger on the end of conversion/sequence flag or are they tied to the DMA transfer? 

I believe it is tied to the DMA, surely something trivially easy to prove.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
T J
Lead
Posted on June 29, 2018 at 07:04

I can help if you are stuck, I have this running on the '091.

typedef enum {

    Rs8_Ad1,   // initialised in the Cube

    Rs5_Ad5,

    Rs1_Ad6,

    Rs2_Ad7,

    Rs3_Ad8,

    Rs4_Ad9,

    CurrentSense_Ad13,

    Rs6_Ad14,

    Rs7_Ad15,

    VTemp_Ad16,

    VRef_Ad17,

    VBat_Ad18,

    ADC_ChannelCount,

} ADCresultsAveColumn_t;

    HAL_ADC_Start_DMA(&hadc, (uint32_t *)ADC_DMABuffer, ADC_ChannelCount);

I use this callback: I fill a row with this new set of DMAdata

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {  // transfer to 16 rows of data

        HAL_ADC_CompleteCycle = true;          // signal foreground to process

        // copy 15 results away now

        for(int i = 0 ; i < ADC_ChannelCount ; i++) {

            //here add 2nd dimension to the array

            HAL_ADC_Channel_Buffer[ADC_RowCounter][i] = ADC_DMABuffer[i];   // AVEColumnSum += HAL_ADC_Channel_Buffer [Ave_ADC_RowCounter][Ave_ADC_ChannelCounter];

        }

        ADC_RowCounter++;                              // for next time through the loop

        if(ADC_RowCounter >= ADC_RowCount) ADC_RowCounter = 0;        

}
Cyril FENARD
ST Employee
Posted on July 03, 2018 at 12:02

Hi

taylor.welsh

,

I share a participation to the following link: 

https://community.st.com/0D50X00009XkXZ3SAN

https://community.st.com/0D50X00009XkXZ3SAN

It gives some details on how callbacks are done in other ADC use-case.

Hoping this brings some help for your case also.

Regards.

Cyril