I am trying to use ADC with 2 channels and DMA, but I only get 1 reading before the overrun bit gets set. Also the 1 reading is wrong, I am expecting a value of approx 2100, but I am getting around 70. I can see in the hadc->DR that the value are correct, but it is not transferred to the array somehow (adc_value in runADC200Hz function below).

here is the code I am using:

main.c

static void MX_ADC_Init(void)
{

/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
{
Error_Handler();
}
/** Configure for the selected ADC regular channel to be converted.
*/
{
Error_Handler();
}
/** Configure for the selected ADC regular channel to be converted.
*/
{
Error_Handler();
}
}

static void MX_DMA_Init(void)
{

/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();

/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

}


stm32f0xx_hal_msp.c

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
{

/* Peripheral clock enable */

__HAL_RCC_GPIOA_CLK_ENABLE();
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

{
Error_Handler();
}

}

}


stm32f0xx_it.c

void DMA1_Channel1_IRQHandler(void)
{
}

/**
* @brief This function handles ADC and COMP interrupts (COMP interrupts through EXTI lines 21 and 22).
*/
{
}


I am running the ADC every 5ms like this:

static uint32_t adc_value[2];

{
asm("nop");
}
}


After the first conversion these flags are set:

• End of sampling (EOSMP)
• End of conversion (EOC)
• End of sequence (EOS)

I have been setting up ADC with DMA several times before with no problems, but that was on F2 and F7. Strange thing is that I have access to another code which works for the exact same chip, with the exact same code I have written above. I have no idea where I should look and compare beyond those functions above. Any suggestion on what Im doing wrong here? I have tried every type of sampletime but it is the same result. thanks for any comments!

• try making your array uint16_t instead of uint32_t Jun 11, 2020 at 17:54
• @Ocanath unfortunately no difference Jun 12, 2020 at 12:03

You are repeatedly calling the ADC in DMA mode, yet you have configured it to run continuous conversion mode. Meaning it will never stop sampling, repeating the sequence until stopped.

If your goal is to sample at 200 Hz, change it to these:

hadc.Init.ContinuousConvMode = DISABLE;


And configure a timer to trigger the sampling sequence.

I forgot, you also need to qualify adc_value as volatile since it changes outside of the compilers knowledge (the dma changes it).

The static keyword is poorly named and actually means private in this context. It has no effect other than reducing scope.

• Thanks for comment. It made no difference unfortunately Jun 12, 2020 at 12:04
• My bad, it actually solved the overrun problem, I can now run more iterations, thansk!. But I am still not getting the correct value transfered from DR to my array Jun 12, 2020 at 12:26
• @hoddy make it volatile. Jun 12, 2020 at 12:55
• volatile didn't work. I checked the DMA register and nothing in the CCR1 is getting set, except for the channel enable bit. That's weird because I have checked that the HAL_ADC_MspInit() function is running Jun 12, 2020 at 13:13
• @hoddy check if the correct result is written in ADC->DR Jun 12, 2020 at 13:42

Regarding "hadc->DR that the value are correct, but it is not transferred to the array": There is a bug from cubeMX. These functions were generated in this order:

  MX_ADC_Init();
MX_DMA_Init();


but they are supposed to be:

  MX_DMA_Init();