cancel
Showing results for 
Search instead for 
Did you mean: 

ADC with DMA in discontinuous mode samples first rank twice (STM32F103)

FDrab.1
Associate II

Hi,

I want to use an ADC with DMA in a STM32F103. I configured it in Cube as you can see in the following picures.

When I start the conversion with

HAL_ADC_Start_DMA(&hadc1,(uint32_t*)AdcData,5);

HAL_ADC_ConvCpltCallback() is called and I see that the AdcData values all changed.

Unfortunately the first rank is sampled twice and the last rank is lost.

I tried to extend the DMA length to 6 but then I do not receive the callback.

I tried to extend the DMA length to 4 but then the last AdcData is unchanged.

Has anybody an idea why this happens and how I can get rid of this?

0693W000001s5D7QAI.jpg0693W000001s595QAA.jpg0693W000001s590QAA.jpg

1 ACCEPTED SOLUTION

Accepted Solutions
FDrab.1
Associate II

Now I found out that the false ADC conversion is triggered by setting the DMA bit when it is already set. Somehow the HAL does not clear this bit at the end of conversion.

I added

hadc1.Instance->CR2 &= ~ADC_CR2_DMA;

to my code after the conversion finished and now it works as expected.

But this is not a good solution.

EDIT:

I now searched for the ADC_CR2_DMA bi in the HAL source file and found

CLEAR_BIT(hadc->Instance->CR2, ADC_CR2_DMA);

only in HAL_ADC_Stop_DMA();

So I have to call HAL_ADC_Stop_DMA() before I can call HAL_ADC_Start_DMA() again?

EDIT:

Nope, calling HAL_ADC_Stop_DMA() causes a DMA_ERROR since the transfer finished already regularly.

Calling HAL_ADC_Init() does not solve this problem either. It does not clear the DMA flag.

So, STM, please review this issue for purpose..

View solution in original post

11 REPLIES 11

Read out and check/post the ADC registers content.

JW

FDrab.1
Associate II

Find attached the ADC and DMA registers.

Please note: I use the generated code only. No modifications..

FDrab.1
Associate II

I just found out, that the first sequence is correct (no double data). The second and following sequences are wrong...

Discontinuous mode is intended to convert a subgroup of the sequence defined in ADC_SQRx. But you set DISCNUM to the same value as ADC_SQR1.L. That doesn't make sense, so just simply don't set DISCEN.

JW

FDrab.1
Associate II

Hello JW. Thanx for your answer.

Though your answer sounds feasible it doesn't solve my problem.

I set discontinuous mode to "disabled" and regenerated the code.

What I now see is that in the second scan cycle the DMA waits endlessly for data.

I debugged into the HAL and saw, that setting the DMA bit in ADC_CR2 causes the ADC to execute a conversion! This is later the unwanted data..

     /* Enable ADC DMA mode */

     SET_BIT(hadc->Instance->CR2, ADC_CR2_DMA); // line 1643 of \STM32CubeMX\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_adc.c

Stupid question: What functions should I call to use this ADC in a SW triggered sequence mode?

I do:

  • MX_ADC1_Init()
  • HAL_ADCEx_Calibration_Start()
  • HAL_ADC_Start_DMA()
  • HAL_ADC_Start_DMA()
  • HAL_ADC_Start_DMA()
  • ...

Do I need to reinilialize the ADC between HAL_ADC_Start_DMA()?

FDrab.1
Associate II

Now I found out that the false ADC conversion is triggered by setting the DMA bit when it is already set. Somehow the HAL does not clear this bit at the end of conversion.

I added

hadc1.Instance->CR2 &= ~ADC_CR2_DMA;

to my code after the conversion finished and now it works as expected.

But this is not a good solution.

EDIT:

I now searched for the ADC_CR2_DMA bi in the HAL source file and found

CLEAR_BIT(hadc->Instance->CR2, ADC_CR2_DMA);

only in HAL_ADC_Stop_DMA();

So I have to call HAL_ADC_Stop_DMA() before I can call HAL_ADC_Start_DMA() again?

EDIT:

Nope, calling HAL_ADC_Stop_DMA() causes a DMA_ERROR since the transfer finished already regularly.

Calling HAL_ADC_Init() does not solve this problem either. It does not clear the DMA flag.

So, STM, please review this issue for purpose..

> I debugged into the HAL and saw, that setting the DMA bit in ADC_CR2 causes the ADC to execute a conversion!

I don't think so. Why do you think it does?

What's exactly the value written into ADC_CR2?

Does the ADC_SR register indicate a conversion (EOC being set after being 0)?

I don't Cube/HAL, and I personally would write this thing using register access, avoiding confusion stemming from Cube/HAL.

JW

Hi JW,

why I think setting the DMA bit causes a conversion?

I set a breakpoint to the line where the ADC_CR2_DMA bit is set. Then I reset all registers of the ADC and DMA to the values they had at the first cycle at exactly this location. When I now steped over the code which sets the DMA bit

  • the ADC data register content changes,
  • the EOC flag goes from 0 to 1
  • and the DMA transaction counter decreases..

So I'm quite sure that an ADC conversion is executed when the DMA bit is written by 1 when it already was 1 before.

I will ask a STM supporter to review this..

Breakpoint stops the processor but not the peripherals, they continue to work. Whether changes in register values during this time are reflected in the displayed values, depend on the toolchain.

>Then I reset all registers of the ADC and DMA to the values they had at the first cycle at exactly this location. 

What exactly do you do? Doesn't this start an ADC conversion?

JW