cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F3 two ADC with DMA transferred data mixup [SOLVED]

leonardo2
Associate II
Posted on November 22, 2016 at 09:43

Hallo,

I am trying to solve this problem that I am facing with ADC and DMA use.

I use a STM32F303 Microcontroller, with CubeMX vers4.17 and Eclipse.

I was able to test and use all the peripherals I needed but I encountered problems with the ADC and DMA.

I use the internal Opamps and I want to sample the two analog signals coming from Opamps with ADC1 and ADC3.

I followed the tutorial 

http://tunizem.blogspot.de/2014/09/using-adc-with-dma-on-stm32.html

And with this I was able to succesfully enable ADC1 and sample using DMA1, with the TIMER3 configured as trimmer.

Then I tryed only with the other channel, I was able to succesfully enable ADC3 and sample using DMA2 (again with TMR3).

The problems come out when I use the two configurations together: the DMA1 buffer is filled with both data coming from ADC1 and data coming from ADC3!! This doesn't happen with the buffer of DMA2 in which the sampled data are still correct.

I checked the data both through sending them undersampled through UART to the computer and with DEBUG checking the whole buffer contents.

I checked the frequency of the IRQ of TMR3, DMA1 and DMA2 and they are all correct and the same.

I also tried with another board to sample ADC1 and ADC4 and the problem happens again but this time I get in the DMA2 buffer (which is connected to ADC4) data coming from ADC1.

I think that it could be some wrong settings but I was not able to figure out which.

If somebody have some ideas or suggestions it would be really helpful!

thank you very much in advance!

regards

-------------------------

Here's the code:

&sharpdefine DMA1_ARRAY_LEN 30

&sharpdefine DMA2_ARRAY_LEN 30

int main(void)

{

/* USER CODE BEGIN 1 */

uint32_t DMA1_error, DMA2_error;

char str[32];

/* USER CODE END 1 */

/* MCU Configuration----------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

HAL_Init();

/* Configure the system clock */

SystemClock_Config();

/* Initialize all configured peripherals */

MX_GPIO_Init();

MX_DMA_Init();

MX_ADC1_Init();

MX_ADC3_Init();

MX_OPAMP1_Init();

MX_OPAMP2_Init();

MX_OPAMP3_Init();

MX_OPAMP4_Init();

MX_SPI2_Init();

MX_TIM3_Init();

MX_USART1_UART_Init();

/* USER CODE BEGIN 2 */

LED_OFF(LED_GREEN_Pin);

LED_OFF(LED_RED_Pin);

HAL_OPAMP_Start(&hopamp1);

HAL_OPAMP_Start(&hopamp2);

HAL_OPAMP_Start(&hopamp3);

HAL_OPAMP_Start(&hopamp4);

SensorPower_ON();

// -- Enables ADC DMA request

if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC1ConvertedValues, 2*DMA1_ARRAY_LEN) != HAL_OK)

return 0;

if (HAL_ADC_Start_DMA(&hadc3, (uint32_t*)ADC3ConvertedValues, 2*DMA2_ARRAY_LEN) != HAL_OK)

return 0;

// Enable Timer3

HAL_TIM_Base_Start(&htim3);

/* USER CODE END 2 */

/* Infinite loop */

/* USER CODE BEGIN WHILE */

while (1)

{

HAL_Delay(1);

DMA1_error = HAL_DMA_GetError(&hdma_adc1);

DMA2_error = HAL_DMA_GetError(&hdma_adc3);

sprintf(str, ''$%d %d;'', ADC1ConvertedValues[1], ADC3ConvertedValues[1]); // serial port plotter viewer

UART_return = HAL_UART_Transmit(&huart1, str, strlen(str), 1000);

// Toggle green LED

SysTick_Counter++;

if (SysTick_Counter == 700)

LED_ON(LED_GREEN_Pin);

if (SysTick_Counter == 800)

LED_OFF(LED_GREEN_Pin);

if (SysTick_Counter == 900)

LED_ON(LED_GREEN_Pin);

if (SysTick_Counter == 1000)

{

LED_OFF(LED_GREEN_Pin);

SysTick_Counter = 0;

}

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}

/* USER CODE END 3 */

}

#stm32f3 #dma #adc
1 ACCEPTED SOLUTION

