Skip to main content
Associate II
May 3, 2026
Solved

ADC encounters issues with continuous conversion using GPDMA

  • May 3, 2026
  • 3 replies
  • 509 views

The board I am using is NUCLEO-H7S3 and I have encountered the following issues
I want to perform continuous and large data sampling using ADC+DMA, but when the collected value reaches 10000, the subsequent values become 0. When I modify the number of collected values to 50000, it stops at 17231 and the subsequent values remain 0. At this point, I am connecting the ADC pin to the 3.3V on the board. I'm not sure where the settings went wrong, please help me.
Thank you.

MECHO_0-1777792518463.pngMECHO_1-1777792548684.png

MECHO_5-1777792897527.png

 

MECHO_3-1777792847325.png

MECHO_2-1777792733760.png

MECHO_4-1777792869805.png

 

 

 

Best answer by MECHO

Hello, after testing, there is still an issue. After careful debugging, it was found that the number of data transferred by GPDMA is counted in bytes. If it is detected as half word in the quantity processing, the value originally filled in will be multiplied by 2, and the maximum length is 65535. After actual testing, if the collected data is less than 32376, there will be no data abnormalities. Once it exceeds, an ADC acquisition error will be triggered. So the essence of the problem is that the amount of data transferred by DMA exceeds 32768, rather than being unable to access the corresponding memory area.

 /* Length should be converted to number of bytes */
 if (node_conf.Init.SrcDataWidth == DMA_SRC_DATAWIDTH_WORD)
 {
 /* Word -> Bytes */
 length_bytes = Length * 4U;
 }
 else if (node_conf.Init.SrcDataWidth == DMA_SRC_DATAWIDTH_HALFWORD)
 {
 /* Halfword -> Bytes */
 length_bytes = Length * 2U;
 }
 else /* Bytes */
 {
 /* Same size already expressed in Bytes */
 length_bytes = Length;
 }

 

3 replies

MM..1
Chief III
May 3, 2026

Seems your array is out of DMA access memory. You need more learning about RAM areas and DMA.

And dont insert images of code to forum, Instead use 

uint16_t ADCDATA1[200000];

and in linker script place it into riht region usw.

MECHOAuthor
Associate II
May 3, 2026

Thank you for your reply. I didn't understand what you were saying, but I noticed that the compiler assigned the address 0x2400008c to this array. Could you please provide a more detailed explanation.
My subsequent code will reply in the format you provided
Thanks

AScha.3
Super User
May 3, 2026

Hi,

but when the collected value reaches 10000, the subsequent values become 0

You start DMA here to get 10000 values , then wonder, why it stops at 10000 ?   :)

HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADCDATA1,10000);

+

>I want to perform continuous and large data sampling

So set the DMA to circular mode, on somewhat smaller array, to use the data in half-/full callbacks;

then you can get a continuous decoded (or whatever...) stream of data, as long as you let the DMA running.

"If you feel a post has answered your question, please click ""Accept as Solution""."
MECHOAuthor
Associate II
May 3, 2026

Thank you for your answer. I intended to collect 200000 data points, but DMA can only collect up to 65535 data points at a time. I originally planned to collect 200000 pieces of data first, and then have the computer analyze it, but it has been unable to accurately collect voltage. So I narrowed down the scope for analysis and discovered this problem. The above is my test code, and the problem is consistent with what I found before

/* USER CODE BEGIN PV */

int adcEnd = 0;
uint16_t ADCDATA1[200000];
int end = 0;
/* USER CODE END PV */
si5351aSetFrequency(968000000 , 0 );
 HAL_TIM_Base_Start_IT(&htim7);
 HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
 HAL_TIM_Base_Start(&htim6);
 HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADCDATA1,10000);
 int data;
 /* USER CODE END 2 */

 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 if(end == 1)
 {
 for (int i = 0; i < 200000; i++) 
 {
 data = 3300 * ADCDATA1[i] /4096;
 printf("%dmv-%d\r\n",data,i);
 }
 while (1)
 {
 ;
 }
 }
 /* USER CODE END WHILE */

 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
 adcEnd++;
 if (adcEnd < 3) 
 {
 HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADCDATA1[10000 * adcEnd], 10000);
 }
 else 
 {
 HAL_ADC_Stop(&hadc1);
 end = 1;
 }
 
}
AScha.3
Super User
May 3, 2026

Did you enable the callback ?

AScha3_0-1777808826021.png

Just set a breakpoint in the callback, to see its called .

+

Why not on circular mode ? Is the standard way, for continuous data stream.

 

"If you feel a post has answered your question, please click ""Accept as Solution""."
Visitor II
May 10, 2026

I havent understood

AScha.3
Super User
May 12, 2026

Simply: you should use cicular mode . All these problems solved then.

As i said in my first post...

"If you feel a post has answered your question, please click ""Accept as Solution""."