Skip to main content
Associate II
March 19, 2024
Solved

ADC in conjustion with DMA

  • March 19, 2024
  • 4 replies
  • 3968 views

Hi

I am facing an odd problem with ADC in conjunction with DMA on STM32L151V8T-A. 

I can see that it measures all three channels. However, the result of each channel is stored in the first element of my results array (Result[3]). 

Every time that the callback function is called the results of one out of three channels is stored in Result[0] element. It is as if the memory address is not increasing.

Can somebody help?

Best answer by mƎALLEm

I attached a project where I did 3 channels conversion in continuous mode with DMA on STM32L152D_EVAL board. Unfortunately, I don't have your board on hands.

The three converted channels are:

- Channel 31: potentiometer

- Channel 16: temperature sensor

- Channel 17: Vrefint

I tested the project with IAR, you can port it easily to CubeIDE with CubeMx.

As you can see in this screenshot, the data converted are arranged in the correct order.

SofLit_0-1711122362478.png

You can inspire from my project to find your issue.

Please select this answer if it does answer your question.

 

4 replies

ST Employee
March 19, 2024

Hello @Pejwaak,

Please, make sure in your DMA settings you have correctly enable the incrementing address of "Destination Address".

Feel free to share your settings :)

Kind Regards,

Gwénolé

PejwaakAuthor
Associate II
March 19, 2024

Hi

Thanks for getting to me. I am not writing the low level code. I am using HAL library and I assumed as long as I follow the working examples. It should do the same thing although this is a different STM32 microcontroller.

Here is the part of the code that runs it. I also use the call back function to sent the ADCFlag.

HAL_ADC_Start_DMA(&hadc, ADCArray, 3);
 HAL_TIM_Base_Start_IT(&htim2);
 /* USER CODE END 2 */

 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 /* USER CODE END WHILE */

 /* USER CODE BEGIN 3 */
 if(ADCFlag){
 ADCStat = HAL_ADC_GetState(&hadc);
 if(ADCStat == 0){
 ADCFlag = 0;
 HAL_ADC_Start_DMA(&hadc, ADCArray, 3);
 }
 
mƎALLEm
ST Technical Moderator
March 19, 2024

Hello,

Did you enable Scan mode?

SofLit_0-1710862082364.png

Did you enable Memory incrementation in DMA config as stated by @GwenoleB ?

SofLit_1-1710862158687.png

 

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.
PejwaakAuthor
Associate II
March 19, 2024

Hi

Yes, I have taken every standard step according to the examples. Like I said all channels are being sampled but at the end of the sequence only one channel is written to ACDArray[0] and the rest remain zero. then at then end of next sequence the values for another channel is written two ACDArray[0] and the rest remain zero. It is really odd. 

PejwaakAuthor
Associate II
March 19, 2024

Hi

Thanks it is a lo of line. I am going to put the relevant bits here. Hopefully it will work.

static void MX_ADC_Init(void)
{

/* USER CODE BEGIN ADC_Init 0 */

/* USER CODE END ADC_Init 0 */

ADC_ChannelConfTypeDef sConfig = {0};

/* USER CODE BEGIN ADC_Init 1 */

/* USER CODE END ADC_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;
hadc.Init.Resolution = ADC_RESOLUTION_10B;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc.Init.LowPowerAutoWait = ADC_AUTOWAIT_DISABLE;
hadc.Init.LowPowerAutoPowerOff = ADC_AUTOPOWEROFF_DISABLE;
hadc.Init.ChannelsBank = ADC_CHANNELS_BANK_A;
hadc.Init.ContinuousConvMode = ENABLE;
hadc.Init.NbrOfConversion = 3;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.DMAContinuousRequests = ENABLE;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_16CYCLES;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_6;
sConfig.Rank = ADC_REGULAR_RANK_3;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC_Init 2 */

/* USER CODE END ADC_Init 2 */

}

This is the configuration of ADC. The rest of the code is presented above. It is very simple. Start with DMA, set the flag by callback function, reset the flag and restart the ADC with DMA again. 

mƎALLEm
ST Technical Moderator
March 19, 2024

Could you please share your .ioc file?

PS: next time please use </> button to insert your code for source code readability.

 

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.
PejwaakAuthor
Associate II
March 22, 2024

Thanks very much for your kind helps. I will have a look at your project and will get back you asap.

mƎALLEm
ST Technical Moderator
March 20, 2024

Ok thanks. I will look at it by tomorrow or after and get back to you with a feedback

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.