Accepted Solutions
leonardo2
Associate II
Posted on November 25, 2016 at 09:08

I solved the problem this way, I changed this line(s) in the code:

HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC1ConvertedValues, 2048)

to this

HAL_ADC_Start_DMA(&hadc1, ADC1ConvertedValues, 1024)

bye

View solution in original post

3 REPLIES 3
leonardo2
Associate II
Posted on November 25, 2016 at 09:08

I solved the problem this way, I changed this line(s) in the code:

HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC1ConvertedValues, 2048)

to this

HAL_ADC_Start_DMA(&hadc1, ADC1ConvertedValues, 1024)

bye

Jeremy Labrado
Associate II
Posted on January 05, 2017 at 02:07

Hi Ole56,

I am trying to read 2 ADCs simultaneouslylike you with a unique Timmer, but all in the same buffer DMA. 

This looks like what you had when you had the problem.

Can you send me the configuration of your ADCs and DMA please. Maybe, the IRQ can be usefull as well.

Thanks,

Jeremy

leonardo2
Associate II
Posted on January 05, 2017 at 09:54

Hi Jeremy,

Here are the configurations. What I can tell you is that in my situation the data were saved randomly in the same array, unfortunately there was no logic, no divisio between the two channels.

/* ADC1 init function */

static void MX_ADC1_Init(void)

{

ADC_ChannelConfTypeDef sConfig;

/**Common config

*/

hadc1.Instance = ADC1;

hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;

hadc1.Init.Resolution = ADC_RESOLUTION_12B;

hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;

hadc1.Init.ContinuousConvMode = DISABLE;

hadc1.Init.DiscontinuousConvMode = DISABLE;

hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;

hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;

hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc1.Init.NbrOfConversion = 3;

hadc1.Init.DMAContinuousRequests = ENABLE;

hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

hadc1.Init.LowPowerAutoWait = DISABLE;

hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;

if (HAL_ADC_Init(&hadc1) != HAL_OK)

{

Error_Handler();

}

/**Configure Regular Channel

*/

sConfig.Channel = ADC_CHANNEL_3;

sConfig.Rank = 1;

sConfig.SingleDiff = ADC_SINGLE_ENDED;

sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;

sConfig.OffsetNumber = ADC_OFFSET_NONE;

sConfig.Offset = 0;

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

{

Error_Handler();

}

/**Configure Regular Channel

*/

sConfig.Channel = ADC_CHANNEL_1;

sConfig.Rank = 2;

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

{

Error_Handler();

}

/**Configure Regular Channel

*/

sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;

sConfig.Rank = 3;

sConfig.SamplingTime = ADC_SAMPLETIME_61CYCLES_5;

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

{

Error_Handler();

}

}

/* ADC3 init function */

static void MX_ADC3_Init(void)

{

ADC_ChannelConfTypeDef sConfig;

/**Common config

*/

hadc3.Instance = ADC3;

hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;

hadc3.Init.Resolution = ADC_RESOLUTION_12B;

hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE;

hadc3.Init.ContinuousConvMode = DISABLE;

hadc3.Init.DiscontinuousConvMode = DISABLE;

hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;

hadc3.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;

hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc3.Init.NbrOfConversion = 1;

hadc3.Init.DMAContinuousRequests = ENABLE;

hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

hadc3.Init.LowPowerAutoWait = DISABLE;

hadc3.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;

if (HAL_ADC_Init(&hadc3) != HAL_OK)

{

Error_Handler();

}

/**Configure Regular Channel

*/

sConfig.Channel = ADC_CHANNEL_1;

sConfig.Rank = 1;

sConfig.SingleDiff = ADC_SINGLE_ENDED;

sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;

sConfig.OffsetNumber = ADC_OFFSET_NONE;

sConfig.Offset = 0;

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

{

Error_Handler();

}

}

/**

* Enable DMA controller clock

*/

static void MX_DMA_Init(void)

{

/* DMA controller clock enable */

__HAL_RCC_DMA2_CLK_ENABLE();

__HAL_RCC_DMA1_CLK_ENABLE();

/* DMA interrupt init */

/* DMA1_Channel1_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

/* DMA2_Channel5_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA2_Channel5_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(DMA2_Channel5_IRQn);

}

Then in HAL_ADC_Start_DMA() you will find how DMA is used.

Hope this helps!

bye

Ole