AnsweredAssumed Answered

STM32F103 ADC + DMA multichannel, from FreeRTOS software timer. Continuous mode works. Manually triggering HAL_ADC_Start_DMA() return HAL_ERROR on ADC_Enable() on second call

Question asked by borgonovo.ivan_sergi on Feb 21, 2018



I've successfully run a FreeRTOS program that use ADC + DMA in scan, continuous, circular mode and I successfully can average in HAL_ADC_ConvCpltCallback().


Now I'd still like to use DMA to fill a buffer of 3 channels x 8 conversions but I'd like to start the conversion from  a FreeRTOS software timer.

So I'd expect that I start the DMA from a software timer, once the hardware has finished it stops conversions and HAL_ADC_ConvCpltCallback() get called, I average results and wait another software timer restart the conversion.


I've tried to disable continuous mode, to run DMA in REGULAR mode vs CIRCULAR... but every time I try, the second time HAL_ADC_Start_DMA() get called I get an HAL_ERROR from ADC_Enable().


This works continuously if I just call HAL_ADC_Start_DMA() once.


uint16_t ADCraw[ADCSamples][ADCChannels];


    hadc1.Instance = ADC1;
    hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
    hadc1.Init.ContinuousConvMode = ENABLE;
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc1.Init.NbrOfConversion = 3;


        hdma_adc1.Instance = DMA1_Channel1;
        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;


HAL_ADC_Start_DMA(&hadc1, (uint32_t*) ADCraw, ADCChannels * ADCSamples);